src/share/vm/gc_implementation/g1/ptrQueue.hpp

Fri, 01 Oct 2010 16:43:05 -0400

author
tonyp
date
Fri, 01 Oct 2010 16:43:05 -0400
changeset 2197
6e0aac35bfa9
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
permissions
-rw-r--r--

6980838: G1: guarantee(false) failed: thread has an unexpected active value in its SATB queue
Summary: Under certain circumstances a safepoint could happen between a JavaThread object being created and that object being added to the Java threads list. This could cause the active field of that thread's SATB queue to get out-of-sync with respect to the other Java threads. The solution is to activate the SATB queue, when necessary, before adding the thread to the Java threads list, not when the JavaThread object is created. The changeset also includes a small fix to rename the surrogate locker thread from "Surrogate Locker Thread (CMS)" to "Surrogate Locker Thread (Concurrent GC)" since it's also used in G1.
Reviewed-by: iveresov, ysr, johnc, jcoomes

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 // There are various techniques that require threads to be able to log
ysr@777 26 // addresses. For example, a generational write barrier might log
ysr@777 27 // the addresses of modified old-generation objects. This type supports
ysr@777 28 // this operation.
ysr@777 29
iveresov@1546 30 // The definition of placement operator new(size_t, void*) in the <new>.
iveresov@1546 31 #include <new>
iveresov@1546 32
ysr@777 33 class PtrQueueSet;
apetrusenko@984 34 class PtrQueue VALUE_OBJ_CLASS_SPEC {
ysr@777 35
ysr@777 36 protected:
ysr@777 37 // The ptr queue set to which this queue belongs.
ysr@777 38 PtrQueueSet* _qset;
ysr@777 39
ysr@777 40 // Whether updates should be logged.
ysr@777 41 bool _active;
ysr@777 42
ysr@777 43 // The buffer.
ysr@777 44 void** _buf;
ysr@777 45 // The index at which an object was last enqueued. Starts at "_sz"
ysr@777 46 // (indicating an empty buffer) and goes towards zero.
ysr@777 47 size_t _index;
ysr@777 48
ysr@777 49 // The size of the buffer.
ysr@777 50 size_t _sz;
ysr@777 51
ysr@777 52 // If true, the queue is permanent, and doesn't need to deallocate
ysr@777 53 // its buffer in the destructor (since that obtains a lock which may not
ysr@777 54 // be legally locked by then.
ysr@777 55 bool _perm;
ysr@777 56
ysr@777 57 // If there is a lock associated with this buffer, this is that lock.
ysr@777 58 Mutex* _lock;
ysr@777 59
ysr@777 60 PtrQueueSet* qset() { return _qset; }
ysr@777 61
ysr@777 62 public:
ysr@777 63 // Initialize this queue to contain a null buffer, and be part of the
ysr@777 64 // given PtrQueueSet.
tonyp@1752 65 PtrQueue(PtrQueueSet*, bool perm = false, bool active = false);
ysr@777 66 // Release any contained resources.
iveresov@876 67 void flush();
iveresov@876 68 // Calls flush() when destroyed.
iveresov@876 69 ~PtrQueue() { flush(); }
ysr@777 70
ysr@777 71 // Associate a lock with a ptr queue.
ysr@777 72 void set_lock(Mutex* lock) { _lock = lock; }
ysr@777 73
ysr@777 74 void reset() { if (_buf != NULL) _index = _sz; }
ysr@777 75
ysr@777 76 // Enqueues the given "obj".
ysr@777 77 void enqueue(void* ptr) {
ysr@777 78 if (!_active) return;
ysr@777 79 else enqueue_known_active(ptr);
ysr@777 80 }
ysr@777 81
iveresov@1546 82 void handle_zero_index();
ysr@777 83 void locking_enqueue_completed_buffer(void** buf);
ysr@777 84
ysr@777 85 void enqueue_known_active(void* ptr);
ysr@777 86
ysr@777 87 size_t size() {
ysr@777 88 assert(_sz >= _index, "Invariant.");
ysr@777 89 return _buf == NULL ? 0 : _sz - _index;
ysr@777 90 }
ysr@777 91
tonyp@2197 92 bool is_empty() {
tonyp@2197 93 return _buf == NULL || _sz == _index;
tonyp@2197 94 }
tonyp@2197 95
ysr@777 96 // Set the "active" property of the queue to "b". An enqueue to an
ysr@777 97 // inactive thread is a no-op. Setting a queue to inactive resets its
ysr@777 98 // log to the empty state.
ysr@777 99 void set_active(bool b) {
ysr@777 100 _active = b;
ysr@777 101 if (!b && _buf != NULL) {
ysr@777 102 _index = _sz;
ysr@777 103 } else if (b && _buf != NULL) {
ysr@777 104 assert(_index == _sz, "invariant: queues are empty when activated.");
ysr@777 105 }
ysr@777 106 }
ysr@777 107
tonyp@1752 108 bool is_active() { return _active; }
tonyp@1752 109
ysr@777 110 static int byte_index_to_index(int ind) {
ysr@777 111 assert((ind % oopSize) == 0, "Invariant.");
ysr@777 112 return ind / oopSize;
ysr@777 113 }
ysr@777 114
ysr@777 115 static int index_to_byte_index(int byte_ind) {
ysr@777 116 return byte_ind * oopSize;
ysr@777 117 }
ysr@777 118
ysr@777 119 // To support compiler.
ysr@777 120 static ByteSize byte_offset_of_index() {
ysr@777 121 return byte_offset_of(PtrQueue, _index);
ysr@777 122 }
ysr@777 123 static ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); }
ysr@777 124
ysr@777 125 static ByteSize byte_offset_of_buf() {
ysr@777 126 return byte_offset_of(PtrQueue, _buf);
ysr@777 127 }
ysr@777 128 static ByteSize byte_width_of_buf() { return in_ByteSize(sizeof(void*)); }
ysr@777 129
ysr@777 130 static ByteSize byte_offset_of_active() {
ysr@777 131 return byte_offset_of(PtrQueue, _active);
ysr@777 132 }
ysr@777 133 static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); }
ysr@777 134
ysr@777 135 };
ysr@777 136
iveresov@1546 137 class BufferNode {
iveresov@1546 138 size_t _index;
iveresov@1546 139 BufferNode* _next;
iveresov@1546 140 public:
iveresov@1546 141 BufferNode() : _index(0), _next(NULL) { }
iveresov@1546 142 BufferNode* next() const { return _next; }
iveresov@1546 143 void set_next(BufferNode* n) { _next = n; }
iveresov@1546 144 size_t index() const { return _index; }
iveresov@1546 145 void set_index(size_t i) { _index = i; }
iveresov@1546 146
iveresov@1546 147 // Align the size of the structure to the size of the pointer
iveresov@1546 148 static size_t aligned_size() {
iveresov@1546 149 static const size_t alignment = round_to(sizeof(BufferNode), sizeof(void*));
iveresov@1546 150 return alignment;
iveresov@1546 151 }
iveresov@1546 152
iveresov@1546 153 // BufferNode is allocated before the buffer.
iveresov@1546 154 // The chunk of memory that holds both of them is a block.
iveresov@1546 155
iveresov@1546 156 // Produce a new BufferNode given a buffer.
iveresov@1546 157 static BufferNode* new_from_buffer(void** buf) {
iveresov@1546 158 return new (make_block_from_buffer(buf)) BufferNode;
iveresov@1546 159 }
iveresov@1546 160
iveresov@1546 161 // The following are the required conversion routines:
iveresov@1546 162 static BufferNode* make_node_from_buffer(void** buf) {
iveresov@1546 163 return (BufferNode*)make_block_from_buffer(buf);
iveresov@1546 164 }
iveresov@1546 165 static void** make_buffer_from_node(BufferNode *node) {
iveresov@1546 166 return make_buffer_from_block(node);
iveresov@1546 167 }
iveresov@1546 168 static void* make_block_from_node(BufferNode *node) {
iveresov@1546 169 return (void*)node;
iveresov@1546 170 }
iveresov@1546 171 static void** make_buffer_from_block(void* p) {
iveresov@1546 172 return (void**)((char*)p + aligned_size());
iveresov@1546 173 }
iveresov@1546 174 static void* make_block_from_buffer(void** p) {
iveresov@1546 175 return (void*)((char*)p - aligned_size());
iveresov@1546 176 }
iveresov@1546 177 };
iveresov@1546 178
ysr@777 179 // A PtrQueueSet represents resources common to a set of pointer queues.
ysr@777 180 // In particular, the individual queues allocate buffers from this shared
ysr@777 181 // set, and return completed buffers to the set.
ysr@777 182 // All these variables are are protected by the TLOQ_CBL_mon. XXX ???
apetrusenko@984 183 class PtrQueueSet VALUE_OBJ_CLASS_SPEC {
ysr@777 184 protected:
ysr@777 185 Monitor* _cbl_mon; // Protects the fields below.
iveresov@1546 186 BufferNode* _completed_buffers_head;
iveresov@1546 187 BufferNode* _completed_buffers_tail;
iveresov@1546 188 int _n_completed_buffers;
iveresov@1546 189 int _process_completed_threshold;
ysr@777 190 volatile bool _process_completed;
ysr@777 191
ysr@777 192 // This (and the interpretation of the first element as a "next"
ysr@777 193 // pointer) are protected by the TLOQ_FL_lock.
ysr@777 194 Mutex* _fl_lock;
iveresov@1546 195 BufferNode* _buf_free_list;
ysr@777 196 size_t _buf_free_list_sz;
iveresov@1051 197 // Queue set can share a freelist. The _fl_owner variable
iveresov@1051 198 // specifies the owner. It is set to "this" by default.
iveresov@1051 199 PtrQueueSet* _fl_owner;
ysr@777 200
ysr@777 201 // The size of all buffers in the set.
ysr@777 202 size_t _sz;
ysr@777 203
ysr@777 204 bool _all_active;
ysr@777 205
ysr@777 206 // If true, notify_all on _cbl_mon when the threshold is reached.
ysr@777 207 bool _notify_when_complete;
ysr@777 208
ysr@777 209 // Maximum number of elements allowed on completed queue: after that,
ysr@777 210 // enqueuer does the work itself. Zero indicates no maximum.
ysr@777 211 int _max_completed_queue;
iveresov@1546 212 int _completed_queue_padding;
ysr@777 213
ysr@777 214 int completed_buffers_list_length();
ysr@777 215 void assert_completed_buffer_list_len_correct_locked();
ysr@777 216 void assert_completed_buffer_list_len_correct();
ysr@777 217
ysr@777 218 protected:
ysr@777 219 // A mutator thread does the the work of processing a buffer.
ysr@777 220 // Returns "true" iff the work is complete (and the buffer may be
ysr@777 221 // deallocated).
ysr@777 222 virtual bool mut_process_buffer(void** buf) {
ysr@777 223 ShouldNotReachHere();
ysr@777 224 return false;
ysr@777 225 }
ysr@777 226
ysr@777 227 public:
ysr@777 228 // Create an empty ptr queue set.
ysr@777 229 PtrQueueSet(bool notify_when_complete = false);
ysr@777 230
ysr@777 231 // Because of init-order concerns, we can't pass these as constructor
ysr@777 232 // arguments.
ysr@777 233 void initialize(Monitor* cbl_mon, Mutex* fl_lock,
iveresov@1546 234 int process_completed_threshold,
iveresov@1546 235 int max_completed_queue,
iveresov@1051 236 PtrQueueSet *fl_owner = NULL) {
ysr@777 237 _max_completed_queue = max_completed_queue;
iveresov@1546 238 _process_completed_threshold = process_completed_threshold;
iveresov@1546 239 _completed_queue_padding = 0;
ysr@777 240 assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?");
iveresov@1051 241 _cbl_mon = cbl_mon;
iveresov@1051 242 _fl_lock = fl_lock;
iveresov@1051 243 _fl_owner = (fl_owner != NULL) ? fl_owner : this;
ysr@777 244 }
ysr@777 245
ysr@777 246 // Return an empty oop array of size _sz (required to be non-zero).
ysr@777 247 void** allocate_buffer();
ysr@777 248
ysr@777 249 // Return an empty buffer to the free list. The "buf" argument is
ysr@777 250 // required to be a pointer to the head of an array of length "_sz".
ysr@777 251 void deallocate_buffer(void** buf);
ysr@777 252
ysr@777 253 // Declares that "buf" is a complete buffer.
iveresov@1546 254 void enqueue_complete_buffer(void** buf, size_t index = 0);
iveresov@1546 255
iveresov@1546 256 // To be invoked by the mutator.
iveresov@1546 257 bool process_or_enqueue_complete_buffer(void** buf);
ysr@777 258
ysr@777 259 bool completed_buffers_exist_dirty() {
ysr@777 260 return _n_completed_buffers > 0;
ysr@777 261 }
ysr@777 262
ysr@777 263 bool process_completed_buffers() { return _process_completed; }
iveresov@1546 264 void set_process_completed(bool x) { _process_completed = x; }
ysr@777 265
tonyp@1752 266 bool is_active() { return _all_active; }
ysr@777 267
ysr@777 268 // Set the buffer size. Should be called before any "enqueue" operation
ysr@777 269 // can be called. And should only be called once.
ysr@777 270 void set_buffer_size(size_t sz);
ysr@777 271
ysr@777 272 // Get the buffer size.
ysr@777 273 size_t buffer_size() { return _sz; }
ysr@777 274
iveresov@1546 275 // Get/Set the number of completed buffers that triggers log processing.
iveresov@1546 276 void set_process_completed_threshold(int sz) { _process_completed_threshold = sz; }
iveresov@1546 277 int process_completed_threshold() const { return _process_completed_threshold; }
ysr@777 278
ysr@777 279 // Must only be called at a safe point. Indicates that the buffer free
ysr@777 280 // list size may be reduced, if that is deemed desirable.
ysr@777 281 void reduce_free_list();
ysr@777 282
iveresov@1546 283 int completed_buffers_num() { return _n_completed_buffers; }
iveresov@1051 284
iveresov@1051 285 void merge_bufferlists(PtrQueueSet* src);
iveresov@1546 286
iveresov@1546 287 void set_max_completed_queue(int m) { _max_completed_queue = m; }
iveresov@1546 288 int max_completed_queue() { return _max_completed_queue; }
iveresov@1546 289
iveresov@1546 290 void set_completed_queue_padding(int padding) { _completed_queue_padding = padding; }
iveresov@1546 291 int completed_queue_padding() { return _completed_queue_padding; }
iveresov@1546 292
iveresov@1546 293 // Notify the consumer if the number of buffers crossed the threshold
iveresov@1546 294 void notify_if_necessary();
ysr@777 295 };

mercurial