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

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

author
tonyp
date
Fri, 01 Oct 2010 16:43:05 -0400
changeset 2197
6e0aac35bfa9
parent 2060
2d160770d2e5
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 /*
johnc@2060 2 * Copyright (c) 2001, 2010, 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 class FreeIdSet;
ysr@777 26
ysr@777 27 // A closure class for processing card table entries. Note that we don't
ysr@777 28 // require these closure objects to be stack-allocated.
ysr@777 29 class CardTableEntryClosure: public CHeapObj {
ysr@777 30 public:
ysr@777 31 // Process the card whose card table entry is "card_ptr". If returns
ysr@777 32 // "false", terminate the iteration early.
ysr@777 33 virtual bool do_card_ptr(jbyte* card_ptr, int worker_i = 0) = 0;
ysr@777 34 };
ysr@777 35
ysr@777 36 // A ptrQueue whose elements are "oops", pointers to object heads.
ysr@777 37 class DirtyCardQueue: public PtrQueue {
ysr@777 38 public:
ysr@777 39 DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) :
tonyp@2197 40 // Dirty card queues are always active, so we create them with their
tonyp@2197 41 // active field set to true.
tonyp@2197 42 PtrQueue(qset_, perm, true /* active */) { }
tonyp@2197 43
ysr@777 44 // Apply the closure to all elements, and reset the index to make the
ysr@777 45 // buffer empty. If a closure application returns "false", return
ysr@777 46 // "false" immediately, halting the iteration. If "consume" is true,
ysr@777 47 // deletes processed entries from logs.
ysr@777 48 bool apply_closure(CardTableEntryClosure* cl,
ysr@777 49 bool consume = true,
ysr@777 50 size_t worker_i = 0);
ysr@777 51
ysr@777 52 // Apply the closure to all elements of "buf", down to "index"
ysr@777 53 // (inclusive.) If returns "false", then a closure application returned
ysr@777 54 // "false", and we return immediately. If "consume" is true, entries are
ysr@777 55 // set to NULL as they are processed, so they will not be processed again
ysr@777 56 // later.
ysr@777 57 static bool apply_closure_to_buffer(CardTableEntryClosure* cl,
ysr@777 58 void** buf, size_t index, size_t sz,
ysr@777 59 bool consume = true,
ysr@777 60 int worker_i = 0);
ysr@777 61 void **get_buf() { return _buf;}
ysr@777 62 void set_buf(void **buf) {_buf = buf;}
ysr@777 63 size_t get_index() { return _index;}
ysr@777 64 void reinitialize() { _buf = 0; _sz = 0; _index = 0;}
ysr@777 65 };
ysr@777 66
ysr@777 67
ysr@777 68
ysr@777 69 class DirtyCardQueueSet: public PtrQueueSet {
ysr@777 70 CardTableEntryClosure* _closure;
ysr@777 71
ysr@777 72 DirtyCardQueue _shared_dirty_card_queue;
ysr@777 73
ysr@777 74 // Override.
ysr@777 75 bool mut_process_buffer(void** buf);
ysr@777 76
ysr@777 77 // Protected by the _cbl_mon.
ysr@777 78 FreeIdSet* _free_ids;
ysr@777 79
ysr@777 80 // The number of completed buffers processed by mutator and rs thread,
ysr@777 81 // respectively.
ysr@777 82 jint _processed_buffers_mut;
ysr@777 83 jint _processed_buffers_rs_thread;
ysr@777 84
ysr@777 85 public:
iveresov@1546 86 DirtyCardQueueSet(bool notify_when_complete = true);
ysr@777 87
ysr@777 88 void initialize(Monitor* cbl_mon, Mutex* fl_lock,
iveresov@1546 89 int process_completed_threshold,
iveresov@1546 90 int max_completed_queue,
iveresov@1546 91 Mutex* lock, PtrQueueSet* fl_owner = NULL);
ysr@777 92
ysr@777 93 // The number of parallel ids that can be claimed to allow collector or
ysr@777 94 // mutator threads to do card-processing work.
ysr@777 95 static size_t num_par_ids();
ysr@777 96
ysr@777 97 static void handle_zero_index_for_thread(JavaThread* t);
ysr@777 98
ysr@777 99 // Register "blk" as "the closure" for all queues. Only one such closure
ysr@777 100 // is allowed. The "apply_closure_to_completed_buffer" method will apply
ysr@777 101 // this closure to a completed buffer, and "iterate_closure_all_threads"
ysr@777 102 // applies it to partially-filled buffers (the latter should only be done
ysr@777 103 // with the world stopped).
ysr@777 104 void set_closure(CardTableEntryClosure* closure);
ysr@777 105
ysr@777 106 // If there is a registered closure for buffers, apply it to all entries
ysr@777 107 // in all currently-active buffers. This should only be applied at a
ysr@777 108 // safepoint. (Currently must not be called in parallel; this should
ysr@777 109 // change in the future.) If "consume" is true, processed entries are
ysr@777 110 // discarded.
ysr@777 111 void iterate_closure_all_threads(bool consume = true,
ysr@777 112 size_t worker_i = 0);
ysr@777 113
ysr@777 114 // If there exists some completed buffer, pop it, then apply the
ysr@777 115 // registered closure to all its elements, nulling out those elements
ysr@777 116 // processed. If all elements are processed, returns "true". If no
ysr@777 117 // completed buffers exist, returns false. If a completed buffer exists,
ysr@777 118 // but is only partially completed before a "yield" happens, the
ysr@777 119 // partially completed buffer (with its processed elements set to NULL)
ysr@777 120 // is returned to the completed buffer set, and this call returns false.
ysr@777 121 bool apply_closure_to_completed_buffer(int worker_i = 0,
ysr@777 122 int stop_at = 0,
johnc@1525 123 bool during_pause = false);
johnc@1525 124
johnc@2060 125 // If there exists some completed buffer, pop it, then apply the
johnc@2060 126 // specified closure to all its elements, nulling out those elements
johnc@2060 127 // processed. If all elements are processed, returns "true". If no
johnc@2060 128 // completed buffers exist, returns false. If a completed buffer exists,
johnc@2060 129 // but is only partially completed before a "yield" happens, the
johnc@2060 130 // partially completed buffer (with its processed elements set to NULL)
johnc@2060 131 // is returned to the completed buffer set, and this call returns false.
johnc@2060 132 bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
johnc@2060 133 int worker_i = 0,
johnc@2060 134 int stop_at = 0,
johnc@2060 135 bool during_pause = false);
johnc@2060 136
johnc@2060 137 // Helper routine for the above.
johnc@2060 138 bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
johnc@2060 139 int worker_i,
iveresov@1546 140 BufferNode* nd);
ysr@777 141
iveresov@1546 142 BufferNode* get_completed_buffer(int stop_at);
johnc@1525 143
ysr@777 144 // Applies the current closure to all completed buffers,
ysr@777 145 // non-consumptively.
ysr@777 146 void apply_closure_to_all_completed_buffers();
ysr@777 147
ysr@777 148 DirtyCardQueue* shared_dirty_card_queue() {
ysr@777 149 return &_shared_dirty_card_queue;
ysr@777 150 }
ysr@777 151
johnc@2060 152 // Deallocate any completed log buffers
johnc@2060 153 void clear();
johnc@2060 154
ysr@777 155 // If a full collection is happening, reset partial logs, and ignore
ysr@777 156 // completed ones: the full collection will make them all irrelevant.
ysr@777 157 void abandon_logs();
ysr@777 158
ysr@777 159 // If any threads have partial logs, add them to the global list of logs.
ysr@777 160 void concatenate_logs();
ysr@777 161 void clear_n_completed_buffers() { _n_completed_buffers = 0;}
ysr@777 162
ysr@777 163 jint processed_buffers_mut() {
ysr@777 164 return _processed_buffers_mut;
ysr@777 165 }
ysr@777 166 jint processed_buffers_rs_thread() {
ysr@777 167 return _processed_buffers_rs_thread;
ysr@777 168 }
ysr@777 169
ysr@777 170 };

mercurial