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_GC_SHARED_PTRQUEUE_HPP 26 #define SHARE_GC_SHARED_PTRQUEUE_HPP 27 28 #include "memory/padded.hpp" 29 #include "utilities/align.hpp" 30 #include "utilities/debug.hpp" 31 #include "utilities/lockFreeStack.hpp" 32 #include "utilities/sizes.hpp" 33 34 class Mutex; 35 class Monitor; 36 37 // There are various techniques that require threads to be able to log 38 // addresses. For example, a generational write barrier might log 39 // the addresses of modified old-generation objects. This type supports 40 // this operation. 41 42 class BufferNode; 43 class PtrQueueSet; 44 class PtrQueue { 45 friend class VMStructs; 46 47 // Noncopyable - not defined. 48 PtrQueue(const PtrQueue&); 49 PtrQueue& operator=(const PtrQueue&); 50 51 // The ptr queue set to which this queue belongs. 52 PtrQueueSet* const _qset; 53 54 // Whether updates should be logged. 55 bool _active; 56 57 // If true, the queue is permanent, and doesn't need to deallocate 58 // its buffer in the destructor (since that obtains a lock which may not 59 // be legally locked by then. 60 const bool _permanent; 61 62 // The (byte) index at which an object was last enqueued. Starts at 63 // capacity_in_bytes (indicating an empty buffer) and goes towards zero. 64 // Value is always pointer-size aligned. 65 size_t _index; 66 67 // Size of the current buffer, in bytes. 68 // Value is always pointer-size aligned. 69 size_t _capacity_in_bytes; 70 71 static const size_t _element_size = sizeof(void*); 72 73 // Get the capacity, in bytes. The capacity must have been set. 74 size_t capacity_in_bytes() const { 75 assert(_capacity_in_bytes > 0, "capacity not set"); 76 return _capacity_in_bytes; 77 } 78 79 void set_capacity(size_t entries) { 80 size_t byte_capacity = index_to_byte_index(entries); 81 assert(_capacity_in_bytes == 0 || _capacity_in_bytes == byte_capacity, 82 "changing capacity " SIZE_FORMAT " -> " SIZE_FORMAT, 83 _capacity_in_bytes, byte_capacity); 84 _capacity_in_bytes = byte_capacity; 85 } 86 87 static size_t byte_index_to_index(size_t ind) { 88 assert(is_aligned(ind, _element_size), "precondition"); 89 return ind / _element_size; 90 } 91 92 static size_t index_to_byte_index(size_t ind) { 93 return ind * _element_size; 94 } 95 96 protected: 97 // The buffer. 98 void** _buf; 99 100 size_t index() const { 101 return byte_index_to_index(_index); 102 } 103 104 void set_index(size_t new_index) { 105 size_t byte_index = index_to_byte_index(new_index); 106 assert(byte_index <= capacity_in_bytes(), "precondition"); 107 _index = byte_index; 108 } 109 110 size_t capacity() const { 111 return byte_index_to_index(capacity_in_bytes()); 112 } 113 114 // If there is a lock associated with this buffer, this is that lock. 115 Mutex* _lock; 116 117 PtrQueueSet* qset() { return _qset; } 118 bool is_permanent() const { return _permanent; } 119 120 // Process queue entries and release resources. 121 void flush_impl(); 122 123 // Initialize this queue to contain a null buffer, and be part of the 124 // given PtrQueueSet. 125 PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false); 126 127 // Requires queue flushed or permanent. 128 ~PtrQueue(); 129 130 public: 131 132 // Associate a lock with a ptr queue. 133 void set_lock(Mutex* lock) { _lock = lock; } 134 135 // Forcibly set empty. 136 void reset() { 137 if (_buf != NULL) { 138 _index = capacity_in_bytes(); 139 } 140 } 141 142 void enqueue(volatile void* ptr) { 143 enqueue((void*)(ptr)); 144 } 145 146 // Enqueues the given "obj". 147 void enqueue(void* ptr) { 148 if (!_active) return; 149 else enqueue_known_active(ptr); 150 } 151 152 // This method is called when we're doing the zero index handling 153 // and gives a chance to the queues to do any pre-enqueueing 154 // processing they might want to do on the buffer. It should return 155 // true if the buffer should be enqueued, or false if enough 156 // entries were cleared from it so that it can be re-used. It should 157 // not return false if the buffer is still full (otherwise we can 158 // get into an infinite loop). 159 virtual bool should_enqueue_buffer() { return true; } 160 void handle_zero_index(); 161 162 void enqueue_known_active(void* ptr); 163 164 // Return the size of the in-use region. 165 size_t size() const { 166 size_t result = 0; 167 if (_buf != NULL) { 168 assert(_index <= capacity_in_bytes(), "Invariant"); 169 result = byte_index_to_index(capacity_in_bytes() - _index); 170 } 171 return result; 172 } 173 174 bool is_empty() const { 175 return _buf == NULL || capacity_in_bytes() == _index; 176 } 177 178 // Set the "active" property of the queue to "b". An enqueue to an 179 // inactive thread is a no-op. Setting a queue to inactive resets its 180 // log to the empty state. 181 void set_active(bool b) { 182 _active = b; 183 if (!b && _buf != NULL) { 184 reset(); 185 } else if (b && _buf != NULL) { 186 assert(index() == capacity(), 187 "invariant: queues are empty when activated."); 188 } 189 } 190 191 bool is_active() const { return _active; } 192 193 // To support compiler. 194 195 protected: 196 template<typename Derived> 197 static ByteSize byte_offset_of_index() { 198 return byte_offset_of(Derived, _index); 199 } 200 201 static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); } 202 203 template<typename Derived> 204 static ByteSize byte_offset_of_buf() { 205 return byte_offset_of(Derived, _buf); 206 } 207 208 static ByteSize byte_width_of_buf() { return in_ByteSize(_element_size); } 209 210 template<typename Derived> 211 static ByteSize byte_offset_of_active() { 212 return byte_offset_of(Derived, _active); 213 } 214 215 static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); } 216 217 }; 218 219 class BufferNode { 220 size_t _index; 221 BufferNode* volatile _next; 222 void* _buffer[1]; // Pseudo flexible array member. 223 224 BufferNode() : _index(0), _next(NULL) { } 225 ~BufferNode() { } 226 227 static size_t buffer_offset() { 228 return offset_of(BufferNode, _buffer); 229 } 230 231 static BufferNode* volatile* next_ptr(BufferNode& bn) { return &bn._next; } 232 233 AIX_ONLY(public:) // xlC 12 on AIX doesn't implement C++ DR45. 234 // Allocate a new BufferNode with the "buffer" having size elements. 235 static BufferNode* allocate(size_t size); 236 237 // Free a BufferNode. 238 static void deallocate(BufferNode* node); 239 240 public: 241 typedef LockFreeStack<BufferNode, &next_ptr> Stack; 242 243 BufferNode* next() const { return _next; } 244 void set_next(BufferNode* n) { _next = n; } 245 size_t index() const { return _index; } 246 void set_index(size_t i) { _index = i; } 247 248 // Return the BufferNode containing the buffer, after setting its index. 249 static BufferNode* make_node_from_buffer(void** buffer, size_t index) { 250 BufferNode* node = 251 reinterpret_cast<BufferNode*>( 252 reinterpret_cast<char*>(buffer) - buffer_offset()); 253 node->set_index(index); 254 return node; 255 } 256 257 // Return the buffer for node. 258 static void** make_buffer_from_node(BufferNode *node) { 259 // &_buffer[0] might lead to index out of bounds warnings. 260 return reinterpret_cast<void**>( 261 reinterpret_cast<char*>(node) + buffer_offset()); 262 } 263 264 class Allocator; // Free-list based allocator. 265 class TestSupport; // Unit test support. 266 }; 267 268 // Allocation is based on a lock-free free list of nodes, linked through 269 // BufferNode::_next (see BufferNode::Stack). To solve the ABA problem, 270 // popping a node from the free list is performed within a GlobalCounter 271 // critical section, and pushing nodes onto the free list is done after 272 // a GlobalCounter synchronization associated with the nodes to be pushed. 273 // This is documented behavior so that other parts of the node life-cycle 274 // can depend on and make use of it too. 275 class BufferNode::Allocator { 276 friend class TestSupport; 277 278 // Since we don't expect many instances, and measured >15% speedup 279 // on stress gtest, padding seems like a good tradeoff here. 280 #define DECLARE_PADDED_MEMBER(Id, Type, Name) \ 281 Type Name; DEFINE_PAD_MINUS_SIZE(Id, DEFAULT_CACHE_LINE_SIZE, sizeof(Type)) 282 283 const size_t _buffer_size; 284 char _name[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)]; // Use name as padding. 285 DECLARE_PADDED_MEMBER(1, Stack, _pending_list); 286 DECLARE_PADDED_MEMBER(2, Stack, _free_list); 287 DECLARE_PADDED_MEMBER(3, volatile size_t, _pending_count); 288 DECLARE_PADDED_MEMBER(4, volatile size_t, _free_count); 289 DECLARE_PADDED_MEMBER(5, volatile bool, _transfer_lock); 290 291 #undef DECLARE_PADDED_MEMBER 292 293 void delete_list(BufferNode* list); 294 bool try_transfer_pending(); 295 296 public: 297 Allocator(const char* name, size_t buffer_size); 298 ~Allocator(); 299 300 const char* name() const { return _name; } 301 size_t buffer_size() const { return _buffer_size; } 302 size_t free_count() const; 303 BufferNode* allocate(); 304 void release(BufferNode* node); 305 306 // Deallocate some of the available buffers. remove_goal is the target 307 // number to remove. Returns the number actually deallocated, which may 308 // be less than the goal if there were fewer available. 309 size_t reduce_free_list(size_t remove_goal); 310 }; 311 312 // A PtrQueueSet represents resources common to a set of pointer queues. 313 // In particular, the individual queues allocate buffers from this shared 314 // set, and return completed buffers to the set. 315 class PtrQueueSet { 316 BufferNode::Allocator* _allocator; 317 318 Monitor* _cbl_mon; // Protects the fields below. 319 BufferNode* _completed_buffers_head; 320 BufferNode* _completed_buffers_tail; 321 size_t _n_completed_buffers; 322 323 size_t _process_completed_buffers_threshold; 324 volatile bool _process_completed_buffers; 325 326 // If true, notify_all on _cbl_mon when the threshold is reached. 327 bool _notify_when_complete; 328 329 // Maximum number of elements allowed on completed queue: after that, 330 // enqueuer does the work itself. 331 size_t _max_completed_buffers; 332 size_t _completed_buffers_padding; 333 334 void assert_completed_buffers_list_len_correct_locked() NOT_DEBUG_RETURN; 335 336 protected: 337 bool _all_active; 338 339 // A mutator thread does the the work of processing a buffer. 340 // Returns "true" iff the work is complete (and the buffer may be 341 // deallocated). 342 virtual bool mut_process_buffer(BufferNode* node) { 343 ShouldNotReachHere(); 344 return false; 345 } 346 347 // Create an empty ptr queue set. 348 PtrQueueSet(bool notify_when_complete = false); 349 ~PtrQueueSet(); 350 351 // Because of init-order concerns, we can't pass these as constructor 352 // arguments. 353 void initialize(Monitor* cbl_mon, BufferNode::Allocator* allocator); 354 355 // For (unlocked!) iteration over the completed buffers. 356 BufferNode* completed_buffers_head() const { return _completed_buffers_head; } 357 358 // Deallocate all of the completed buffers. 359 void abandon_completed_buffers(); 360 361 public: 362 363 // Return the buffer for a BufferNode of size buffer_size(). 364 void** allocate_buffer(); 365 366 // Return an empty buffer to the free list. The node is required 367 // to have been allocated with a size of buffer_size(). 368 void deallocate_buffer(BufferNode* node); 369 370 // A completed buffer is a buffer the mutator is finished with, and 371 // is ready to be processed by the collector. It need not be full. 372 373 // Adds node to the completed buffer list. 374 void enqueue_completed_buffer(BufferNode* node); 375 376 // If the number of completed buffers is > stop_at, then remove and 377 // return a completed buffer from the list. Otherwise, return NULL. 378 BufferNode* get_completed_buffer(size_t stop_at = 0); 379 380 // To be invoked by the mutator. 381 bool process_or_enqueue_completed_buffer(BufferNode* node); 382 383 bool process_completed_buffers() { return _process_completed_buffers; } 384 void set_process_completed_buffers(bool x) { _process_completed_buffers = x; } 385 386 bool is_active() { return _all_active; } 387 388 size_t buffer_size() const { 389 return _allocator->buffer_size(); 390 } 391 392 // Get/Set the number of completed buffers that triggers log processing. 393 // Log processing should be done when the number of buffers exceeds the 394 // threshold. 395 void set_process_completed_buffers_threshold(size_t sz) { 396 _process_completed_buffers_threshold = sz; 397 } 398 size_t process_completed_buffers_threshold() const { 399 return _process_completed_buffers_threshold; 400 } 401 static const size_t ProcessCompletedBuffersThresholdNever = ~size_t(0); 402 403 size_t completed_buffers_num() const { return _n_completed_buffers; } 404 405 void merge_bufferlists(PtrQueueSet* src); 406 407 void set_max_completed_buffers(size_t m) { 408 _max_completed_buffers = m; 409 } 410 size_t max_completed_buffers() const { 411 return _max_completed_buffers; 412 } 413 static const size_t MaxCompletedBuffersUnlimited = ~size_t(0); 414 415 void set_completed_buffers_padding(size_t padding) { 416 _completed_buffers_padding = padding; 417 } 418 size_t completed_buffers_padding() const { 419 return _completed_buffers_padding; 420 } 421 422 // Notify the consumer if the number of buffers crossed the threshold 423 void notify_if_necessary(); 424 }; 425 426 #endif // SHARE_GC_SHARED_PTRQUEUE_HPP