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 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 | |