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

changeset 435
a61af66fc99e
child 1907
c18cbe5936b8
     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 +}

mercurial