1 /*
  2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_JFR_RECORDER_STORAGE_JFREPOCHSTORAGE_INLINE_HPP
 26 #define SHARE_JFR_RECORDER_STORAGE_JFREPOCHSTORAGE_INLINE_HPP
 27 
 28 #include "jfr/recorder/storage/jfrEpochStorage.hpp"
 29 
 30 #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
 31 #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp"
 32 #include "jfr/utilities/jfrConcurrentQueue.inline.hpp"
 33 #include "jfr/utilities/jfrLinkedList.inline.hpp"
 34 #include "logging/log.hpp"
 35 
 36 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
 37 JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::JfrEpochStorageHost() : _mspace(NULL) {}
 38 
 39 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
 40 JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::~JfrEpochStorageHost() {
 41   delete _mspace;
 42 }
 43 
 44 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
 45 bool JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::initialize(size_t min_elem_size, size_t free_list_cache_count_limit, size_t cache_prealloc_count) {
 46   assert(_mspace == NULL, "invariant");
 47   _mspace = new EpochMspace(min_elem_size, free_list_cache_count_limit, this);
 48   return _mspace != NULL && _mspace->initialize(cache_prealloc_count);
 49 }
 50 
 51 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
 52 inline NodeType* JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::acquire(size_t size, Thread* thread) {
 53   BufferPtr buffer = mspace_acquire_to_live_list(size, _mspace, thread);
 54   if (buffer == NULL) {
 55     log_warning(jfr)("Unable to allocate " SIZE_FORMAT " bytes of %s.", _mspace->min_element_size(), "epoch storage");
 56     return NULL;
 57   }
 58   assert(buffer->acquired_by_self(), "invariant");
 59   return buffer;
 60 }
 61 
 62 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
 63 void JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::release(NodeType* buffer) {
 64   assert(buffer != NULL, "invariant");
 65   buffer->set_retired();
 66 }
 67 
 68 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
 69 void JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::register_full(NodeType* buffer, Thread* thread) {
 70   // nothing here at the moment
 71 }
 72 
 73 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
 74 template <typename Functor>
 75 void JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::iterate(Functor& functor, bool previous_epoch) {
 76   typedef ReinitializeAllReleaseRetiredOp<EpochMspace, typename EpochMspace::LiveList> PreviousEpochReleaseOperation;
 77   typedef CompositeOperation<Functor, PreviousEpochReleaseOperation> PreviousEpochOperation;
 78   typedef ReleaseRetiredOp<Functor, EpochMspace, typename EpochMspace::LiveList> CurrentEpochOperation;
 79   if (previous_epoch) {
 80     PreviousEpochReleaseOperation pero(_mspace, _mspace->live_list(true));
 81     PreviousEpochOperation peo(&functor, &pero);
 82     process_live_list(peo, _mspace, true); // previous epoch list
 83     return;
 84   }
 85   if (EagerReclaim) {
 86     CurrentEpochOperation ceo(functor, _mspace, _mspace->live_list());
 87     process_live_list(ceo, _mspace, false); // current epoch list
 88     return;
 89   }
 90   process_live_list(functor, _mspace, false); // current epoch list
 91 }
 92 
 93 #ifdef ASSERT
 94 
 95 template <typename Mspace>
 96 class EmptyVerifier {
 97  private:
 98   Mspace* _mspace;
 99  public:
100   typedef typename Mspace::Node Node;
101   typedef typename Mspace::NodePtr NodePtr;
102   EmptyVerifier(Mspace* mspace) : _mspace(mspace) {}
103   bool process(NodePtr node) {
104     assert(node != NULL, "invariant");
105     assert(node->empty(), "invariant");
106     return true;
107   }
108 };
109 
110 template <typename NodeType, template <typename> class RetrievalPolicy, bool EagerReclaim>
111 void JfrEpochStorageHost<NodeType, RetrievalPolicy, EagerReclaim>::verify_previous_empty() const {
112   typedef EmptyVerifier<JfrEpochStorage::Mspace> VerifyEmptyMspace;
113   VerifyEmptyMspace vem(_mspace);
114   process_live_list(vem, _mspace, true);
115 }
116 
117 #endif // ASSERT
118 
119 #endif // SHARE_JFR_RECORDER_STORAGE_JFREPOCHSTORAGE_INLINE_HPP