src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp

Print this page
rev 3754 : 7189971: Implement CMSWaitDuration for non-incremental mode of CMS
Summary: In the incremental mode of CMS the CMSWaitDuration delays the iCMS cycle until after a scavenge. Implement the same for the non-incremental mode.
Reviewed-by:
Contributed-by: Michal Frajt <michal@frajt.eu>

*** 298,309 **** assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), "Should have been cleared"); } } ! // Wait until the next synchronous GC, a concurrent full gc request, ! // or a timeout, whichever is earlier. void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); if (_should_terminate || _collector->_full_gc_requested) { return; --- 298,308 ---- assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), "Should have been cleared"); } } ! // Wait until any cms_lock event void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); if (_should_terminate || _collector->_full_gc_requested) { return;
*** 313,331 **** clear_CMS_flag(CMS_cms_wants_token); assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), "Should not be set"); } void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { while (!_should_terminate) { if (CMSIncrementalMode) { icms_wait(); return; } else { // Wait until the next synchronous GC, a concurrent full gc // request or a timeout, whichever is earlier. ! wait_on_cms_lock(CMSWaitDuration); } // Check if we should start a CMS collection cycle if (_collector->shouldConcurrentCollect()) { return; } --- 312,395 ---- clear_CMS_flag(CMS_cms_wants_token); assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), "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_for_scavenge(CMSWaitDuration); } // Check if we should start a CMS collection cycle if (_collector->shouldConcurrentCollect()) { return; }