duke@435: /* mikael@6198: * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: jmasa@3730: #ifndef SHARE_VM_MEMORY_FREELIST_HPP jmasa@3730: #define SHARE_VM_MEMORY_FREELIST_HPP stefank@2314: stefank@2314: #include "gc_implementation/shared/allocationStats.hpp" stefank@2314: duke@435: class CompactibleFreeListSpace; duke@435: jmasa@3730: // A class for maintaining a free list of Chunk's. The FreeList duke@435: // maintains a the structure of the list (head, tail, etc.) plus duke@435: // statistics for allocations from the list. The links between items duke@435: // are not part of FreeList. The statistics are jmasa@3730: // used to make decisions about coalescing Chunk's when they duke@435: // are swept during collection. duke@435: // duke@435: // See the corresponding .cpp file for a description of the specifics duke@435: // for that implementation. duke@435: duke@435: class Mutex; duke@435: jmasa@4196: template duke@435: class FreeList VALUE_OBJ_CLASS_SPEC { duke@435: friend class CompactibleFreeListSpace; dcubed@587: friend class VMStructs; ysr@1580: ysr@1580: private: jmasa@4196: Chunk_t* _head; // Head of list of free chunks jmasa@4196: Chunk_t* _tail; // Tail of list of free chunks ysr@1580: size_t _size; // Size in Heap words of each chunk duke@435: ssize_t _count; // Number of entries in list duke@435: jmasa@4196: protected: duke@435: duke@435: #ifdef ASSERT duke@435: Mutex* _protecting_lock; duke@435: #endif duke@435: duke@435: // Asserts false if the protecting lock (if any) is not held. duke@435: void assert_proper_lock_protection_work() const PRODUCT_RETURN; duke@435: void assert_proper_lock_protection() const { duke@435: #ifdef ASSERT duke@435: if (_protecting_lock != NULL) duke@435: assert_proper_lock_protection_work(); duke@435: #endif duke@435: } duke@435: ysr@1580: void increment_count() { ysr@1580: _count++; ysr@1580: } ysr@1580: duke@435: void decrement_count() { duke@435: _count--; ysr@447: assert(_count >= 0, "Count should not be negative"); ysr@447: } duke@435: duke@435: public: duke@435: // Constructor duke@435: // Construct a list without any entries. duke@435: FreeList(); duke@435: jmasa@4196: // Do initialization jmasa@4196: void initialize(); jmasa@4196: jmasa@4196: // Reset the head, tail, and count of a free list. jmasa@4196: void reset(); duke@435: duke@435: // Declare the current free list to be protected by the given lock. duke@435: #ifdef ASSERT jmasa@4196: Mutex* protecting_lock() const { return _protecting_lock; } jmasa@4196: void set_protecting_lock(Mutex* v) { jmasa@4196: _protecting_lock = v; duke@435: } duke@435: #endif duke@435: duke@435: // Accessors. jmasa@4196: Chunk_t* head() const { duke@435: assert_proper_lock_protection(); duke@435: return _head; duke@435: } jmasa@4196: void set_head(Chunk_t* v) { duke@435: assert_proper_lock_protection(); duke@435: _head = v; duke@435: assert(!_head || _head->size() == _size, "bad chunk size"); duke@435: } duke@435: // Set the head of the list and set the prev field of non-null duke@435: // values to NULL. jmasa@4196: void link_head(Chunk_t* v); duke@435: jmasa@4196: Chunk_t* tail() const { duke@435: assert_proper_lock_protection(); duke@435: return _tail; duke@435: } jmasa@4196: void set_tail(Chunk_t* v) { duke@435: assert_proper_lock_protection(); duke@435: _tail = v; duke@435: assert(!_tail || _tail->size() == _size, "bad chunk size"); duke@435: } duke@435: // Set the tail of the list and set the next field of non-null duke@435: // values to NULL. jmasa@4196: void link_tail(Chunk_t* v) { duke@435: assert_proper_lock_protection(); duke@435: set_tail(v); duke@435: if (v != NULL) { jmasa@3732: v->clear_next(); duke@435: } duke@435: } duke@435: duke@435: // No locking checks in read-accessors: lock-free reads (only) are benign. duke@435: // Readers are expected to have the lock if they are doing work that duke@435: // requires atomicity guarantees in sections of code. duke@435: size_t size() const { duke@435: return _size; duke@435: } duke@435: void set_size(size_t v) { duke@435: assert_proper_lock_protection(); duke@435: _size = v; duke@435: } jmasa@4196: ssize_t count() const { return _count; } jmasa@4196: void set_count(ssize_t v) { _count = v;} duke@435: jmasa@4196: size_t get_better_size() { return size(); } duke@435: jmasa@4196: size_t returned_bytes() const { ShouldNotReachHere(); return 0; } jmasa@4196: void set_returned_bytes(size_t v) {} jmasa@4196: void increment_returned_bytes_by(size_t v) {} duke@435: duke@435: // Unlink head of list and return it. Returns NULL if duke@435: // the list is empty. jmasa@4196: Chunk_t* get_chunk_at_head(); duke@435: duke@435: // Remove the first "n" or "count", whichever is smaller, chunks from the duke@435: // list, setting "fl", which is required to be empty, to point to them. jmasa@4196: void getFirstNChunksFromList(size_t n, FreeList* fl); duke@435: duke@435: // Unlink this chunk from it's free list jmasa@4196: void remove_chunk(Chunk_t* fc); duke@435: duke@435: // Add this chunk to this free list. jmasa@4196: void return_chunk_at_head(Chunk_t* fc); jmasa@4196: void return_chunk_at_tail(Chunk_t* fc); duke@435: duke@435: // Similar to returnChunk* but also records some diagnostic duke@435: // information. jmasa@4196: void return_chunk_at_head(Chunk_t* fc, bool record_return); jmasa@4196: void return_chunk_at_tail(Chunk_t* fc, bool record_return); duke@435: duke@435: // Prepend "fl" (whose size is required to be the same as that of "this") duke@435: // to the front of "this" list. jmasa@4196: void prepend(FreeList* fl); duke@435: duke@435: // Verify that the chunk is in the list. duke@435: // found. Return NULL if "fc" is not found. jmasa@4196: bool verify_chunk_in_free_list(Chunk_t* fc) const; ysr@447: ysr@447: // Printing support ysr@447: static void print_labels_on(outputStream* st, const char* c); ysr@447: void print_on(outputStream* st, const char* c = NULL) const; duke@435: }; stefank@2314: jmasa@3730: #endif // SHARE_VM_MEMORY_FREELIST_HPP