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