src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp

changeset 1546
44f61c24ddab
parent 1454
035d2e036a9b
child 1717
b81f3572f355
     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    {

mercurial