1 /*
2 * Copyright (c) 2001, 2015, 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_GC_G1_PTRQUEUE_HPP
26 #define SHARE_VM_GC_G1_PTRQUEUE_HPP
27
28 #include "memory/allocation.hpp"
29 #include "utilities/sizes.hpp"
30
31 // There are various techniques that require threads to be able to log
32 // addresses. For example, a generational write barrier might log
33 // the addresses of modified old-generation objects. This type supports
34 // this operation.
35
36 // The definition of placement operator new(size_t, void*) in the <new>.
37 #include <new>
38
39 class PtrQueueSet;
40 class PtrQueue VALUE_OBJ_CLASS_SPEC {
41 friend class VMStructs;
42
43 // Noncopyable - not defined.
44 PtrQueue(const PtrQueue&);
45 PtrQueue& operator=(const PtrQueue&);
46
47 // The ptr queue set to which this queue belongs.
48 PtrQueueSet* const _qset;
49
50 // Whether updates should be logged.
51 bool _active;
52
53 // If true, the queue is permanent, and doesn't need to deallocate
54 // its buffer in the destructor (since that obtains a lock which may not
55 // be legally locked by then.
56 const bool _permanent;
57
58 protected:
148 }
149
150 static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); }
151
152 template<typename Derived>
153 static ByteSize byte_offset_of_buf() {
154 return byte_offset_of(Derived, _buf);
155 }
156
157 static ByteSize byte_width_of_buf() { return in_ByteSize(sizeof(void*)); }
158
159 template<typename Derived>
160 static ByteSize byte_offset_of_active() {
161 return byte_offset_of(Derived, _active);
162 }
163
164 static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); }
165
166 };
167
168 class BufferNode {
169 size_t _index;
170 BufferNode* _next;
171 public:
172 BufferNode() : _index(0), _next(NULL) { }
173 BufferNode* next() const { return _next; }
174 void set_next(BufferNode* n) { _next = n; }
175 size_t index() const { return _index; }
176 void set_index(size_t i) { _index = i; }
177
178 // Align the size of the structure to the size of the pointer
179 static size_t aligned_size() {
180 static const size_t alignment = round_to(sizeof(BufferNode), sizeof(void*));
181 return alignment;
182 }
183
184 // BufferNode is allocated before the buffer.
185 // The chunk of memory that holds both of them is a block.
186
187 // Produce a new BufferNode given a buffer.
188 static BufferNode* new_from_buffer(void** buf) {
189 return new (make_block_from_buffer(buf)) BufferNode;
190 }
191
192 // The following are the required conversion routines:
193 static BufferNode* make_node_from_buffer(void** buf) {
194 return (BufferNode*)make_block_from_buffer(buf);
195 }
196 static void** make_buffer_from_node(BufferNode *node) {
197 return make_buffer_from_block(node);
198 }
199 static void* make_block_from_node(BufferNode *node) {
200 return (void*)node;
201 }
202 static void** make_buffer_from_block(void* p) {
203 return (void**)((char*)p + aligned_size());
204 }
205 static void* make_block_from_buffer(void** p) {
206 return (void*)((char*)p - aligned_size());
207 }
208 };
209
210 // A PtrQueueSet represents resources common to a set of pointer queues.
211 // In particular, the individual queues allocate buffers from this shared
212 // set, and return completed buffers to the set.
213 // All these variables are are protected by the TLOQ_CBL_mon. XXX ???
214 class PtrQueueSet VALUE_OBJ_CLASS_SPEC {
215 protected:
216 Monitor* _cbl_mon; // Protects the fields below.
217 BufferNode* _completed_buffers_head;
218 BufferNode* _completed_buffers_tail;
219 int _n_completed_buffers;
220 int _process_completed_threshold;
221 volatile bool _process_completed;
222
223 // This (and the interpretation of the first element as a "next"
224 // pointer) are protected by the TLOQ_FL_lock.
225 Mutex* _fl_lock;
226 BufferNode* _buf_free_list;
|
1 /*
2 * Copyright (c) 2001, 2016, 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_GC_G1_PTRQUEUE_HPP
26 #define SHARE_VM_GC_G1_PTRQUEUE_HPP
27
28 #include "memory/allocation.hpp"
29 #include "utilities/sizes.hpp"
30
31 // There are various techniques that require threads to be able to log
32 // addresses. For example, a generational write barrier might log
33 // the addresses of modified old-generation objects. This type supports
34 // this operation.
35
36 class PtrQueueSet;
37 class PtrQueue VALUE_OBJ_CLASS_SPEC {
38 friend class VMStructs;
39
40 // Noncopyable - not defined.
41 PtrQueue(const PtrQueue&);
42 PtrQueue& operator=(const PtrQueue&);
43
44 // The ptr queue set to which this queue belongs.
45 PtrQueueSet* const _qset;
46
47 // Whether updates should be logged.
48 bool _active;
49
50 // If true, the queue is permanent, and doesn't need to deallocate
51 // its buffer in the destructor (since that obtains a lock which may not
52 // be legally locked by then.
53 const bool _permanent;
54
55 protected:
145 }
146
147 static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); }
148
149 template<typename Derived>
150 static ByteSize byte_offset_of_buf() {
151 return byte_offset_of(Derived, _buf);
152 }
153
154 static ByteSize byte_width_of_buf() { return in_ByteSize(sizeof(void*)); }
155
156 template<typename Derived>
157 static ByteSize byte_offset_of_active() {
158 return byte_offset_of(Derived, _active);
159 }
160
161 static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); }
162
163 };
164
165 // A BufferNode has some header fields, followed by storage for the
166 // buffer. In C99 terms, it has a flexible array member for the
167 // buffer. However, C++ doesn't support flexible array members, so
168 // we're forced to fake it.
169 class BufferNode {
170 size_t _index;
171 BufferNode* _next;
172 void* _buffer[1]; // Pseudo flexible array member.
173
174 BufferNode() : _index(0), _next(NULL) { }
175 ~BufferNode() { }
176
177 static size_t buffer_offset() {
178 return offset_of(BufferNode, _buffer);
179 }
180
181 public:
182 BufferNode* next() const { return _next; }
183 void set_next(BufferNode* n) { _next = n; }
184 size_t index() const { return _index; }
185 void set_index(size_t i) { _index = i; }
186
187 // Allocate a new BufferNode with the "buffer" having size bytes.
188 static BufferNode* allocate(size_t byte_size);
189
190 // Free a BufferNode.
191 static void deallocate(BufferNode* node);
192
193 // Return the BufferNode containing the buffer.
194 static BufferNode* make_node_from_buffer(void** buffer) {
195 return reinterpret_cast<BufferNode*>(
196 reinterpret_cast<char*>(buffer) - buffer_offset());
197 }
198
199 // Return the buffer for node.
200 static void** make_buffer_from_node(BufferNode *node) {
201 // &_buffer[0] might lead to index out of bounds warnings.
202 return reinterpret_cast<void**>(
203 reinterpret_cast<char*>(node) + buffer_offset());
204 }
205 };
206
207 // A PtrQueueSet represents resources common to a set of pointer queues.
208 // In particular, the individual queues allocate buffers from this shared
209 // set, and return completed buffers to the set.
210 // All these variables are are protected by the TLOQ_CBL_mon. XXX ???
211 class PtrQueueSet VALUE_OBJ_CLASS_SPEC {
212 protected:
213 Monitor* _cbl_mon; // Protects the fields below.
214 BufferNode* _completed_buffers_head;
215 BufferNode* _completed_buffers_tail;
216 int _n_completed_buffers;
217 int _process_completed_threshold;
218 volatile bool _process_completed;
219
220 // This (and the interpretation of the first element as a "next"
221 // pointer) are protected by the TLOQ_FL_lock.
222 Mutex* _fl_lock;
223 BufferNode* _buf_free_list;
|