1 /*
   2  * Copyright (c) 2001, 2019, 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_MEMORY_FREELIST_HPP
  26 #define SHARE_MEMORY_FREELIST_HPP
  27 
  28 // A class for maintaining a free list of Chunk's.  The FreeList
  29 // maintains a the structure of the list (head, tail, etc.) plus
  30 // statistics for allocations from the list.  The links between items
  31 // are not part of FreeList.  The statistics are
  32 // used to make decisions about coalescing Chunk's when they
  33 // are swept during collection.
  34 //
  35 // See the corresponding .cpp file for a description of the specifics
  36 // for that implementation.
  37 
  38 class Mutex;
  39 
  40 template <class Chunk_t>
  41 class FreeList {
  42   friend class VMStructs;
  43 
  44  private:
  45   Chunk_t*      _head;          // Head of list of free chunks
  46   Chunk_t*      _tail;          // Tail of list of free chunks
  47   size_t        _size;          // Size in Heap words of each chunk
  48   ssize_t       _count;         // Number of entries in list
  49 
  50  protected:
  51 
  52 #ifdef ASSERT
  53   Mutex*        _protecting_lock;
  54   void assert_proper_lock_protection_work() const;
  55 #endif
  56 
  57   // Asserts false if the protecting lock (if any) is not held.
  58   void assert_proper_lock_protection() const {
  59     DEBUG_ONLY(assert_proper_lock_protection_work());
  60   }
  61 
  62   void increment_count()    {
  63     _count++;
  64   }
  65 
  66   void decrement_count() {
  67     _count--;
  68     assert(_count >= 0, "Count should not be negative");
  69   }
  70 
  71  public:
  72   // Constructor
  73   // Construct a list without any entries.
  74   FreeList();
  75 
  76   // Do initialization
  77   void initialize();
  78 
  79   // Reset the head, tail, and count of a free list.
  80   void reset();
  81 
  82   // Declare the current free list to be protected by the given lock.
  83 #ifdef ASSERT
  84   Mutex* protecting_lock() const { return _protecting_lock; }
  85   void set_protecting_lock(Mutex* v) {
  86     _protecting_lock = v;
  87   }
  88 #endif
  89 
  90   // Accessors.
  91   Chunk_t* head() const {
  92     assert_proper_lock_protection();
  93     return _head;
  94   }
  95   void set_head(Chunk_t* v) {
  96     assert_proper_lock_protection();
  97     _head = v;
  98     assert(!_head || _head->size() == _size, "bad chunk size");
  99   }
 100   // Set the head of the list and set the prev field of non-null
 101   // values to NULL.
 102   void link_head(Chunk_t* v);
 103 
 104   Chunk_t* tail() const {
 105     assert_proper_lock_protection();
 106     return _tail;
 107   }
 108   void set_tail(Chunk_t* v) {
 109     assert_proper_lock_protection();
 110     _tail = v;
 111     assert(!_tail || _tail->size() == _size, "bad chunk size");
 112   }
 113   // Set the tail of the list and set the next field of non-null
 114   // values to NULL.
 115   void link_tail(Chunk_t* v) {
 116     assert_proper_lock_protection();
 117     set_tail(v);
 118     if (v != NULL) {
 119       v->clear_next();
 120     }
 121   }
 122 
 123   // No locking checks in read-accessors: lock-free reads (only) are benign.
 124   // Readers are expected to have the lock if they are doing work that
 125   // requires atomicity guarantees in sections of code.
 126   size_t size() const {
 127     return _size;
 128   }
 129   void set_size(size_t v) {
 130     assert_proper_lock_protection();
 131     _size = v;
 132   }
 133   ssize_t count() const { return _count; }
 134   void set_count(ssize_t v) { _count = v;}
 135 
 136   size_t get_better_size() { return size(); }
 137 
 138   size_t returned_bytes() const { ShouldNotReachHere(); return 0; }
 139   void set_returned_bytes(size_t v) {}
 140   void increment_returned_bytes_by(size_t v) {}
 141 
 142   // Unlink head of list and return it.  Returns NULL if
 143   // the list is empty.
 144   Chunk_t* get_chunk_at_head();
 145 
 146   // Remove the first "n" or "count", whichever is smaller, chunks from the
 147   // list, setting "fl", which is required to be empty, to point to them.
 148   void getFirstNChunksFromList(size_t n, FreeList<Chunk_t>* fl);
 149 
 150   // Unlink this chunk from it's free list
 151   void remove_chunk(Chunk_t* fc);
 152 
 153   // Add this chunk to this free list.
 154   void return_chunk_at_head(Chunk_t* fc);
 155   void return_chunk_at_tail(Chunk_t* fc);
 156 
 157   // Similar to returnChunk* but also records some diagnostic
 158   // information.
 159   void return_chunk_at_head(Chunk_t* fc, bool record_return);
 160   void return_chunk_at_tail(Chunk_t* fc, bool record_return);
 161 
 162   // Prepend "fl" (whose size is required to be the same as that of "this")
 163   // to the front of "this" list.
 164   void prepend(FreeList<Chunk_t>* fl);
 165 
 166   // Verify that the chunk is in the list.
 167   // found.  Return NULL if "fc" is not found.
 168   bool verify_chunk_in_free_list(Chunk_t* fc) const;
 169 
 170   // Printing support
 171   static void print_labels_on(outputStream* st, const char* c);
 172   void print_on(outputStream* st, const char* c = NULL) const;
 173 };
 174 
 175 #endif // SHARE_MEMORY_FREELIST_HPP