changeset 1840:4e0094bc41fa

6983311: G1: LoopTest hangs when run with -XX:+ExplicitInvokesConcurrent Summary: Clear the concurrent marking "in progress" flag while the FullGCCount_lock is held. This avoids a race that can cause back to back System.gc() calls, when ExplicitGCInvokesConcurrent is enabled, to fail to initiate a marking cycle causing the requesting thread to hang. Reviewed-by: tonyp, ysr
author johnc
date Fri, 01 Oct 2010 18:23:16 -0700
parents 8f6f7587d292
children 32a1f7bf0c21
files src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
diffstat 3 files changed, 14 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Thu Sep 30 12:15:13 2010 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Fri Oct 01 18:23:16 2010 -0700
@@ -303,9 +303,10 @@
 }
 
 void ConcurrentMarkThread::sleepBeforeNextCycle() {
-  clear_in_progress();
   // We join here because we don't want to do the "shouldConcurrentMark()"
   // below while the world is otherwise stopped.
+  assert(!in_progress(), "should have been cleared");
+
   MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
   while (!started()) {
     CGC_lock->wait(Mutex::_no_safepoint_check_flag);
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp	Thu Sep 30 12:15:13 2010 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp	Fri Oct 01 18:23:16 2010 -0700
@@ -69,12 +69,12 @@
 
   ConcurrentMark* cm()     { return _cm; }
 
-  void set_started()       { _started = true;  }
-  void clear_started()     { _started = false; }
+  void set_started()       { assert(!_in_progress, "cycle in progress"); _started = true;  }
+  void clear_started()     { assert(_in_progress, "must be starting a cycle"); _started = false; }
   bool started()           { return _started;  }
 
-  void set_in_progress()   { _in_progress = true;  }
-  void clear_in_progress() { _in_progress = false; }
+  void set_in_progress()   { assert(_started, "must be starting a cycle"); _in_progress = true;  }
+  void clear_in_progress() { assert(!_started, "must not be starting a new cycle"); _in_progress = false; }
   bool in_progress()       { return _in_progress;  }
 
   // This flag returns true from the moment a marking cycle is
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Sep 30 12:15:13 2010 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Oct 01 18:23:16 2010 -0700
@@ -1785,6 +1785,14 @@
 
   _full_collections_completed += 1;
 
+  // We need to clear the "in_progress" flag in the CM thread before
+  // we wake up any waiters (especially when ExplicitInvokesConcurrent
+  // is set) so that if a waiter requests another System.gc() it doesn't
+  // incorrectly see that a marking cyle is still in progress.
+  if (outer) {
+    _cmThread->clear_in_progress();
+  }
+
   // This notify_all() will ensure that a thread that called
   // System.gc() with (with ExplicitGCInvokesConcurrent set or not)
   // and it's waiting for a full GC to finish will be woken up. It is