diff src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp @ 794:315a5d70b295

6484957: G1: parallel concurrent refinement 6826318: G1: remove traversal-based refinement code Summary: Removed traversal-based refinement code as it's no longer used. Made the concurrent refinement (queue-based) parallel. Reviewed-by: tonyp
author iveresov
date Mon, 11 May 2009 16:30:56 -0700
parents 20c6f43950b5
children 215f81b4d9b3
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Thu May 07 17:09:48 2009 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Mon May 11 16:30:56 2009 -0700
@@ -30,12 +30,12 @@
 // The CM thread is created when the G1 garbage collector is used
 
 ConcurrentG1RefineThread::
-ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r) :
+ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, int worker_id) :
   ConcurrentGCThread(),
+  _worker_id(worker_id),
+  _active(false),
+  _next(next),
   _cg1r(cg1r),
-  _started(false),
-  _in_progress(false),
-  _do_traversal(false),
   _vtime_accum(0.0),
   _co_tracker(G1CRGroup),
   _interval_ms(5.0)
@@ -43,112 +43,6 @@
   create_and_start();
 }
 
-const long timeout = 200; // ms.
-
-void ConcurrentG1RefineThread::traversalBasedRefinement() {
-  _cg1r->wait_for_ConcurrentG1Refine_enabled();
-  MutexLocker x(G1ConcRefine_mon);
-  while (_cg1r->enabled()) {
-    MutexUnlocker ux(G1ConcRefine_mon);
-    ResourceMark rm;
-    HandleMark   hm;
-
-    if (G1TraceConcurrentRefinement) {
-      gclog_or_tty->print_cr("G1-Refine starting pass");
-    }
-    _sts.join();
-    bool no_sleep = _cg1r->refine();
-    _sts.leave();
-    if (!no_sleep) {
-      MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
-      // We do this only for the timeout; we don't expect this to be signalled.
-      CGC_lock->wait(Mutex::_no_safepoint_check_flag, timeout);
-    }
-  }
-}
-
-void ConcurrentG1RefineThread::queueBasedRefinement() {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-  // Wait for completed log buffers to exist.
-  {
-    MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
-    while (!_do_traversal && !dcqs.process_completed_buffers() &&
-           !_should_terminate) {
-      DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
-    }
-  }
-
-  if (_should_terminate) {
-    return;
-  }
-
-  // Now we take them off (this doesn't hold locks while it applies
-  // closures.)  (If we did a full collection, then we'll do a full
-  // traversal.
-  _sts.join();
-  if (_do_traversal) {
-    (void)_cg1r->refine();
-    switch (_cg1r->get_last_pya()) {
-    case PYA_cancel: case PYA_continue:
-      // Continue was caught and handled inside "refine".  If it's still
-      // "continue" when we get here, we're done.
-      _do_traversal = false;
-      break;
-    case PYA_restart:
-      assert(_do_traversal, "Because of Full GC.");
-      break;
-    }
-  } else {
-    int n_logs = 0;
-    int lower_limit = 0;
-    double start_vtime_sec; // only used when G1SmoothConcRefine is on
-    int prev_buffer_num; // only used when G1SmoothConcRefine is on
-
-    if (G1SmoothConcRefine) {
-      lower_limit = 0;
-      start_vtime_sec = os::elapsedVTime();
-      prev_buffer_num = (int) dcqs.completed_buffers_num();
-    } else {
-      lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
-    }
-    while (dcqs.apply_closure_to_completed_buffer(0, lower_limit)) {
-      double end_vtime_sec;
-      double elapsed_vtime_sec;
-      int elapsed_vtime_ms;
-      int curr_buffer_num;
-
-      if (G1SmoothConcRefine) {
-        end_vtime_sec = os::elapsedVTime();
-        elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
-        elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
-        curr_buffer_num = (int) dcqs.completed_buffers_num();
-
-        if (curr_buffer_num > prev_buffer_num ||
-            curr_buffer_num > DCQBarrierProcessCompletedThreshold) {
-          decreaseInterval(elapsed_vtime_ms);
-        } else if (curr_buffer_num < prev_buffer_num) {
-          increaseInterval(elapsed_vtime_ms);
-        }
-      }
-
-      sample_young_list_rs_lengths();
-      _co_tracker.update(false);
-
-      if (G1SmoothConcRefine) {
-        prev_buffer_num = curr_buffer_num;
-        _sts.leave();
-        os::sleep(Thread::current(), (jlong) _interval_ms, false);
-        _sts.join();
-        start_vtime_sec = os::elapsedVTime();
-      }
-      n_logs++;
-    }
-    // Make sure we harvest the PYA, if any.
-    (void)_cg1r->get_pya();
-  }
-  _sts.leave();
-}
-
 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1p = g1h->g1_policy();
