1.1 --- a/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri Dec 11 09:30:48 2009 -0800 1.2 +++ b/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Wed Dec 16 15:12:51 2009 -0800 1.3 @@ -25,10 +25,6 @@ 1.4 #include "incls/_precompiled.incl" 1.5 #include "incls/_concurrentG1RefineThread.cpp.incl" 1.6 1.7 -// ======= Concurrent Mark Thread ======== 1.8 - 1.9 -// The CM thread is created when the G1 garbage collector is used 1.10 - 1.11 ConcurrentG1RefineThread:: 1.12 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, 1.13 int worker_id_offset, int worker_id) : 1.14 @@ -37,19 +33,42 @@ 1.15 _worker_id(worker_id), 1.16 _active(false), 1.17 _next(next), 1.18 + _monitor(NULL), 1.19 _cg1r(cg1r), 1.20 - _vtime_accum(0.0), 1.21 - _interval_ms(5.0) 1.22 + _vtime_accum(0.0) 1.23 { 1.24 + 1.25 + // Each thread has its own monitor. The i-th thread is responsible for signalling 1.26 + // to thread i+1 if the number of buffers in the queue exceeds a threashold for this 1.27 + // thread. Monitors are also used to wake up the threads during termination. 1.28 + // The 0th worker in notified by mutator threads and has a special monitor. 1.29 + // The last worker is used for young gen rset size sampling. 1.30 + if (worker_id > 0) { 1.31 + _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true); 1.32 + } else { 1.33 + _monitor = DirtyCardQ_CBL_mon; 1.34 + } 1.35 + initialize(); 1.36 create_and_start(); 1.37 } 1.38 1.39 +void ConcurrentG1RefineThread::initialize() { 1.40 + if (_worker_id < cg1r()->worker_thread_num()) { 1.41 + // Current thread activation threshold 1.42 + _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), 1.43 + cg1r()->yellow_zone()); 1.44 + // A thread deactivates once the number of buffer reached a deactivation threshold 1.45 + _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone()); 1.46 + } else { 1.47 + set_active(true); 1.48 + } 1.49 +} 1.50 + 1.51 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { 1.52 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 1.53 G1CollectorPolicy* g1p = g1h->g1_policy(); 1.54 if (g1p->adaptive_young_list_length()) { 1.55 int regions_visited = 0; 1.56 - 1.57 g1h->young_list_rs_length_sampling_init(); 1.58 while (g1h->young_list_rs_length_sampling_more()) { 1.59 g1h->young_list_rs_length_sampling_next(); 1.60 @@ -70,99 +89,121 @@ 1.61 } 1.62 } 1.63 1.64 +void ConcurrentG1RefineThread::run_young_rs_sampling() { 1.65 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.66 + _vtime_start = os::elapsedVTime(); 1.67 + while(!_should_terminate) { 1.68 + _sts.join(); 1.69 + sample_young_list_rs_lengths(); 1.70 + _sts.leave(); 1.71 + 1.72 + if (os::supports_vtime()) { 1.73 + _vtime_accum = (os::elapsedVTime() - _vtime_start); 1.74 + } else { 1.75 + _vtime_accum = 0.0; 1.76 + } 1.77 + 1.78 + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); 1.79 + if (_should_terminate) { 1.80 + break; 1.81 + } 1.82 + _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefineServiceInterval); 1.83 + } 1.84 +} 1.85 + 1.86 +void ConcurrentG1RefineThread::wait_for_completed_buffers() { 1.87 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.88 + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); 1.89 + while (!_should_terminate && !is_active()) { 1.90 + _monitor->wait(Mutex::_no_safepoint_check_flag); 1.91 + } 1.92 +} 1.93 + 1.94 +bool ConcurrentG1RefineThread::is_active() { 1.95 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.96 + return _worker_id > 0 ? _active : dcqs.process_completed_buffers(); 1.97 +} 1.98 + 1.99 +void ConcurrentG1RefineThread::activate() { 1.100 + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); 1.101 + if (_worker_id > 0) { 1.102 + if (G1TraceConcurrentRefinement) { 1.103 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.104 + gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d", 1.105 + _worker_id, _threshold, (int)dcqs.completed_buffers_num()); 1.106 + } 1.107 + set_active(true); 1.108 + } else { 1.109 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.110 + dcqs.set_process_completed(true); 1.111 + } 1.112 + _monitor->notify(); 1.113 +} 1.114 + 1.115 +void ConcurrentG1RefineThread::deactivate() { 1.116 + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); 1.117 + if (_worker_id > 0) { 1.118 + if (G1TraceConcurrentRefinement) { 1.119 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.120 + gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d", 1.121 + _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num()); 1.122 + } 1.123 + set_active(false); 1.124 + } else { 1.125 + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.126 + dcqs.set_process_completed(false); 1.127 + } 1.128 +} 1.129 + 1.130 void ConcurrentG1RefineThread::run() { 1.131 initialize_in_thread(); 1.132 - _vtime_start = os::elapsedVTime(); 1.133 wait_for_universe_init(); 1.134 1.135 + if (_worker_id >= cg1r()->worker_thread_num()) { 1.136 + run_young_rs_sampling(); 1.137 + terminate(); 1.138 + } 1.139 + 1.140 + _vtime_start = os::elapsedVTime(); 1.141 while (!_should_terminate) { 1.142 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 1.143 - // Wait for completed log buffers to exist. 1.144 - { 1.145 - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); 1.146 - while (((_worker_id == 0 && !dcqs.process_completed_buffers()) || 1.147 - (_worker_id > 0 && !is_active())) && 1.148 - !_should_terminate) { 1.149 - DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag); 1.150 - } 1.151 + 1.152 + // Wait for work 1.153 + wait_for_completed_buffers(); 1.154 + 1.155 + if (_should_terminate) { 1.156 + break; 1.157 } 1.158 1.159 - if (_should_terminate) { 1.160 - return; 1.161 - } 1.162 + _sts.join(); 1.163 1.164 - // Now we take them off (this doesn't hold locks while it applies 1.165 - // closures.) (If we did a full collection, then we'll do a full 1.166 - // traversal. 1.167 - _sts.join(); 1.168 - int n_logs = 0; 1.169 - int lower_limit = 0; 1.170 - double start_vtime_sec; // only used when G1SmoothConcRefine is on 1.171 - int prev_buffer_num; // only used when G1SmoothConcRefine is on 1.172 - // This thread activation threshold 1.173 - int threshold = G1UpdateBufferQueueProcessingThreshold * _worker_id; 1.174 - // Next thread activation threshold 1.175 - int next_threshold = threshold + G1UpdateBufferQueueProcessingThreshold; 1.176 - int deactivation_threshold = MAX2<int>(threshold - G1UpdateBufferQueueProcessingThreshold / 2, 0); 1.177 + do { 1.178 + int curr_buffer_num = (int)dcqs.completed_buffers_num(); 1.179 + // If the number of the buffers falls down into the yellow zone, 1.180 + // that means that the transition period after the evacuation pause has ended. 1.181 + if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { 1.182 + dcqs.set_completed_queue_padding(0); 1.183 + } 1.184 1.185 - if (G1SmoothConcRefine) { 1.186 - lower_limit = 0; 1.187 - start_vtime_sec = os::elapsedVTime(); 1.188 - prev_buffer_num = (int) dcqs.completed_buffers_num(); 1.189 - } else { 1.190 - lower_limit = G1UpdateBufferQueueProcessingThreshold / 4; // For now. 1.191 - } 1.192 - while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, lower_limit)) { 1.193 - double end_vtime_sec; 1.194 - double elapsed_vtime_sec; 1.195 - int elapsed_vtime_ms; 1.196 - int curr_buffer_num = (int) dcqs.completed_buffers_num(); 1.197 - 1.198 - if (G1SmoothConcRefine) { 1.199 - end_vtime_sec = os::elapsedVTime(); 1.200 - elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; 1.201 - elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0); 1.202 - 1.203 - if (curr_buffer_num > prev_buffer_num || 1.204 - curr_buffer_num > next_threshold) { 1.205 - decreaseInterval(elapsed_vtime_ms); 1.206 - } else if (curr_buffer_num < prev_buffer_num) { 1.207 - increaseInterval(elapsed_vtime_ms); 1.208 - } 1.209 - } 1.210 - if (_worker_id == 0) { 1.211 - sample_young_list_rs_lengths(); 1.212 - } else if (curr_buffer_num < deactivation_threshold) { 1.213 + if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { 1.214 // If the number of the buffer has fallen below our threshold 1.215 // we should deactivate. The predecessor will reactivate this 1.216 // thread should the number of the buffers cross the threshold again. 1.217 - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); 1.218 deactivate(); 1.219 - if (G1TraceConcurrentRefinement) { 1.220 - gclog_or_tty->print_cr("G1-Refine-deactivated worker %d", _worker_id); 1.221 - } 1.222 break; 1.223 } 1.224 1.225 // Check if we need to activate the next thread. 1.226 - if (curr_buffer_num > next_threshold && _next != NULL && !_next->is_active()) { 1.227 - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); 1.228 + if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { 1.229 _next->activate(); 1.230 - DirtyCardQ_CBL_mon->notify_all(); 1.231 - if (G1TraceConcurrentRefinement) { 1.232 - gclog_or_tty->print_cr("G1-Refine-activated worker %d", _next->_worker_id); 1.233 - } 1.234 } 1.235 + } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone())); 1.236 1.237 - if (G1SmoothConcRefine) { 1.238 - prev_buffer_num = curr_buffer_num; 1.239 - _sts.leave(); 1.240 - os::sleep(Thread::current(), (jlong) _interval_ms, false); 1.241 - _sts.join(); 1.242 - start_vtime_sec = os::elapsedVTime(); 1.243 - } 1.244 - n_logs++; 1.245 + // We can exit the loop above while being active if there was a yield request. 1.246 + if (is_active()) { 1.247 + deactivate(); 1.248 } 1.249 + 1.250 _sts.leave(); 1.251 1.252 if (os::supports_vtime()) { 1.253 @@ -172,7 +213,6 @@ 1.254 } 1.255 } 1.256 assert(_should_terminate, "just checking"); 1.257 - 1.258 terminate(); 1.259 } 1.260 1.261 @@ -191,8 +231,8 @@ 1.262 } 1.263 1.264 { 1.265 - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); 1.266 - DirtyCardQ_CBL_mon->notify_all(); 1.267 + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); 1.268 + _monitor->notify(); 1.269 } 1.270 1.271 {