1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Thu Jun 05 15:57:56 2008 -0700 1.3 @@ -0,0 +1,246 @@ 1.4 +/* 1.5 + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "incls/_precompiled.incl" 1.29 +#include "incls/_concurrentG1RefineThread.cpp.incl" 1.30 + 1.31 +// ======= Concurrent Mark Thread ======== 1.32 + 1.33 +// The CM thread is created when the G1 garbage collector is used 1.34 + 1.35 +ConcurrentG1RefineThread:: 1.36 +ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r) : 1.37 + ConcurrentGCThread(), 1.38 + _cg1r(cg1r), 1.39 + _started(false), 1.40 + _in_progress(false), 1.41 + _do_traversal(false), 1.42 + _vtime_accum(0.0), 1.43 + _co_tracker(G1CRGroup), 1.44 + _interval_ms(5.0) 1.45 +{ 1.46 + create_and_start(); 1.47 +} 1.48 + 1.49 +const long timeout = 200; // ms. 1.50 + 1.51 +void ConcurrentG1RefineThread::traversalBasedRefinement() { 1.52 + _cg1r->wait_for_ConcurrentG1Refine_enabled(); 1.53 + MutexLocker x(G1ConcRefine_mon); 1.54 + while (_cg1r->enabled()) { 1.55 + MutexUnlocker ux(G1ConcRefine_mon); 1.56 + ResourceMark rm; 1.57 + HandleMark hm; 1.58 + 1.59 + if (TraceG1Refine) gclog_or_tty->print_cr("G1-Refine starting pass"); 1.60 + _sts.join(); 1.61 + bool no_sleep = _cg1r->refine(); 1.62 + _sts.leave(); 1.63 + if (!no_sleep) { 1.64 + MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); 1.65 + // We do this only for the timeout; we don't expect this to be signalled. 1.66 + CGC_lock->wait(Mutex::_no_safepoint_check_flag, timeout); 1.67 + } 1.68 + } 1.69 +} 1.70 + 1.71 +void ConcurrentG1RefineThread::queueBasedRefinement() { 1.72 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.73 + // Wait for completed log buffers to exist. 1.74 + { 1.75 + MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); 1.76 + while (!_do_traversal && !dcqs.process_completed_buffers() && 1.77 + !_should_terminate) { 1.78 + DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag); 1.79 + } 1.80 + } 1.81 + 1.82 + if (_should_terminate) { 1.83 + return; 1.84 + } 1.85 + 1.86 + // Now we take them off (this doesn't hold locks while it applies 1.87 + // closures.) (If we did a full collection, then we'll do a full 1.88 + // traversal. 1.89 + _sts.join(); 1.90 + if (_do_traversal) { 1.91 + (void)_cg1r->refine(); 1.92 + switch (_cg1r->get_last_pya()) { 1.93 + case PYA_cancel: case PYA_continue: 1.94 + // Continue was caught and handled inside "refine". If it's still 1.95 + // "continue" when we get here, we're done. 1.96 + _do_traversal = false; 1.97 + break; 1.98 + case PYA_restart: 1.99 + assert(_do_traversal, "Because of Full GC."); 1.100 + break; 1.101 + } 1.102 + } else { 1.103 + int n_logs = 0; 1.104 + int lower_limit = 0; 1.105 + double start_vtime_sec; // only used when G1SmoothConcRefine is on 1.106 + int prev_buffer_num; // only used when G1SmoothConcRefine is on 1.107 + 1.108 + if (G1SmoothConcRefine) { 1.109 + lower_limit = 0; 1.110 + start_vtime_sec = os::elapsedVTime(); 1.111 + prev_buffer_num = (int) dcqs.completed_buffers_num(); 1.112 + } else { 1.113 + lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now. 1.114 + } 1.115 + while (dcqs.apply_closure_to_completed_buffer(0, lower_limit)) { 1.116 + double end_vtime_sec; 1.117 + double elapsed_vtime_sec; 1.118 + int elapsed_vtime_ms; 1.119 + int curr_buffer_num; 1.120 + 1.121 + if (G1SmoothConcRefine) { 1.122 + end_vtime_sec = os::elapsedVTime(); 1.123 + elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; 1.124 + elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0); 1.125 + curr_buffer_num = (int) dcqs.completed_buffers_num(); 1.126 + 1.127 + if (curr_buffer_num > prev_buffer_num || 1.128 + curr_buffer_num > DCQBarrierProcessCompletedThreshold) { 1.129 + decreaseInterval(elapsed_vtime_ms); 1.130 + } else if (curr_buffer_num < prev_buffer_num) { 1.131 + increaseInterval(elapsed_vtime_ms); 1.132 + } 1.133 + } 1.134 + 1.135 + sample_young_list_rs_lengths(); 1.136 + _co_tracker.update(false); 1.137 + 1.138 + if (G1SmoothConcRefine) { 1.139 + start_vtime_sec = os::elapsedVTime(); 1.140 + prev_buffer_num = curr_buffer_num; 1.141 + 1.142 + _sts.leave(); 1.143 + os::sleep(Thread::current(), (jlong) _interval_ms, false); 1.144 + _sts.join(); 1.145 + } 1.146 + 1.147 + n_logs++; 1.148 + } 1.149 + // Make sure we harvest the PYA, if any. 1.150 + (void)_cg1r->get_pya(); 1.151 + } 1.152 + _sts.leave(); 1.153 +} 1.154 + 1.155 +void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { 1.156 + G1CollectedHeap* g1h = G1CollectedHeap::heap(); 1.157 + G1CollectorPolicy* g1p = g1h->g1_policy(); 1.158 + if (g1p->adaptive_young_list_length()) { 1.159 + int regions_visited = 0; 1.160 + 1.161 + g1h->young_list_rs_length_sampling_init(); 1.162 + while (g1h->young_list_rs_length_sampling_more()) { 1.163 + g1h->young_list_rs_length_sampling_next(); 1.164 + ++regions_visited; 1.165 + 1.166 + // we try to yield every time we visit 10 regions 1.167 + if (regions_visited == 10) { 1.168 + if (_sts.should_yield()) { 1.169 + _sts.yield("G1 refine"); 1.170 + // we just abandon the iteration 1.171 + break; 1.172 + } 1.173 + regions_visited = 0; 1.174 + } 1.175 + } 1.176 + 1.177 + g1p->check_prediction_validity(); 1.178 + } 1.179 +} 1.180 + 1.181 +void ConcurrentG1RefineThread::run() { 1.182 + initialize_in_thread(); 1.183 + _vtime_start = os::elapsedVTime(); 1.184 + wait_for_universe_init(); 1.185 + 1.186 + _co_tracker.enable(); 1.187 + _co_tracker.start(); 1.188 + 1.189 + while (!_should_terminate) { 1.190 + // wait until started is set. 1.191 + if (G1RSBarrierUseQueue) { 1.192 + queueBasedRefinement(); 1.193 + } else { 1.194 + traversalBasedRefinement(); 1.195 + } 1.196 + _sts.join(); 1.197 + _co_tracker.update(); 1.198 + _sts.leave(); 1.199 + if (os::supports_vtime()) { 1.200 + _vtime_accum = (os::elapsedVTime() - _vtime_start); 1.201 + } else { 1.202 + _vtime_accum = 0.0; 1.203 + } 1.204 + } 1.205 + _sts.join(); 1.206 + _co_tracker.update(true); 1.207 + _sts.leave(); 1.208 + assert(_should_terminate, "just checking"); 1.209 + 1.210 + terminate(); 1.211 +} 1.212 + 1.213 + 1.214 +void ConcurrentG1RefineThread::yield() { 1.215 + if (TraceG1Refine) gclog_or_tty->print_cr("G1-Refine-yield"); 1.216 + _sts.yield("G1 refine"); 1.217 + if (TraceG1Refine) gclog_or_tty->print_cr("G1-Refine-yield-end"); 1.218 +} 1.219 + 1.220 +void ConcurrentG1RefineThread::stop() { 1.221 + // it is ok to take late safepoints here, if needed 1.222 + { 1.223 + MutexLockerEx mu(Terminator_lock); 1.224 + _should_terminate = true; 1.225 + } 1.226 + 1.227 + { 1.228 + MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); 1.229 + DirtyCardQ_CBL_mon->notify_all(); 1.230 + } 1.231 + 1.232 + { 1.233 + MutexLockerEx mu(Terminator_lock); 1.234 + while (!_has_terminated) { 1.235 + Terminator_lock->wait(); 1.236 + } 1.237 + } 1.238 + if (TraceG1Refine) gclog_or_tty->print_cr("G1-Refine-stop"); 1.239 +} 1.240 + 1.241 +void ConcurrentG1RefineThread::print() { 1.242 + gclog_or_tty->print("\"Concurrent G1 Refinement Thread\" "); 1.243 + Thread::print(); 1.244 + gclog_or_tty->cr(); 1.245 +} 1.246 + 1.247 +void ConcurrentG1RefineThread::set_do_traversal(bool b) { 1.248 + _do_traversal = b; 1.249 +}