@@ -184,15 +78,97 @@
   _co_tracker.start();
 
   while (!_should_terminate) {
-    // wait until started is set.
-    if (G1RSBarrierUseQueue) {
-      queueBasedRefinement();
+    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+    // Wait for completed log buffers to exist.
+    {
+      MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
+      while (((_worker_id == 0 && !dcqs.process_completed_buffers()) ||
+              (_worker_id > 0 && !is_active())) &&
+             !_should_terminate) {
+         DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
+      }
+    }
+
+    if (_should_terminate) {
+      return;
+    }
+
+    // Now we take them off (this doesn't hold locks while it applies
+    // closures.)  (If we did a full collection, then we'll do a full
+    // traversal.
+    _sts.join();
+    int n_logs = 0;
+    int lower_limit = 0;
+    double start_vtime_sec; // only used when G1SmoothConcRefine is on
+    int prev_buffer_num; // only used when G1SmoothConcRefine is on
+    // This thread activation threshold
+    int threshold = DCQBarrierProcessCompletedThreshold * _worker_id;
+    // Next thread activation threshold
+    int next_threshold = threshold + DCQBarrierProcessCompletedThreshold;
+    int deactivation_threshold = MAX2<int>(threshold - DCQBarrierProcessCompletedThreshold / 2, 0);
+
+    if (G1SmoothConcRefine) {
+      lower_limit = 0;
+      start_vtime_sec = os::elapsedVTime();
+      prev_buffer_num = (int) dcqs.completed_buffers_num();
     } else {
-      traversalBasedRefinement();
+      lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
     }
-    _sts.join();
-    _co_tracker.update();
+    while (dcqs.apply_closure_to_completed_buffer(_worker_id, lower_limit)) {
+      double end_vtime_sec;
+      double elapsed_vtime_sec;
+      int elapsed_vtime_ms;
+      int curr_buffer_num = (int) dcqs.completed_buffers_num();
+
+      if (G1SmoothConcRefine) {
+        end_vtime_sec = os::elapsedVTime();
+        elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
+        elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
+
+        if (curr_buffer_num > prev_buffer_num ||
+            curr_buffer_num > next_threshold) {
+          decreaseInterval(elapsed_vtime_ms);
+        } else if (curr_buffer_num < prev_buffer_num) {
+          increaseInterval(elapsed_vtime_ms);
+        }
+      }
+      if (_worker_id == 0) {
+        sample_young_list_rs_lengths();
+      } else if (curr_buffer_num < deactivation_threshold) {
+        // If the number of the buffer has fallen below our threshold
+        // we should deactivate. The predecessor will reactivate this
+        // thread should the number of the buffers cross the threshold again.
+        MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
+        deactivate();
+        if (G1TraceConcurrentRefinement) {
+          gclog_or_tty->print_cr("G1-Refine-deactivated worker %d", _worker_id);
+        }
+        break;
+      }
+      _co_tracker.update(false);
+
+      // Check if we need to activate the next thread.
+      if (curr_buffer_num > next_threshold && _next != NULL && !_next->is_active()) {
+        MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
+        _next->activate();
+        DirtyCardQ_CBL_mon->notify_all();
+        if (G1TraceConcurrentRefinement) {
+          gclog_or_tty->print_cr("G1-Refine-activated worker %d", _next->_worker_id);
+        }
+      }
+
+      if (G1SmoothConcRefine) {
+        prev_buffer_num = curr_buffer_num;
+        _sts.leave();
+        os::sleep(Thread::current(), (jlong) _interval_ms, false);
+        _sts.join();
+        start_vtime_sec = os::elapsedVTime();
+      }
+      n_logs++;
+    }
+    _co_tracker.update(false);
     _sts.leave();
+
     if (os::supports_vtime()) {
       _vtime_accum = (os::elapsedVTime() - _vtime_start);
     } else {
@@ -240,7 +216,3 @@
   Thread::print();
   gclog_or_tty->cr();
 }
-
-void ConcurrentG1RefineThread::set_do_traversal(bool b) {
-  _do_traversal = b;
-}