--- old/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp 2012-10-25 12:49:34.806607869 -0700 +++ new/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp 2012-10-25 12:49:34.611308265 -0700 @@ -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,80 @@ "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 for any cms_lock event when timeout not specified (0 millis) + if (t_millis == 0) { + wait_on_cms_lock(t_millis); + return; + } + + GenCollectedHeap* gch = GenCollectedHeap::heap(); + double start_time = os::elapsedTime(); + double end_time = start_time + (t_millis / 1000.0); + + // Total collections count before waiting loop + unsigned int before_count; + { + MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag); + before_count = gch->total_collections(); + } + + while (true) { + double now_time = os::elapsedTime(); + long wait_time_millis = (long)((end_time - now_time) * 1000.0); + + if (wait_time_millis <= 0) { + // Wait time is over + break; + } + + // 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 + 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 (os::elapsedTime() >= end_time) { + // 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; + } + } +} + void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { while (!_should_terminate) { if (CMSIncrementalMode) { icms_wait(); + if (CMSWaitDuration > 0) { + 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); + wait_on_cms_lock_for_scavenge(CMSWaitDuration); } // Check if we should start a CMS collection cycle if (_collector->shouldConcurrentCollect()) { --- old/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp 2012-10-25 12:49:36.254859730 -0700 +++ new/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp 2012-10-25 12:49:36.059583135 -0700 @@ -135,12 +135,18 @@ return CMS_flag_is_set(CMS_cms_wants_token); } - // Wait on CMS lock until the next synchronous GC + // Wait on CMS lock until the next event // 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(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: