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

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

     1 /*
     2  * Copyright 2001-2006 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_concurrentMarkSweepThread.cpp.incl"
    28 // ======= Concurrent Mark Sweep Thread ========
    30 // The CMS thread is created when Concurrent Mark Sweep is used in the
    31 // older of two generations in a generational memory system.
    33 ConcurrentMarkSweepThread*
    34      ConcurrentMarkSweepThread::_cmst     = NULL;
    35 CMSCollector* ConcurrentMarkSweepThread::_collector = NULL;
    36 bool ConcurrentMarkSweepThread::_should_terminate = false;
    37 int  ConcurrentMarkSweepThread::_CMS_flag         = CMS_nil;
    39 volatile jint ConcurrentMarkSweepThread::_pending_yields      = 0;
    40 volatile jint ConcurrentMarkSweepThread::_pending_decrements  = 0;
    42 volatile bool ConcurrentMarkSweepThread::_icms_enabled   = false;
    43 volatile bool ConcurrentMarkSweepThread::_should_run     = false;
    44 // When icms is enabled, the icms thread is stopped until explicitly
    45 // started.
    46 volatile bool ConcurrentMarkSweepThread::_should_stop    = true;
    48 SurrogateLockerThread*
    49      ConcurrentMarkSweepThread::_slt = NULL;
    50 SurrogateLockerThread::SLT_msg_type
    51      ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty;
    52 Monitor*
    53      ConcurrentMarkSweepThread::_sltMonitor = NULL;
    55 ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
    56   : ConcurrentGCThread() {
    57   assert(UseConcMarkSweepGC,  "UseConcMarkSweepGC should be set");
    58   assert(_cmst == NULL, "CMS thread already created");
    59   _cmst = this;
    60   assert(_collector == NULL, "Collector already set");
    61   _collector = collector;
    63   set_name("Concurrent Mark-Sweep GC Thread");
    65   if (os::create_thread(this, os::cgc_thread)) {
    66     // XXX: need to set this to low priority
    67     // unless "agressive mode" set; priority
    68     // should be just less than that of VMThread.
    69     os::set_priority(this, NearMaxPriority);
    70     if (!DisableStartThread) {
    71       os::start_thread(this);
    72     }
    73   }
    74   _sltMonitor = SLT_lock;
    75   set_icms_enabled(CMSIncrementalMode);
    76 }
    78 void ConcurrentMarkSweepThread::run() {
    79   assert(this == cmst(), "just checking");
    81   this->record_stack_base_and_size();
    82   this->initialize_thread_local_storage();
    83   this->set_active_handles(JNIHandleBlock::allocate_block());
    84   // From this time Thread::current() should be working.
    85   assert(this == Thread::current(), "just checking");
    86   if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) {
    87     warning("Couldn't bind CMS thread to processor %u", CPUForCMSThread);
    88   }
    89   // Wait until Universe::is_fully_initialized()
    90   {
    91     CMSLoopCountWarn loopX("CMS::run", "waiting for "
    92                            "Universe::is_fully_initialized()", 2);
    93     MutexLockerEx x(CGC_lock, true);
    94     set_CMS_flag(CMS_cms_wants_token);
    95     // Wait until Universe is initialized and all initialization is completed.
    96     while (!is_init_completed() && !Universe::is_fully_initialized() &&
    97            !_should_terminate) {
    98       CGC_lock->wait(true, 200);
    99       loopX.tick();
   100     }
   101     // Wait until the surrogate locker thread that will do
   102     // pending list locking on our behalf has been created.
   103     // We cannot start the SLT thread ourselves since we need
   104     // to be a JavaThread to do so.
   105     CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2);
   106     while (_slt == NULL && !_should_terminate) {
   107       CGC_lock->wait(true, 200);
   108       loopY.tick();
   109     }
   110     clear_CMS_flag(CMS_cms_wants_token);
   111   }
   113   while (!_should_terminate) {
   114     sleepBeforeNextCycle();
   115     if (_should_terminate) break;
   116     _collector->collect_in_background(false);  // !clear_all_soft_refs
   117   }
   118   assert(_should_terminate, "just checking");
   119   // Check that the state of any protocol for synchronization
   120   // between background (CMS) and foreground collector is "clean"
   121   // (i.e. will not potentially block the foreground collector,
   122   // requiring action by us).
   123   verify_ok_to_terminate();
   124   // Signal that it is terminated
   125   {
   126     MutexLockerEx mu(Terminator_lock,
   127                      Mutex::_no_safepoint_check_flag);
   128     assert(_cmst == this, "Weird!");
   129     _cmst = NULL;
   130     Terminator_lock->notify();
   131   }
   133   // Thread destructor usually does this..
   134   ThreadLocalStorage::set_thread(NULL);
   135 }
   137 #ifndef PRODUCT
   138 void ConcurrentMarkSweepThread::verify_ok_to_terminate() const {
   139   assert(!(CGC_lock->owned_by_self() || cms_thread_has_cms_token() ||
   140            cms_thread_wants_cms_token()),
   141          "Must renounce all worldly possessions and desires for nirvana");
   142   _collector->verify_ok_to_terminate();
   143 }
   144 #endif
   146 // create and start a new ConcurrentMarkSweep Thread for given CMS generation
   147 ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) {
   148   if (!_should_terminate) {
   149     assert(cmst() == NULL, "start() called twice?");
   150     ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector);
   151     assert(cmst() == th, "Where did the just-created CMS thread go?");
   152     return th;
   153   }
   154   return NULL;
   155 }
   157 void ConcurrentMarkSweepThread::stop() {
   158   if (CMSIncrementalMode) {
   159     // Disable incremental mode and wake up the thread so it notices the change.
   160     disable_icms();
   161     start_icms();
   162   }
   163   // it is ok to take late safepoints here, if needed
   164   {
   165     MutexLockerEx x(Terminator_lock);
   166     _should_terminate = true;
   167   }
   168   { // Now post a notify on CGC_lock so as to nudge
   169     // CMS thread(s) that might be slumbering in
   170     // sleepBeforeNextCycle.
   171     MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
   172     CGC_lock->notify_all();
   173   }
   174   { // Now wait until (all) CMS thread(s) have exited
   175     MutexLockerEx x(Terminator_lock);
   176     while(cmst() != NULL) {
   177       Terminator_lock->wait();
   178     }
   179   }
   180 }
   182 void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) {
   183   assert(tc != NULL, "Null ThreadClosure");
   184   if (_cmst != NULL) {
   185     tc->do_thread(_cmst);
   186   }
   187   assert(Universe::is_fully_initialized(),
   188          "Called too early, make sure heap is fully initialized");
   189   if (_collector != NULL) {
   190     AbstractWorkGang* gang = _collector->conc_workers();
   191     if (gang != NULL) {
   192       gang->threads_do(tc);
   193     }
   194   }
   195 }
   197 void ConcurrentMarkSweepThread::print_on(outputStream* st) const {
   198   st->print("\"%s\" ", name());
   199   Thread::print_on(st);
   200   st->cr();
   201 }
   203 void ConcurrentMarkSweepThread::print_all_on(outputStream* st) {
   204   if (_cmst != NULL) {
   205     _cmst->print_on(st);
   206   }
   207   if (_collector != NULL) {
   208     AbstractWorkGang* gang = _collector->conc_workers();
   209     if (gang != NULL) {
   210       gang->print_worker_threads_on(st);
   211     }
   212   }
   213 }
   215 void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) {
   216   assert(UseConcMarkSweepGC, "just checking");
   218   MutexLockerEx x(CGC_lock,
   219                   Mutex::_no_safepoint_check_flag);
   220   if (!is_cms_thread) {
   221     assert(Thread::current()->is_VM_thread(), "Not a VM thread");
   222     CMSSynchronousYieldRequest yr;
   223     while (CMS_flag_is_set(CMS_cms_has_token)) {
   224       // indicate that we want to get the token
   225       set_CMS_flag(CMS_vm_wants_token);
   226       CGC_lock->wait(true);
   227     }
   228     // claim the token and proceed
   229     clear_CMS_flag(CMS_vm_wants_token);
   230     set_CMS_flag(CMS_vm_has_token);
   231   } else {
   232     assert(Thread::current()->is_ConcurrentGC_thread(),
   233            "Not a CMS thread");
   234     // The following barrier assumes there's only one CMS thread.
   235     // This will need to be modified is there are more CMS threads than one.
   236     while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) {
   237       set_CMS_flag(CMS_cms_wants_token);
   238       CGC_lock->wait(true);
   239     }
   240     // claim the token
   241     clear_CMS_flag(CMS_cms_wants_token);
   242     set_CMS_flag(CMS_cms_has_token);
   243   }
   244 }
   246 void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) {
   247   assert(UseConcMarkSweepGC, "just checking");
   249   MutexLockerEx x(CGC_lock,
   250                   Mutex::_no_safepoint_check_flag);
   251   if (!is_cms_thread) {
   252     assert(Thread::current()->is_VM_thread(), "Not a VM thread");
   253     assert(CMS_flag_is_set(CMS_vm_has_token), "just checking");
   254     clear_CMS_flag(CMS_vm_has_token);
   255     if (CMS_flag_is_set(CMS_cms_wants_token)) {
   256       // wake-up a waiting CMS thread
   257       CGC_lock->notify();
   258     }
   259     assert(!CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token),
   260            "Should have been cleared");
   261   } else {
   262     assert(Thread::current()->is_ConcurrentGC_thread(),
   263            "Not a CMS thread");
   264     assert(CMS_flag_is_set(CMS_cms_has_token), "just checking");
   265     clear_CMS_flag(CMS_cms_has_token);
   266     if (CMS_flag_is_set(CMS_vm_wants_token)) {
   267       // wake-up a waiting VM thread
   268       CGC_lock->notify();
   269     }
   270     assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
   271            "Should have been cleared");
   272   }
   273 }
   275 // Wait until the next synchronous GC or a timeout, whichever is earlier.
   276 void ConcurrentMarkSweepThread::wait_on_cms_lock(long t) {
   277   MutexLockerEx x(CGC_lock,
   278                   Mutex::_no_safepoint_check_flag);
   279   set_CMS_flag(CMS_cms_wants_token);   // to provoke notifies
   280   CGC_lock->wait(Mutex::_no_safepoint_check_flag, t);
   281   clear_CMS_flag(CMS_cms_wants_token);
   282   assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
   283          "Should not be set");
   284 }
   286 void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {
   287   while (!_should_terminate) {
   288     if (CMSIncrementalMode) {
   289       icms_wait();
   290       return;
   291     } else {
   292       // Wait until the next synchronous GC or a timeout, whichever is earlier
   293       wait_on_cms_lock(CMSWaitDuration);
   294     }
   295     // Check if we should start a CMS collection cycle
   296     if (_collector->shouldConcurrentCollect()) {
   297       return;
   298     }
   299     // .. collection criterion not yet met, let's go back
   300     // and wait some more
   301   }
   302 }
   304 // Incremental CMS
   305 void ConcurrentMarkSweepThread::start_icms() {
   306   assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");
   307   MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);
   308   trace_state("start_icms");
   309   _should_run = true;
   310   iCMS_lock->notify_all();
   311 }
   313 void ConcurrentMarkSweepThread::stop_icms() {
   314   assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");
   315   MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);
   316   if (!_should_stop) {
   317     trace_state("stop_icms");
   318     _should_stop = true;
   319     _should_run = false;
   320     asynchronous_yield_request();
   321     iCMS_lock->notify_all();
   322   }
   323 }
   325 void ConcurrentMarkSweepThread::icms_wait() {
   326   assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");
   327   if (_should_stop && icms_enabled()) {
   328     MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);
   329     trace_state("pause_icms");
   330     _collector->stats().stop_cms_timer();
   331     while(!_should_run && icms_enabled()) {
   332       iCMS_lock->wait(Mutex::_no_safepoint_check_flag);
   333     }
   334     _collector->stats().start_cms_timer();
   335     _should_stop = false;
   336     trace_state("pause_icms end");
   337   }
   338 }
   340 // Note: this method, although exported by the ConcurrentMarkSweepThread,
   341 // which is a non-JavaThread, can only be called by a JavaThread.
   342 // Currently this is done at vm creation time (post-vm-init) by the
   343 // main/Primordial (Java)Thread.
   344 // XXX Consider changing this in the future to allow the CMS thread
   345 // itself to create this thread?
   346 void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) {
   347   assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC");
   348   assert(_slt == NULL, "SLT already created");
   349   _slt = SurrogateLockerThread::make(THREAD);
   350 }

mercurial