< prev index next >

src/hotspot/share/gc/g1/concurrentMarkThread.cpp

Print this page
rev 47419 : imported patch webrev.0

@@ -109,21 +109,35 @@
   void do_void(){
     _cm->cleanup();
   }
 };
 
-// Marking pauses can be scheduled flexibly, so we might delay marking to meet MMU.
-void ConcurrentMarkThread::delay_to_keep_mmu(G1Policy* g1_policy, bool remark) {
+// There are 3 reasons to use SuspendibleThreadSetJoiner.
+// 1. To avoid concurrency problem.
+//    - G1MMUTracker::add_pause(), when_sec() and its variation(when_ms() etc..) can be called
+//      concurrently from ConcurrentMarkThread and VMThread.
+// 2. If there is running young gc but not yet updated MMU, its gc time will be reflected at this MMU calculation.
+// 3. ConcurrentMarkThread will not sleep if there is young gc which makes MMU more accurate.
+double ConcurrentMarkThread::mmu_sleep_time(G1Policy* g1_policy, bool remark) {
+  SuspendibleThreadSetJoiner sts_join;
+
   const G1Analytics* analytics = g1_policy->analytics();
-  if (g1_policy->adaptive_young_list_length()) {
     double now = os::elapsedTime();
     double prediction_ms = remark ? analytics->predict_remark_time_ms()
                                   : analytics->predict_cleanup_time_ms();
     G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
-    jlong sleep_time_ms = mmu_tracker->when_ms(now, prediction_ms);
+  return mmu_tracker->when_ms(now, prediction_ms);
+}
+
+// Marking pauses can be scheduled flexibly, so we might delay marking to meet MMU.
+void ConcurrentMarkThread::delay_to_keep_mmu(G1Policy* g1_policy, bool remark) {
+  if (g1_policy->adaptive_young_list_length()) {
+    jlong sleep_time_ms = mmu_sleep_time(g1_policy, remark);
+    if (!cm()->has_aborted() && sleep_time_ms > 0) {
     os::sleep(this, sleep_time_ms, false);
   }
+  }
 }
 
 class G1ConcPhaseTimer : public GCTraceConcTimeImpl<LogLevel::Info, LOG_TAGS(gc, marking)> {
   G1ConcurrentMark* _cm;
 

@@ -347,13 +361,15 @@
       _vtime_accum = (end_time - _vtime_start);
 
       if (!cm()->has_aborted()) {
         delay_to_keep_mmu(g1_policy, false /* cleanup */);
 
+        if (!cm()->has_aborted()) {
         CMCleanUp cl_cl(_cm);
         VM_CGC_Operation op(&cl_cl, "Pause Cleanup");
         VMThread::execute(&op);
+        }
       } else {
         // We don't want to update the marking status if a GC pause
         // is already underway.
         SuspendibleThreadSetJoiner sts_join;
         g1h->collector_state()->set_mark_in_progress(false);
< prev index next >