1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,350 @@ 1.4 +/* 1.5 + * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +# include "incls/_precompiled.incl" 1.29 +# include "incls/_concurrentMarkSweepThread.cpp.incl" 1.30 + 1.31 +// ======= Concurrent Mark Sweep Thread ======== 1.32 + 1.33 +// The CMS thread is created when Concurrent Mark Sweep is used in the 1.34 +// older of two generations in a generational memory system. 1.35 + 1.36 +ConcurrentMarkSweepThread* 1.37 + ConcurrentMarkSweepThread::_cmst = NULL; 1.38 +CMSCollector* ConcurrentMarkSweepThread::_collector = NULL; 1.39 +bool ConcurrentMarkSweepThread::_should_terminate = false; 1.40 +int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil; 1.41 + 1.42 +volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; 1.43 +volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0; 1.44 + 1.45 +volatile bool ConcurrentMarkSweepThread::_icms_enabled = false; 1.46 +volatile bool ConcurrentMarkSweepThread::_should_run = false; 1.47 +// When icms is enabled, the icms thread is stopped until explicitly 1.48 +// started. 1.49 +volatile bool ConcurrentMarkSweepThread::_should_stop = true; 1.50 + 1.51 +SurrogateLockerThread* 1.52 + ConcurrentMarkSweepThread::_slt = NULL; 1.53 +SurrogateLockerThread::SLT_msg_type 1.54 + ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty; 1.55 +Monitor* 1.56 + ConcurrentMarkSweepThread::_sltMonitor = NULL; 1.57 + 1.58 +ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector) 1.59 + : ConcurrentGCThread() { 1.60 + assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set"); 1.61 + assert(_cmst == NULL, "CMS thread already created"); 1.62 + _cmst = this; 1.63 + assert(_collector == NULL, "Collector already set"); 1.64 + _collector = collector; 1.65 + 1.66 + set_name("Concurrent Mark-Sweep GC Thread"); 1.67 + 1.68 + if (os::create_thread(this, os::cgc_thread)) { 1.69 + // XXX: need to set this to low priority 1.70 + // unless "agressive mode" set; priority 1.71 + // should be just less than that of VMThread. 1.72 + os::set_priority(this, NearMaxPriority); 1.73 + if (!DisableStartThread) { 1.74 + os::start_thread(this); 1.75 + } 1.76 + } 1.77 + _sltMonitor = SLT_lock; 1.78 + set_icms_enabled(CMSIncrementalMode); 1.79 +} 1.80 + 1.81 +void ConcurrentMarkSweepThread::run() { 1.82 + assert(this == cmst(), "just checking"); 1.83 + 1.84 + this->record_stack_base_and_size(); 1.85 + this->initialize_thread_local_storage(); 1.86 + this->set_active_handles(JNIHandleBlock::allocate_block()); 1.87 + // From this time Thread::current() should be working. 1.88 + assert(this == Thread::current(), "just checking"); 1.89 + if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) { 1.90 + warning("Couldn't bind CMS thread to processor %u", CPUForCMSThread); 1.91 + } 1.92 + // Wait until Universe::is_fully_initialized() 1.93 + { 1.94 + CMSLoopCountWarn loopX("CMS::run", "waiting for " 1.95 + "Universe::is_fully_initialized()", 2); 1.96 + MutexLockerEx x(CGC_lock, true); 1.97 + set_CMS_flag(CMS_cms_wants_token); 1.98 + // Wait until Universe is initialized and all initialization is completed. 1.99 + while (!is_init_completed() && !Universe::is_fully_initialized() && 1.100 + !_should_terminate) { 1.101 + CGC_lock->wait(true, 200); 1.102 + loopX.tick(); 1.103 + } 1.104 + // Wait until the surrogate locker thread that will do 1.105 + // pending list locking on our behalf has been created. 1.106 + // We cannot start the SLT thread ourselves since we need 1.107 + // to be a JavaThread to do so. 1.108 + CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2); 1.109 + while (_slt == NULL && !_should_terminate) { 1.110 + CGC_lock->wait(true, 200); 1.111 + loopY.tick(); 1.112 + } 1.113 + clear_CMS_flag(CMS_cms_wants_token); 1.114 + } 1.115 + 1.116 + while (!_should_terminate) { 1.117 + sleepBeforeNextCycle(); 1.118 + if (_should_terminate) break; 1.119 + _collector->collect_in_background(false); // !clear_all_soft_refs 1.120 + } 1.121 + assert(_should_terminate, "just checking"); 1.122 + // Check that the state of any protocol for synchronization 1.123 + // between background (CMS) and foreground collector is "clean" 1.124 + // (i.e. will not potentially block the foreground collector, 1.125 + // requiring action by us). 1.126 + verify_ok_to_terminate(); 1.127 + // Signal that it is terminated 1.128 + { 1.129 + MutexLockerEx mu(Terminator_lock, 1.130 + Mutex::_no_safepoint_check_flag); 1.131 + assert(_cmst == this, "Weird!"); 1.132 + _cmst = NULL; 1.133 + Terminator_lock->notify(); 1.134 + } 1.135 + 1.136 + // Thread destructor usually does this.. 1.137 + ThreadLocalStorage::set_thread(NULL); 1.138 +} 1.139 + 1.140 +#ifndef PRODUCT 1.141 +void ConcurrentMarkSweepThread::verify_ok_to_terminate() const { 1.142 + assert(!(CGC_lock->owned_by_self() || cms_thread_has_cms_token() || 1.143 + cms_thread_wants_cms_token()), 1.144 + "Must renounce all worldly possessions and desires for nirvana"); 1.145 + _collector->verify_ok_to_terminate(); 1.146 +} 1.147 +#endif 1.148 + 1.149 +// create and start a new ConcurrentMarkSweep Thread for given CMS generation 1.150 +ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) { 1.151 + if (!_should_terminate) { 1.152 + assert(cmst() == NULL, "start() called twice?"); 1.153 + ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector); 1.154 + assert(cmst() == th, "Where did the just-created CMS thread go?"); 1.155 + return th; 1.156 + } 1.157 + return NULL; 1.158 +} 1.159 + 1.160 +void ConcurrentMarkSweepThread::stop() { 1.161 + if (CMSIncrementalMode) { 1.162 + // Disable incremental mode and wake up the thread so it notices the change. 1.163 + disable_icms(); 1.164 + start_icms(); 1.165 + } 1.166 + // it is ok to take late safepoints here, if needed 1.167 + { 1.168 + MutexLockerEx x(Terminator_lock); 1.169 + _should_terminate = true; 1.170 + } 1.171 + { // Now post a notify on CGC_lock so as to nudge 1.172 + // CMS thread(s) that might be slumbering in 1.173 + // sleepBeforeNextCycle. 1.174 + MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); 1.175 + CGC_lock->notify_all(); 1.176 + } 1.177 + { // Now wait until (all) CMS thread(s) have exited 1.178 + MutexLockerEx x(Terminator_lock); 1.179 + while(cmst() != NULL) { 1.180 + Terminator_lock->wait(); 1.181 + } 1.182 + } 1.183 +} 1.184 + 1.185 +void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) { 1.186 + assert(tc != NULL, "Null ThreadClosure"); 1.187 + if (_cmst != NULL) { 1.188 + tc->do_thread(_cmst); 1.189 + } 1.190 + assert(Universe::is_fully_initialized(), 1.191 + "Called too early, make sure heap is fully initialized"); 1.192 + if (_collector != NULL) { 1.193 + AbstractWorkGang* gang = _collector->conc_workers(); 1.194 + if (gang != NULL) { 1.195 + gang->threads_do(tc); 1.196 + } 1.197 + } 1.198 +} 1.199 + 1.200 +void ConcurrentMarkSweepThread::print_on(outputStream* st) const { 1.201 + st->print("\"%s\" ", name()); 1.202 + Thread::print_on(st); 1.203 + st->cr(); 1.204 +} 1.205 + 1.206 +void ConcurrentMarkSweepThread::print_all_on(outputStream* st) { 1.207 + if (_cmst != NULL) { 1.208 + _cmst->print_on(st); 1.209 + } 1.210 + if (_collector != NULL) { 1.211 + AbstractWorkGang* gang = _collector->conc_workers(); 1.212 + if (gang != NULL) { 1.213 + gang->print_worker_threads_on(st); 1.214 + } 1.215 + } 1.216 +} 1.217 + 1.218 +void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) { 1.219 + assert(UseConcMarkSweepGC, "just checking"); 1.220 + 1.221 + MutexLockerEx x(CGC_lock, 1.222 + Mutex::_no_safepoint_check_flag); 1.223 + if (!is_cms_thread) { 1.224 + assert(Thread::current()->is_VM_thread(), "Not a VM thread"); 1.225 + CMSSynchronousYieldRequest yr; 1.226 + while (CMS_flag_is_set(CMS_cms_has_token)) { 1.227 + // indicate that we want to get the token 1.228 + set_CMS_flag(CMS_vm_wants_token); 1.229 + CGC_lock->wait(true); 1.230 + } 1.231 + // claim the token and proceed 1.232 + clear_CMS_flag(CMS_vm_wants_token); 1.233 + set_CMS_flag(CMS_vm_has_token); 1.234 + } else { 1.235 + assert(Thread::current()->is_ConcurrentGC_thread(), 1.236 + "Not a CMS thread"); 1.237 + // The following barrier assumes there's only one CMS thread. 1.238 + // This will need to be modified is there are more CMS threads than one. 1.239 + while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) { 1.240 + set_CMS_flag(CMS_cms_wants_token); 1.241 + CGC_lock->wait(true); 1.242 + } 1.243 + // claim the token 1.244 + clear_CMS_flag(CMS_cms_wants_token); 1.245 + set_CMS_flag(CMS_cms_has_token); 1.246 + } 1.247 +} 1.248 + 1.249 +void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) { 1.250 + assert(UseConcMarkSweepGC, "just checking"); 1.251 + 1.252 + MutexLockerEx x(CGC_lock, 1.253 + Mutex::_no_safepoint_check_flag); 1.254 + if (!is_cms_thread) { 1.255 + assert(Thread::current()->is_VM_thread(), "Not a VM thread"); 1.256 + assert(CMS_flag_is_set(CMS_vm_has_token), "just checking"); 1.257 + clear_CMS_flag(CMS_vm_has_token); 1.258 + if (CMS_flag_is_set(CMS_cms_wants_token)) { 1.259 + // wake-up a waiting CMS thread 1.260 + CGC_lock->notify(); 1.261 + } 1.262 + assert(!CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token), 1.263 + "Should have been cleared"); 1.264 + } else { 1.265 + assert(Thread::current()->is_ConcurrentGC_thread(), 1.266 + "Not a CMS thread"); 1.267 + assert(CMS_flag_is_set(CMS_cms_has_token), "just checking"); 1.268 + clear_CMS_flag(CMS_cms_has_token); 1.269 + if (CMS_flag_is_set(CMS_vm_wants_token)) { 1.270 + // wake-up a waiting VM thread 1.271 + CGC_lock->notify(); 1.272 + } 1.273 + assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), 1.274 + "Should have been cleared"); 1.275 + } 1.276 +} 1.277 + 1.278 +// Wait until the next synchronous GC or a timeout, whichever is earlier. 1.279 +void ConcurrentMarkSweepThread::wait_on_cms_lock(long t) { 1.280 + MutexLockerEx x(CGC_lock, 1.281 + Mutex::_no_safepoint_check_flag); 1.282 + set_CMS_flag(CMS_cms_wants_token); // to provoke notifies 1.283 + CGC_lock->wait(Mutex::_no_safepoint_check_flag, t); 1.284 + clear_CMS_flag(CMS_cms_wants_token); 1.285 + assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), 1.286 + "Should not be set"); 1.287 +} 1.288 + 1.289 +void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { 1.290 + while (!_should_terminate) { 1.291 + if (CMSIncrementalMode) { 1.292 + icms_wait(); 1.293 + return; 1.294 + } else { 1.295 + // Wait until the next synchronous GC or a timeout, whichever is earlier 1.296 + wait_on_cms_lock(CMSWaitDuration); 1.297 + } 1.298 + // Check if we should start a CMS collection cycle 1.299 + if (_collector->shouldConcurrentCollect()) { 1.300 + return; 1.301 + } 1.302 + // .. collection criterion not yet met, let's go back 1.303 + // and wait some more 1.304 + } 1.305 +} 1.306 + 1.307 +// Incremental CMS 1.308 +void ConcurrentMarkSweepThread::start_icms() { 1.309 + assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); 1.310 + MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); 1.311 + trace_state("start_icms"); 1.312 + _should_run = true; 1.313 + iCMS_lock->notify_all(); 1.314 +} 1.315 + 1.316 +void ConcurrentMarkSweepThread::stop_icms() { 1.317 + assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); 1.318 + MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); 1.319 + if (!_should_stop) { 1.320 + trace_state("stop_icms"); 1.321 + _should_stop = true; 1.322 + _should_run = false; 1.323 + asynchronous_yield_request(); 1.324 + iCMS_lock->notify_all(); 1.325 + } 1.326 +} 1.327 + 1.328 +void ConcurrentMarkSweepThread::icms_wait() { 1.329 + assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); 1.330 + if (_should_stop && icms_enabled()) { 1.331 + MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); 1.332 + trace_state("pause_icms"); 1.333 + _collector->stats().stop_cms_timer(); 1.334 + while(!_should_run && icms_enabled()) { 1.335 + iCMS_lock->wait(Mutex::_no_safepoint_check_flag); 1.336 + } 1.337 + _collector->stats().start_cms_timer(); 1.338 + _should_stop = false; 1.339 + trace_state("pause_icms end"); 1.340 + } 1.341 +} 1.342 + 1.343 +// Note: this method, although exported by the ConcurrentMarkSweepThread, 1.344 +// which is a non-JavaThread, can only be called by a JavaThread. 1.345 +// Currently this is done at vm creation time (post-vm-init) by the 1.346 +// main/Primordial (Java)Thread. 1.347 +// XXX Consider changing this in the future to allow the CMS thread 1.348 +// itself to create this thread? 1.349 +void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) { 1.350 + assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC"); 1.351 + assert(_slt == NULL, "SLT already created"); 1.352 + _slt = SurrogateLockerThread::make(THREAD); 1.353 +}