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;
}