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