7189971: Implement CMSWaitDuration for non-incremental mode of CMS
Reviewed-by: jmasa, johnc, ysr
Contributed-by: michal@frajt.eu
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Fri Mar 01 04:58:31 2013 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Fri Feb 01 17:02:36 2013 -0800
@@ -300,8 +300,7 @@
}
}
-// Wait until the next synchronous GC, a concurrent full gc request,
-// or a timeout, whichever is earlier.
+// Wait until any cms_lock event
void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {
MutexLockerEx x(CGC_lock,
Mutex::_no_safepoint_check_flag);
@@ -315,15 +314,100 @@
"Should not be set");
}
+// Wait until the next synchronous GC, a concurrent full gc request,
+// or a timeout, whichever is earlier.
+void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) {
+ // Wait time in millis or 0 value representing infinite wait for a scavenge
+ assert(t_millis >= 0, "Wait time for scavenge should be 0 or positive");
+
+ GenCollectedHeap* gch = GenCollectedHeap::heap();
+ double start_time_secs = os::elapsedTime();
+ double end_time_secs = start_time_secs + (t_millis / ((double) MILLIUNITS));
+
+ // Total collections count before waiting loop
+ unsigned int before_count;
+ {
+ MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
+ before_count = gch->total_collections();
+ }
+
+ unsigned int loop_count = 0;
+
+ while(!_should_terminate) {
+ double now_time = os::elapsedTime();
+ long wait_time_millis;
+
+ if(t_millis != 0) {
+ // New wait limit
+ wait_time_millis = (long) ((end_time_secs - now_time) * MILLIUNITS);
+ if(wait_time_millis <= 0) {
+ // Wait time is over
+ break;
+ }
+ } else {
+ // No wait limit, wait if necessary forever
+ wait_time_millis = 0;
+ }
+
+ // Wait until the next event or the remaining timeout
+ {
+ MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
+
+ if (_should_terminate || _collector->_full_gc_requested) {
+ return;
+ }
+ set_CMS_flag(CMS_cms_wants_token); // to provoke notifies
+ assert(t_millis == 0 || wait_time_millis > 0, "Sanity");
+ CGC_lock->wait(Mutex::_no_safepoint_check_flag, wait_time_millis);
+ clear_CMS_flag(CMS_cms_wants_token);
+ assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
+ "Should not be set");
+ }
+
+ // Extra wait time check before entering the heap lock to get the collection count
+ if(t_millis != 0 && os::elapsedTime() >= end_time_secs) {
+ // Wait time is over
+ break;
+ }
+
+ // Total collections count after the event
+ unsigned int after_count;
+ {
+ MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
+ after_count = gch->total_collections();
+ }
+
+ if(before_count != after_count) {
+ // There was a collection - success
+ break;
+ }
+
+ // Too many loops warning
+ if(++loop_count == 0) {
+ warning("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1);
+ }
+ }
+}
+
void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {
while (!_should_terminate) {
if (CMSIncrementalMode) {
icms_wait();
+ if(CMSWaitDuration >= 0) {
+ // Wait until the next synchronous GC, a concurrent full gc
+ // request or a timeout, whichever is earlier.
+ wait_on_cms_lock_for_scavenge(CMSWaitDuration);
+ }
return;
} else {
- // Wait until the next synchronous GC, a concurrent full gc
- // request or a timeout, whichever is earlier.
- wait_on_cms_lock(CMSWaitDuration);
+ if(CMSWaitDuration >= 0) {
+ // Wait until the next synchronous GC, a concurrent full gc
+ // request or a timeout, whichever is earlier.
+ wait_on_cms_lock_for_scavenge(CMSWaitDuration);
+ } else {
+ // Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently
+ wait_on_cms_lock(CMSCheckInterval);
+ }
}
// Check if we should start a CMS collection cycle
if (_collector->shouldConcurrentCollect()) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Fri Mar 01 04:58:31 2013 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Fri Feb 01 17:02:36 2013 -0800
@@ -130,6 +130,12 @@
// A concurrent full gc request terminates the wait.
void wait_on_cms_lock(long t_millis);
+ // Wait on CMS lock until the next synchronous GC
+ // or given timeout, whichever is earlier. A timeout value
+ // of 0 indicates that there is no upper bound on the wait time.
+ // A concurrent full gc request terminates the wait.
+ void wait_on_cms_lock_for_scavenge(long t_millis);
+
// The CMS thread will yield during the work portion of its cycle
// only when requested to. Both synchronous and asychronous requests
// are provided:
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Mar 01 04:58:31 2013 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Feb 01 17:02:36 2013 -0800
@@ -1751,6 +1751,10 @@
manageable(intx, CMSWaitDuration, 2000, \
"Time in milliseconds that CMS thread waits for young GC") \
\
+ develop(uintx, CMSCheckInterval, 1000, \
+ "Interval in milliseconds that CMS thread checks if it " \
+ "should start a collection cycle") \
+ \
product(bool, CMSYield, true, \
"Yield between steps of concurrent mark & sweep") \
\