Wed, 22 Jan 2014 17:42:23 -0800
Merge
duke@435 | 1 | /* |
mikael@6198 | 2 | * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #include "precompiled.hpp" |
stefank@2314 | 26 | #include "classfile/systemDictionary.hpp" |
stefank@2314 | 27 | #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp" |
stefank@2314 | 28 | #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" |
stefank@2314 | 29 | #include "memory/genCollectedHeap.hpp" |
stefank@2314 | 30 | #include "oops/instanceRefKlass.hpp" |
stefank@2314 | 31 | #include "oops/oop.inline.hpp" |
stefank@2314 | 32 | #include "runtime/init.hpp" |
stefank@2314 | 33 | #include "runtime/interfaceSupport.hpp" |
stefank@2314 | 34 | #include "runtime/java.hpp" |
stefank@2314 | 35 | #include "runtime/javaCalls.hpp" |
stefank@2314 | 36 | #include "runtime/mutexLocker.hpp" |
stefank@2314 | 37 | #include "runtime/os.hpp" |
stefank@2314 | 38 | #include "runtime/vmThread.hpp" |
duke@435 | 39 | |
duke@435 | 40 | // ======= Concurrent Mark Sweep Thread ======== |
duke@435 | 41 | |
duke@435 | 42 | // The CMS thread is created when Concurrent Mark Sweep is used in the |
duke@435 | 43 | // older of two generations in a generational memory system. |
duke@435 | 44 | |
duke@435 | 45 | ConcurrentMarkSweepThread* |
duke@435 | 46 | ConcurrentMarkSweepThread::_cmst = NULL; |
duke@435 | 47 | CMSCollector* ConcurrentMarkSweepThread::_collector = NULL; |
duke@435 | 48 | bool ConcurrentMarkSweepThread::_should_terminate = false; |
duke@435 | 49 | int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil; |
duke@435 | 50 | |
duke@435 | 51 | volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; |
duke@435 | 52 | volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0; |
duke@435 | 53 | |
ysr@2647 | 54 | volatile jint ConcurrentMarkSweepThread::_icms_disabled = 0; |
duke@435 | 55 | volatile bool ConcurrentMarkSweepThread::_should_run = false; |
duke@435 | 56 | // When icms is enabled, the icms thread is stopped until explicitly |
duke@435 | 57 | // started. |
duke@435 | 58 | volatile bool ConcurrentMarkSweepThread::_should_stop = true; |
duke@435 | 59 | |
duke@435 | 60 | SurrogateLockerThread* |
duke@435 | 61 | ConcurrentMarkSweepThread::_slt = NULL; |
duke@435 | 62 | SurrogateLockerThread::SLT_msg_type |
duke@435 | 63 | ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty; |
duke@435 | 64 | Monitor* |
duke@435 | 65 | ConcurrentMarkSweepThread::_sltMonitor = NULL; |
duke@435 | 66 | |
duke@435 | 67 | ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector) |
duke@435 | 68 | : ConcurrentGCThread() { |
duke@435 | 69 | assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set"); |
duke@435 | 70 | assert(_cmst == NULL, "CMS thread already created"); |
duke@435 | 71 | _cmst = this; |
duke@435 | 72 | assert(_collector == NULL, "Collector already set"); |
duke@435 | 73 | _collector = collector; |
duke@435 | 74 | |
duke@435 | 75 | set_name("Concurrent Mark-Sweep GC Thread"); |
duke@435 | 76 | |
duke@435 | 77 | if (os::create_thread(this, os::cgc_thread)) { |
phh@3481 | 78 | // An old comment here said: "Priority should be just less |
phh@3481 | 79 | // than that of VMThread". Since the VMThread runs at |
phh@3481 | 80 | // NearMaxPriority, the old comment was inaccurate, but |
phh@3481 | 81 | // changing the default priority to NearMaxPriority-1 |
phh@3481 | 82 | // could change current behavior, so the default of |
phh@3481 | 83 | // NearMaxPriority stays in place. |
phh@3481 | 84 | // |
phh@3481 | 85 | // Note that there's a possibility of the VMThread |
phh@3481 | 86 | // starving if UseCriticalCMSThreadPriority is on. |
phh@3481 | 87 | // That won't happen on Solaris for various reasons, |
phh@3481 | 88 | // but may well happen on non-Solaris platforms. |
phh@3481 | 89 | int native_prio; |
phh@3481 | 90 | if (UseCriticalCMSThreadPriority) { |
phh@3481 | 91 | native_prio = os::java_to_os_priority[CriticalPriority]; |
phh@3481 | 92 | } else { |
phh@3481 | 93 | native_prio = os::java_to_os_priority[NearMaxPriority]; |
phh@3481 | 94 | } |
phh@3481 | 95 | os::set_native_priority(this, native_prio); |
phh@3481 | 96 | |
duke@435 | 97 | if (!DisableStartThread) { |
duke@435 | 98 | os::start_thread(this); |
duke@435 | 99 | } |
duke@435 | 100 | } |
duke@435 | 101 | _sltMonitor = SLT_lock; |
ysr@2647 | 102 | assert(!CMSIncrementalMode || icms_is_enabled(), "Error"); |
duke@435 | 103 | } |
duke@435 | 104 | |
duke@435 | 105 | void ConcurrentMarkSweepThread::run() { |
duke@435 | 106 | assert(this == cmst(), "just checking"); |
duke@435 | 107 | |
duke@435 | 108 | this->record_stack_base_and_size(); |
duke@435 | 109 | this->initialize_thread_local_storage(); |
duke@435 | 110 | this->set_active_handles(JNIHandleBlock::allocate_block()); |
duke@435 | 111 | // From this time Thread::current() should be working. |
duke@435 | 112 | assert(this == Thread::current(), "just checking"); |
duke@435 | 113 | if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) { |
duke@435 | 114 | warning("Couldn't bind CMS thread to processor %u", CPUForCMSThread); |
duke@435 | 115 | } |
duke@435 | 116 | // Wait until Universe::is_fully_initialized() |
duke@435 | 117 | { |
duke@435 | 118 | CMSLoopCountWarn loopX("CMS::run", "waiting for " |
duke@435 | 119 | "Universe::is_fully_initialized()", 2); |
duke@435 | 120 | MutexLockerEx x(CGC_lock, true); |
duke@435 | 121 | set_CMS_flag(CMS_cms_wants_token); |
duke@435 | 122 | // Wait until Universe is initialized and all initialization is completed. |
duke@435 | 123 | while (!is_init_completed() && !Universe::is_fully_initialized() && |
duke@435 | 124 | !_should_terminate) { |
duke@435 | 125 | CGC_lock->wait(true, 200); |
duke@435 | 126 | loopX.tick(); |
duke@435 | 127 | } |
duke@435 | 128 | // Wait until the surrogate locker thread that will do |
duke@435 | 129 | // pending list locking on our behalf has been created. |
duke@435 | 130 | // We cannot start the SLT thread ourselves since we need |
duke@435 | 131 | // to be a JavaThread to do so. |
duke@435 | 132 | CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2); |
duke@435 | 133 | while (_slt == NULL && !_should_terminate) { |
duke@435 | 134 | CGC_lock->wait(true, 200); |
duke@435 | 135 | loopY.tick(); |
duke@435 | 136 | } |
duke@435 | 137 | clear_CMS_flag(CMS_cms_wants_token); |
duke@435 | 138 | } |
duke@435 | 139 | |
duke@435 | 140 | while (!_should_terminate) { |
duke@435 | 141 | sleepBeforeNextCycle(); |
duke@435 | 142 | if (_should_terminate) break; |
sla@5237 | 143 | GCCause::Cause cause = _collector->_full_gc_requested ? |
sla@5237 | 144 | _collector->_full_gc_cause : GCCause::_cms_concurrent_mark; |
sla@5237 | 145 | _collector->collect_in_background(false, cause); |
duke@435 | 146 | } |
duke@435 | 147 | assert(_should_terminate, "just checking"); |
duke@435 | 148 | // Check that the state of any protocol for synchronization |
duke@435 | 149 | // between background (CMS) and foreground collector is "clean" |
duke@435 | 150 | // (i.e. will not potentially block the foreground collector, |
duke@435 | 151 | // requiring action by us). |
duke@435 | 152 | verify_ok_to_terminate(); |
duke@435 | 153 | // Signal that it is terminated |
duke@435 | 154 | { |
duke@435 | 155 | MutexLockerEx mu(Terminator_lock, |
duke@435 | 156 | Mutex::_no_safepoint_check_flag); |
duke@435 | 157 | assert(_cmst == this, "Weird!"); |
duke@435 | 158 | _cmst = NULL; |
duke@435 | 159 | Terminator_lock->notify(); |
duke@435 | 160 | } |
duke@435 | 161 | |
duke@435 | 162 | // Thread destructor usually does this.. |
duke@435 | 163 | ThreadLocalStorage::set_thread(NULL); |
duke@435 | 164 | } |
duke@435 | 165 | |
duke@435 | 166 | #ifndef PRODUCT |
duke@435 | 167 | void ConcurrentMarkSweepThread::verify_ok_to_terminate() const { |
duke@435 | 168 | assert(!(CGC_lock->owned_by_self() || cms_thread_has_cms_token() || |
duke@435 | 169 | cms_thread_wants_cms_token()), |
duke@435 | 170 | "Must renounce all worldly possessions and desires for nirvana"); |
duke@435 | 171 | _collector->verify_ok_to_terminate(); |
duke@435 | 172 | } |
duke@435 | 173 | #endif |
duke@435 | 174 | |
duke@435 | 175 | // create and start a new ConcurrentMarkSweep Thread for given CMS generation |
duke@435 | 176 | ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) { |
duke@435 | 177 | if (!_should_terminate) { |
duke@435 | 178 | assert(cmst() == NULL, "start() called twice?"); |
duke@435 | 179 | ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector); |
duke@435 | 180 | assert(cmst() == th, "Where did the just-created CMS thread go?"); |
duke@435 | 181 | return th; |
duke@435 | 182 | } |
duke@435 | 183 | return NULL; |
duke@435 | 184 | } |
duke@435 | 185 | |
duke@435 | 186 | void ConcurrentMarkSweepThread::stop() { |
duke@435 | 187 | if (CMSIncrementalMode) { |
duke@435 | 188 | // Disable incremental mode and wake up the thread so it notices the change. |
duke@435 | 189 | disable_icms(); |
duke@435 | 190 | start_icms(); |
duke@435 | 191 | } |
duke@435 | 192 | // it is ok to take late safepoints here, if needed |
duke@435 | 193 | { |
duke@435 | 194 | MutexLockerEx x(Terminator_lock); |
duke@435 | 195 | _should_terminate = true; |
duke@435 | 196 | } |
duke@435 | 197 | { // Now post a notify on CGC_lock so as to nudge |
duke@435 | 198 | // CMS thread(s) that might be slumbering in |
duke@435 | 199 | // sleepBeforeNextCycle. |
duke@435 | 200 | MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); |
duke@435 | 201 | CGC_lock->notify_all(); |
duke@435 | 202 | } |
duke@435 | 203 | { // Now wait until (all) CMS thread(s) have exited |
duke@435 | 204 | MutexLockerEx x(Terminator_lock); |
duke@435 | 205 | while(cmst() != NULL) { |
duke@435 | 206 | Terminator_lock->wait(); |
duke@435 | 207 | } |
duke@435 | 208 | } |
duke@435 | 209 | } |
duke@435 | 210 | |
duke@435 | 211 | void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) { |
duke@435 | 212 | assert(tc != NULL, "Null ThreadClosure"); |
duke@435 | 213 | if (_cmst != NULL) { |
duke@435 | 214 | tc->do_thread(_cmst); |
duke@435 | 215 | } |
duke@435 | 216 | assert(Universe::is_fully_initialized(), |
duke@435 | 217 | "Called too early, make sure heap is fully initialized"); |
duke@435 | 218 | if (_collector != NULL) { |
duke@435 | 219 | AbstractWorkGang* gang = _collector->conc_workers(); |
duke@435 | 220 | if (gang != NULL) { |
duke@435 | 221 | gang->threads_do(tc); |
duke@435 | 222 | } |
duke@435 | 223 | } |
duke@435 | 224 | } |
duke@435 | 225 | |
duke@435 | 226 | void ConcurrentMarkSweepThread::print_on(outputStream* st) const { |
duke@435 | 227 | st->print("\"%s\" ", name()); |
duke@435 | 228 | Thread::print_on(st); |
duke@435 | 229 | st->cr(); |
duke@435 | 230 | } |
duke@435 | 231 | |
duke@435 | 232 | void ConcurrentMarkSweepThread::print_all_on(outputStream* st) { |
duke@435 | 233 | if (_cmst != NULL) { |
duke@435 | 234 | _cmst->print_on(st); |
dholmes@4077 | 235 | st->cr(); |
duke@435 | 236 | } |
duke@435 | 237 | if (_collector != NULL) { |
duke@435 | 238 | AbstractWorkGang* gang = _collector->conc_workers(); |
duke@435 | 239 | if (gang != NULL) { |
duke@435 | 240 | gang->print_worker_threads_on(st); |
duke@435 | 241 | } |
duke@435 | 242 | } |
duke@435 | 243 | } |
duke@435 | 244 | |
duke@435 | 245 | void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) { |
duke@435 | 246 | assert(UseConcMarkSweepGC, "just checking"); |
duke@435 | 247 | |
duke@435 | 248 | MutexLockerEx x(CGC_lock, |
duke@435 | 249 | Mutex::_no_safepoint_check_flag); |
duke@435 | 250 | if (!is_cms_thread) { |
duke@435 | 251 | assert(Thread::current()->is_VM_thread(), "Not a VM thread"); |
duke@435 | 252 | CMSSynchronousYieldRequest yr; |
duke@435 | 253 | while (CMS_flag_is_set(CMS_cms_has_token)) { |
duke@435 | 254 | // indicate that we want to get the token |
duke@435 | 255 | set_CMS_flag(CMS_vm_wants_token); |
duke@435 | 256 | CGC_lock->wait(true); |
duke@435 | 257 | } |
duke@435 | 258 | // claim the token and proceed |
duke@435 | 259 | clear_CMS_flag(CMS_vm_wants_token); |
duke@435 | 260 | set_CMS_flag(CMS_vm_has_token); |
duke@435 | 261 | } else { |
duke@435 | 262 | assert(Thread::current()->is_ConcurrentGC_thread(), |
duke@435 | 263 | "Not a CMS thread"); |
duke@435 | 264 | // The following barrier assumes there's only one CMS thread. |
duke@435 | 265 | // This will need to be modified is there are more CMS threads than one. |
duke@435 | 266 | while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) { |
duke@435 | 267 | set_CMS_flag(CMS_cms_wants_token); |
duke@435 | 268 | CGC_lock->wait(true); |
duke@435 | 269 | } |
duke@435 | 270 | // claim the token |
duke@435 | 271 | clear_CMS_flag(CMS_cms_wants_token); |
duke@435 | 272 | set_CMS_flag(CMS_cms_has_token); |
duke@435 | 273 | } |
duke@435 | 274 | } |
duke@435 | 275 | |
duke@435 | 276 | void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) { |
duke@435 | 277 | assert(UseConcMarkSweepGC, "just checking"); |
duke@435 | 278 | |
duke@435 | 279 | MutexLockerEx x(CGC_lock, |
duke@435 | 280 | Mutex::_no_safepoint_check_flag); |
duke@435 | 281 | if (!is_cms_thread) { |
duke@435 | 282 | assert(Thread::current()->is_VM_thread(), "Not a VM thread"); |
duke@435 | 283 | assert(CMS_flag_is_set(CMS_vm_has_token), "just checking"); |
duke@435 | 284 | clear_CMS_flag(CMS_vm_has_token); |
duke@435 | 285 | if (CMS_flag_is_set(CMS_cms_wants_token)) { |
duke@435 | 286 | // wake-up a waiting CMS thread |
duke@435 | 287 | CGC_lock->notify(); |
duke@435 | 288 | } |
duke@435 | 289 | assert(!CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token), |
duke@435 | 290 | "Should have been cleared"); |
duke@435 | 291 | } else { |
duke@435 | 292 | assert(Thread::current()->is_ConcurrentGC_thread(), |
duke@435 | 293 | "Not a CMS thread"); |
duke@435 | 294 | assert(CMS_flag_is_set(CMS_cms_has_token), "just checking"); |
duke@435 | 295 | clear_CMS_flag(CMS_cms_has_token); |
duke@435 | 296 | if (CMS_flag_is_set(CMS_vm_wants_token)) { |
duke@435 | 297 | // wake-up a waiting VM thread |
duke@435 | 298 | CGC_lock->notify(); |
duke@435 | 299 | } |
duke@435 | 300 | assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), |
duke@435 | 301 | "Should have been cleared"); |
duke@435 | 302 | } |
duke@435 | 303 | } |
duke@435 | 304 | |
jmasa@4679 | 305 | // Wait until any cms_lock event |
ysr@2242 | 306 | void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) { |
duke@435 | 307 | MutexLockerEx x(CGC_lock, |
duke@435 | 308 | Mutex::_no_safepoint_check_flag); |
ysr@2242 | 309 | if (_should_terminate || _collector->_full_gc_requested) { |
ysr@2242 | 310 | return; |
ysr@2242 | 311 | } |
duke@435 | 312 | set_CMS_flag(CMS_cms_wants_token); // to provoke notifies |
ysr@2242 | 313 | CGC_lock->wait(Mutex::_no_safepoint_check_flag, t_millis); |
duke@435 | 314 | clear_CMS_flag(CMS_cms_wants_token); |
duke@435 | 315 | assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), |
duke@435 | 316 | "Should not be set"); |
duke@435 | 317 | } |
duke@435 | 318 | |
jmasa@4679 | 319 | // Wait until the next synchronous GC, a concurrent full gc request, |
jmasa@4679 | 320 | // or a timeout, whichever is earlier. |
jmasa@4679 | 321 | void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) { |
jmasa@4679 | 322 | // Wait time in millis or 0 value representing infinite wait for a scavenge |
jmasa@4679 | 323 | assert(t_millis >= 0, "Wait time for scavenge should be 0 or positive"); |
jmasa@4679 | 324 | |
jmasa@4679 | 325 | GenCollectedHeap* gch = GenCollectedHeap::heap(); |
jmasa@4679 | 326 | double start_time_secs = os::elapsedTime(); |
jmasa@4679 | 327 | double end_time_secs = start_time_secs + (t_millis / ((double) MILLIUNITS)); |
jmasa@4679 | 328 | |
jmasa@4679 | 329 | // Total collections count before waiting loop |
jmasa@4679 | 330 | unsigned int before_count; |
jmasa@4679 | 331 | { |
jmasa@4679 | 332 | MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag); |
jmasa@4679 | 333 | before_count = gch->total_collections(); |
jmasa@4679 | 334 | } |
jmasa@4679 | 335 | |
jmasa@4679 | 336 | unsigned int loop_count = 0; |
jmasa@4679 | 337 | |
jmasa@4679 | 338 | while(!_should_terminate) { |
jmasa@4679 | 339 | double now_time = os::elapsedTime(); |
jmasa@4679 | 340 | long wait_time_millis; |
jmasa@4679 | 341 | |
jmasa@4679 | 342 | if(t_millis != 0) { |
jmasa@4679 | 343 | // New wait limit |
jmasa@4679 | 344 | wait_time_millis = (long) ((end_time_secs - now_time) * MILLIUNITS); |
jmasa@4679 | 345 | if(wait_time_millis <= 0) { |
jmasa@4679 | 346 | // Wait time is over |
jmasa@4679 | 347 | break; |
jmasa@4679 | 348 | } |
jmasa@4679 | 349 | } else { |
jmasa@4679 | 350 | // No wait limit, wait if necessary forever |
jmasa@4679 | 351 | wait_time_millis = 0; |
jmasa@4679 | 352 | } |
jmasa@4679 | 353 | |
jmasa@4679 | 354 | // Wait until the next event or the remaining timeout |
jmasa@4679 | 355 | { |
jmasa@4679 | 356 | MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); |
jmasa@4679 | 357 | |
jmasa@4679 | 358 | if (_should_terminate || _collector->_full_gc_requested) { |
jmasa@4679 | 359 | return; |
jmasa@4679 | 360 | } |
jmasa@4679 | 361 | set_CMS_flag(CMS_cms_wants_token); // to provoke notifies |
jmasa@4679 | 362 | assert(t_millis == 0 || wait_time_millis > 0, "Sanity"); |
jmasa@4679 | 363 | CGC_lock->wait(Mutex::_no_safepoint_check_flag, wait_time_millis); |
jmasa@4679 | 364 | clear_CMS_flag(CMS_cms_wants_token); |
jmasa@4679 | 365 | assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token), |
jmasa@4679 | 366 | "Should not be set"); |
jmasa@4679 | 367 | } |
jmasa@4679 | 368 | |
jmasa@4679 | 369 | // Extra wait time check before entering the heap lock to get the collection count |
jmasa@4679 | 370 | if(t_millis != 0 && os::elapsedTime() >= end_time_secs) { |
jmasa@4679 | 371 | // Wait time is over |
jmasa@4679 | 372 | break; |
jmasa@4679 | 373 | } |
jmasa@4679 | 374 | |
jmasa@4679 | 375 | // Total collections count after the event |
jmasa@4679 | 376 | unsigned int after_count; |
jmasa@4679 | 377 | { |
jmasa@4679 | 378 | MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag); |
jmasa@4679 | 379 | after_count = gch->total_collections(); |
jmasa@4679 | 380 | } |
jmasa@4679 | 381 | |
jmasa@4679 | 382 | if(before_count != after_count) { |
jmasa@4679 | 383 | // There was a collection - success |
jmasa@4679 | 384 | break; |
jmasa@4679 | 385 | } |
jmasa@4679 | 386 | |
jmasa@4679 | 387 | // Too many loops warning |
jmasa@4679 | 388 | if(++loop_count == 0) { |
jmasa@4679 | 389 | warning("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1); |
jmasa@4679 | 390 | } |
jmasa@4679 | 391 | } |
jmasa@4679 | 392 | } |
jmasa@4679 | 393 | |
duke@435 | 394 | void ConcurrentMarkSweepThread::sleepBeforeNextCycle() { |
duke@435 | 395 | while (!_should_terminate) { |
duke@435 | 396 | if (CMSIncrementalMode) { |
duke@435 | 397 | icms_wait(); |
jmasa@4679 | 398 | if(CMSWaitDuration >= 0) { |
jmasa@4679 | 399 | // Wait until the next synchronous GC, a concurrent full gc |
jmasa@4679 | 400 | // request or a timeout, whichever is earlier. |
jmasa@4679 | 401 | wait_on_cms_lock_for_scavenge(CMSWaitDuration); |
jmasa@4679 | 402 | } |
duke@435 | 403 | return; |
duke@435 | 404 | } else { |
jmasa@4679 | 405 | if(CMSWaitDuration >= 0) { |
jmasa@4679 | 406 | // Wait until the next synchronous GC, a concurrent full gc |
jmasa@4679 | 407 | // request or a timeout, whichever is earlier. |
jmasa@4679 | 408 | wait_on_cms_lock_for_scavenge(CMSWaitDuration); |
jmasa@4679 | 409 | } else { |
jmasa@4679 | 410 | // Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently |
jmasa@4679 | 411 | wait_on_cms_lock(CMSCheckInterval); |
jmasa@4679 | 412 | } |
duke@435 | 413 | } |
duke@435 | 414 | // Check if we should start a CMS collection cycle |
duke@435 | 415 | if (_collector->shouldConcurrentCollect()) { |
duke@435 | 416 | return; |
duke@435 | 417 | } |
duke@435 | 418 | // .. collection criterion not yet met, let's go back |
duke@435 | 419 | // and wait some more |
duke@435 | 420 | } |
duke@435 | 421 | } |
duke@435 | 422 | |
duke@435 | 423 | // Incremental CMS |
duke@435 | 424 | void ConcurrentMarkSweepThread::start_icms() { |
duke@435 | 425 | assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); |
duke@435 | 426 | MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); |
duke@435 | 427 | trace_state("start_icms"); |
duke@435 | 428 | _should_run = true; |
duke@435 | 429 | iCMS_lock->notify_all(); |
duke@435 | 430 | } |
duke@435 | 431 | |
duke@435 | 432 | void ConcurrentMarkSweepThread::stop_icms() { |
duke@435 | 433 | assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); |
duke@435 | 434 | MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); |
duke@435 | 435 | if (!_should_stop) { |
duke@435 | 436 | trace_state("stop_icms"); |
duke@435 | 437 | _should_stop = true; |
duke@435 | 438 | _should_run = false; |
duke@435 | 439 | asynchronous_yield_request(); |
duke@435 | 440 | iCMS_lock->notify_all(); |
duke@435 | 441 | } |
duke@435 | 442 | } |
duke@435 | 443 | |
duke@435 | 444 | void ConcurrentMarkSweepThread::icms_wait() { |
duke@435 | 445 | assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); |
ysr@2647 | 446 | if (_should_stop && icms_is_enabled()) { |
duke@435 | 447 | MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); |
duke@435 | 448 | trace_state("pause_icms"); |
duke@435 | 449 | _collector->stats().stop_cms_timer(); |
ysr@2647 | 450 | while(!_should_run && icms_is_enabled()) { |
duke@435 | 451 | iCMS_lock->wait(Mutex::_no_safepoint_check_flag); |
duke@435 | 452 | } |
duke@435 | 453 | _collector->stats().start_cms_timer(); |
duke@435 | 454 | _should_stop = false; |
duke@435 | 455 | trace_state("pause_icms end"); |
duke@435 | 456 | } |
duke@435 | 457 | } |
duke@435 | 458 | |
duke@435 | 459 | // Note: this method, although exported by the ConcurrentMarkSweepThread, |
duke@435 | 460 | // which is a non-JavaThread, can only be called by a JavaThread. |
duke@435 | 461 | // Currently this is done at vm creation time (post-vm-init) by the |
duke@435 | 462 | // main/Primordial (Java)Thread. |
duke@435 | 463 | // XXX Consider changing this in the future to allow the CMS thread |
duke@435 | 464 | // itself to create this thread? |
duke@435 | 465 | void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) { |
duke@435 | 466 | assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC"); |
duke@435 | 467 | assert(_slt == NULL, "SLT already created"); |
duke@435 | 468 | _slt = SurrogateLockerThread::make(THREAD); |
duke@435 | 469 | } |