void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) { assert(UseConcMarkSweepGC, "just checking"); MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); if (!is_cms_thread) { assert(Thread::current()->is_VM_thread(), "Not a VM thread"); assert(CMS_flag_is_set(CMS_vm_has_token), "just checking"); clear_CMS_flag(CMS_vm_has_token); if (CMS_flag_is_set(CMS_cms_wants_token)) { // wake-up a waiting CMS thread CGC_lock->notify(); } assert(!CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token), "Should have been cleared"); } else { assert(Thread::current()->is_ConcurrentGC_thread(), "Not a CMS thread"); assert(CMS_flag_is_set(CMS_cms_has_token), "just checking"); clear_CMS_flag(CMS_cms_has_token); if (CMS_flag_is_set(CMS_vm_wants_token)) { // wake-up a waiting VM thread CGC_lock->notify(); } assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), "Should have been cleared"); } }
void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) { assert(UseConcMarkSweepGC, "just checking"); MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); if (!is_cms_thread) { assert(Thread::current()->is_VM_thread(), "Not a VM thread"); CMSSynchronousYieldRequest yr; while (CMS_flag_is_set(CMS_cms_has_token)) { // indicate that we want to get the token set_CMS_flag(CMS_vm_wants_token); CGC_lock->wait(true); } // claim the token and proceed clear_CMS_flag(CMS_vm_wants_token); set_CMS_flag(CMS_vm_has_token); } else { assert(Thread::current()->is_ConcurrentGC_thread(), "Not a CMS thread"); // The following barrier assumes there's only one CMS thread. // This will need to be modified is there are more CMS threads than one. while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) { set_CMS_flag(CMS_cms_wants_token); CGC_lock->wait(true); } // claim the token clear_CMS_flag(CMS_cms_wants_token); set_CMS_flag(CMS_cms_has_token); } }
void ConcurrentMarkSweepThread::run() { assert(this == cmst(), "just checking"); this->record_stack_base_and_size(); this->initialize_thread_local_storage(); this->set_active_handles(JNIHandleBlock::allocate_block()); // From this time Thread::current() should be working. assert(this == Thread::current(), "just checking"); if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) { warning("Couldn't bind CMS thread to processor %u", CPUForCMSThread); } // Wait until Universe::is_fully_initialized() { CMSLoopCountWarn loopX("CMS::run", "waiting for " "Universe::is_fully_initialized()", 2); MutexLockerEx x(CGC_lock, true); set_CMS_flag(CMS_cms_wants_token); // Wait until Universe is initialized and all initialization is completed. while (!is_init_completed() && !Universe::is_fully_initialized() && !_should_terminate) { CGC_lock->wait(true, 200); loopX.tick(); } // Wait until the surrogate locker thread that will do // pending list locking on our behalf has been created. // We cannot start the SLT thread ourselves since we need // to be a JavaThread to do so. CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2); while (_slt == NULL && !_should_terminate) { CGC_lock->wait(true, 200); loopY.tick(); } clear_CMS_flag(CMS_cms_wants_token); } while (!_should_terminate) { sleepBeforeNextCycle(); if (_should_terminate) break; GCCause::Cause cause = _collector->_full_gc_requested ? _collector->_full_gc_cause : GCCause::_cms_concurrent_mark; _collector->collect_in_background(false, cause); } assert(_should_terminate, "just checking"); // Check that the state of any protocol for synchronization // between background (CMS) and foreground collector is "clean" // (i.e. will not potentially block the foreground collector, // requiring action by us). verify_ok_to_terminate(); // Signal that it is terminated { MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag); assert(_cmst == this, "Weird!"); _cmst = NULL; Terminator_lock->notify(); } // Thread destructor usually does this.. ThreadLocalStorage::set_thread(NULL); }
// Wait until the next synchronous GC or a timeout, whichever is earlier. void ConcurrentMarkSweepThread::wait_on_cms_lock(long t) { MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); set_CMS_flag(CMS_cms_wants_token); // to provoke notifies CGC_lock->wait(Mutex::_no_safepoint_check_flag, t); 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(long t_millis) { 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, t_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"); }
// 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); } } }