< prev index next >

src/share/vm/gc/g1/g1ConcurrentMark.cpp

Print this page

        

@@ -439,11 +439,11 @@
   _has_overflown(false),
   _concurrent(false),
   _has_aborted(false),
   _restart_for_overflow(false),
   _concurrent_marking_in_progress(false),
-  _concurrent_phase_started(false),
+  _concurrent_phase_status(ConcPhaseNotStarted),
 
   // _verbose_level set below
 
   _init_times(),
   _remark_times(), _remark_mark_times(), _remark_weak_ref_times(),

@@ -1006,22 +1006,49 @@
     root_regions()->scan_finished();
   }
 }
 
 void G1ConcurrentMark::register_concurrent_phase_start(const char* title) {
-  assert(!_concurrent_phase_started, "Sanity");
-  _concurrent_phase_started = true;
+  uint old_val = 0;
+  do {
+    old_val = Atomic::cmpxchg(ConcPhaseStarted, &_concurrent_phase_status, ConcPhaseNotStarted);
+  } while (old_val != ConcPhaseNotStarted);
   _g1h->gc_timer_cm()->register_gc_concurrent_start(title);
 }
 
-void G1ConcurrentMark::register_concurrent_phase_end() {
-  if (_concurrent_phase_started) {
-    _concurrent_phase_started = false;
+void G1ConcurrentMark::register_concurrent_phase_end_common(bool end_timer) {
+  if (_concurrent_phase_status == ConcPhaseNotStarted) {
+    return;
+  }
+
+  uint old_val = Atomic::cmpxchg(ConcPhaseStopping, &_concurrent_phase_status, ConcPhaseStarted);
+  if (old_val == ConcPhaseStarted) {
     _g1h->gc_timer_cm()->register_gc_concurrent_end();
+    // If 'end_timer' is true, we came here to end timer which needs concurrent phase ended.
+    // We need to end it before changing the status to 'ConcPhaseNotStarted' to prevent
+    // starting a new concurrent phase by 'ConcurrentMarkThread'.
+    if (end_timer) {
+      _g1h->gc_timer_cm()->register_gc_end();
+    }
+    old_val = Atomic::cmpxchg(ConcPhaseNotStarted, &_concurrent_phase_status, ConcPhaseStopping);
+    assert(old_val == ConcPhaseStopping, "Should not have changed since we entered this scope.");
+  } else {
+    do {
+      // Let other thread finish changing '_concurrent_phase_status' to 'ConcPhaseNotStarted'.
+      os::naked_short_sleep(1);
+    } while (_concurrent_phase_status != ConcPhaseNotStarted);
   }
 }
 
+void G1ConcurrentMark::register_concurrent_phase_end() {
+  register_concurrent_phase_end_common(false);
+}
+
+void G1ConcurrentMark::register_concurrent_gc_end() {
+  register_concurrent_phase_end_common(true);
+}
+
 void G1ConcurrentMark::markFromRoots() {
   // we might be tempted to assert that:
   // assert(asynch == !SafepointSynchronize::is_at_safepoint(),
   //        "inconsistent argument?");
   // However that wouldn't be right, because it's possible that

@@ -2603,13 +2630,10 @@
                                  false, /* new active value */
                                  satb_mq_set.is_active() /* expected_active */);
 
   _g1h->trace_heap_after_concurrent_cycle();
 
-  // Close any open concurrent phase timing
-  register_concurrent_phase_end();
-
   _g1h->register_concurrent_cycle_end();
 }
 
 static void print_ms_time_info(const char* prefix, const char* name,
                                NumberSeq& ns) {
< prev index next >