Tue, 26 Jan 2010 16:52:29 -0800
6920090: G1: Disable ReduceInitialCardMarks at least until 6920109 is fixed
Summary: G1 now answers "no" to the query can_elide_initializing_store_barrier() in the product build. A debug flag allows alternate behaviour in debug builds.
Reviewed-by: iveresov, tonyp
1 /*
2 * Copyright 2001-2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
25 #include "incls/_precompiled.incl"
26 #include "incls/_concurrentG1RefineThread.cpp.incl"
28 ConcurrentG1RefineThread::
29 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
30 int worker_id_offset, int worker_id) :
31 ConcurrentGCThread(),
32 _worker_id_offset(worker_id_offset),
33 _worker_id(worker_id),
34 _active(false),
35 _next(next),
36 _monitor(NULL),
37 _cg1r(cg1r),
38 _vtime_accum(0.0)
39 {
41 // Each thread has its own monitor. The i-th thread is responsible for signalling
42 // to thread i+1 if the number of buffers in the queue exceeds a threashold for this
43 // thread. Monitors are also used to wake up the threads during termination.
44 // The 0th worker in notified by mutator threads and has a special monitor.
45 // The last worker is used for young gen rset size sampling.
46 if (worker_id > 0) {
47 _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true);
48 } else {
49 _monitor = DirtyCardQ_CBL_mon;
50 }
51 initialize();
52 create_and_start();
53 }
55 void ConcurrentG1RefineThread::initialize() {
56 if (_worker_id < cg1r()->worker_thread_num()) {
57 // Current thread activation threshold
58 _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(),
59 cg1r()->yellow_zone());
60 // A thread deactivates once the number of buffer reached a deactivation threshold
61 _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone());
62 } else {
63 set_active(true);
64 }
65 }
67 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
68 G1CollectedHeap* g1h = G1CollectedHeap::heap();
69 G1CollectorPolicy* g1p = g1h->g1_policy();
70 if (g1p->adaptive_young_list_length()) {
71 int regions_visited = 0;
72 g1h->young_list_rs_length_sampling_init();
73 while (g1h->young_list_rs_length_sampling_more()) {
74 g1h->young_list_rs_length_sampling_next();
75 ++regions_visited;
77 // we try to yield every time we visit 10 regions
78 if (regions_visited == 10) {
79 if (_sts.should_yield()) {
80 _sts.yield("G1 refine");
81 // we just abandon the iteration
82 break;
83 }
84 regions_visited = 0;
85 }
86 }
88 g1p->check_prediction_validity();
89 }
90 }
92 void ConcurrentG1RefineThread::run_young_rs_sampling() {
93 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
94 _vtime_start = os::elapsedVTime();
95 while(!_should_terminate) {
96 _sts.join();
97 sample_young_list_rs_lengths();
98 _sts.leave();
100 if (os::supports_vtime()) {
101 _vtime_accum = (os::elapsedVTime() - _vtime_start);
102 } else {
103 _vtime_accum = 0.0;
104 }
106 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
107 if (_should_terminate) {
108 break;
109 }
110 _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefineServiceInterval);
111 }
112 }
114 void ConcurrentG1RefineThread::wait_for_completed_buffers() {
115 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
116 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
117 while (!_should_terminate && !is_active()) {
118 _monitor->wait(Mutex::_no_safepoint_check_flag);
119 }
120 }
122 bool ConcurrentG1RefineThread::is_active() {
123 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
124 return _worker_id > 0 ? _active : dcqs.process_completed_buffers();
125 }
127 void ConcurrentG1RefineThread::activate() {
128 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
129 if (_worker_id > 0) {
130 if (G1TraceConcurrentRefinement) {
131 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
132 gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d",
133 _worker_id, _threshold, (int)dcqs.completed_buffers_num());
134 }
135 set_active(true);
136 } else {
137 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
138 dcqs.set_process_completed(true);
139 }
140 _monitor->notify();
141 }
143 void ConcurrentG1RefineThread::deactivate() {
144 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
145 if (_worker_id > 0) {
146 if (G1TraceConcurrentRefinement) {
147 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
148 gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d",
149 _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num());
150 }
151 set_active(false);
152 } else {
153 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
154 dcqs.set_process_completed(false);
155 }
156 }
158 void ConcurrentG1RefineThread::run() {
159 initialize_in_thread();
160 wait_for_universe_init();
162 if (_worker_id >= cg1r()->worker_thread_num()) {
163 run_young_rs_sampling();
164 terminate();
165 }
167 _vtime_start = os::elapsedVTime();
168 while (!_should_terminate) {
169 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
171 // Wait for work
172 wait_for_completed_buffers();
174 if (_should_terminate) {
175 break;
176 }
178 _sts.join();
180 do {
181 int curr_buffer_num = (int)dcqs.completed_buffers_num();
182 // If the number of the buffers falls down into the yellow zone,
183 // that means that the transition period after the evacuation pause has ended.
184 if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
185 dcqs.set_completed_queue_padding(0);
186 }
188 if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
189 // If the number of the buffer has fallen below our threshold
190 // we should deactivate. The predecessor will reactivate this
191 // thread should the number of the buffers cross the threshold again.
192 deactivate();
193 break;
194 }
196 // Check if we need to activate the next thread.
197 if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
198 _next->activate();
199 }
200 } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone()));
202 // We can exit the loop above while being active if there was a yield request.
203 if (is_active()) {
204 deactivate();
205 }
207 _sts.leave();
209 if (os::supports_vtime()) {
210 _vtime_accum = (os::elapsedVTime() - _vtime_start);
211 } else {
212 _vtime_accum = 0.0;
213 }
214 }
215 assert(_should_terminate, "just checking");
216 terminate();
217 }
220 void ConcurrentG1RefineThread::yield() {
221 if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-yield");
222 _sts.yield("G1 refine");
223 if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-yield-end");
224 }
226 void ConcurrentG1RefineThread::stop() {
227 // it is ok to take late safepoints here, if needed
228 {
229 MutexLockerEx mu(Terminator_lock);
230 _should_terminate = true;
231 }
233 {
234 MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
235 _monitor->notify();
236 }
238 {
239 MutexLockerEx mu(Terminator_lock);
240 while (!_has_terminated) {
241 Terminator_lock->wait();
242 }
243 }
244 if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-stop");
245 }
247 void ConcurrentG1RefineThread::print() const {
248 print_on(tty);
249 }
251 void ConcurrentG1RefineThread::print_on(outputStream* st) const {
252 st->print("\"G1 Concurrent Refinement Thread#%d\" ", _worker_id);
253 Thread::print_on(st);
254 st->cr();
255 }