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

Wed, 23 Dec 2009 09:23:54 -0800

author
ysr
date
Wed, 23 Dec 2009 09:23:54 -0800
changeset 1580
e018e6884bd8
parent 435
a61af66fc99e
child 1875
bb843ebc7c55
permissions
-rw-r--r--

6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa

     1 /*
     2  * Copyright 2005-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  */
    24 # include "incls/_precompiled.incl"
    25 # include "incls/_vmCMSOperations.cpp.incl"
    27 HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__begin);
    28 HS_DTRACE_PROBE_DECL(hs_private, cms__initmark__end);
    30 HS_DTRACE_PROBE_DECL(hs_private, cms__remark__begin);
    31 HS_DTRACE_PROBE_DECL(hs_private, cms__remark__end);
    33 //////////////////////////////////////////////////////////
    34 // Methods in abstract class VM_CMS_Operation
    35 //////////////////////////////////////////////////////////
    36 void VM_CMS_Operation::acquire_pending_list_lock() {
    37   // The caller may block while communicating
    38   // with the SLT thread in order to acquire/release the PLL.
    39   ConcurrentMarkSweepThread::slt()->
    40     manipulatePLL(SurrogateLockerThread::acquirePLL);
    41 }
    43 void VM_CMS_Operation::release_and_notify_pending_list_lock() {
    44   // The caller may block while communicating
    45   // with the SLT thread in order to acquire/release the PLL.
    46   ConcurrentMarkSweepThread::slt()->
    47     manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
    48 }
    50 void VM_CMS_Operation::verify_before_gc() {
    51   if (VerifyBeforeGC &&
    52       GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
    53     HandleMark hm;
    54     FreelistLocker x(_collector);
    55     MutexLockerEx  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
    56     Universe::heap()->prepare_for_verify();
    57     Universe::verify(true);
    58   }
    59 }
    61 void VM_CMS_Operation::verify_after_gc() {
    62   if (VerifyAfterGC &&
    63       GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
    64     HandleMark hm;
    65     FreelistLocker x(_collector);
    66     MutexLockerEx  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
    67     Universe::verify(true);
    68   }
    69 }
    71 bool VM_CMS_Operation::lost_race() const {
    72   if (CMSCollector::abstract_state() == CMSCollector::Idling) {
    73     // We lost a race to a foreground collection
    74     // -- there's nothing to do
    75     return true;
    76   }
    77   assert(CMSCollector::abstract_state() == legal_state(),
    78          "Inconsistent collector state?");
    79   return false;
    80 }
    82 bool VM_CMS_Operation::doit_prologue() {
    83   assert(Thread::current()->is_ConcurrentGC_thread(), "just checking");
    84   assert(!CMSCollector::foregroundGCShouldWait(), "Possible deadlock");
    85   assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
    86          "Possible deadlock");
    88   if (needs_pll()) {
    89     acquire_pending_list_lock();
    90   }
    91   // Get the Heap_lock after the pending_list_lock.
    92   Heap_lock->lock();
    93   if (lost_race()) {
    94     assert(_prologue_succeeded == false, "Initialized in c'tor");
    95     Heap_lock->unlock();
    96     if (needs_pll()) {
    97       release_and_notify_pending_list_lock();
    98     }
    99   } else {
   100     _prologue_succeeded = true;
   101   }
   102   return _prologue_succeeded;
   103 }
   105 void VM_CMS_Operation::doit_epilogue() {
   106   assert(Thread::current()->is_ConcurrentGC_thread(), "just checking");
   107   assert(!CMSCollector::foregroundGCShouldWait(), "Possible deadlock");
   108   assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
   109          "Possible deadlock");
   111   // Release the Heap_lock first.
   112   Heap_lock->unlock();
   113   if (needs_pll()) {
   114     release_and_notify_pending_list_lock();
   115   }
   116 }
   118 //////////////////////////////////////////////////////////
   119 // Methods in class VM_CMS_Initial_Mark
   120 //////////////////////////////////////////////////////////
   121 void VM_CMS_Initial_Mark::doit() {
   122   if (lost_race()) {
   123     // Nothing to do.
   124     return;
   125   }
   126   HS_DTRACE_PROBE(hs_private, cms__initmark__begin);
   128   GenCollectedHeap* gch = GenCollectedHeap::heap();
   129   GCCauseSetter gccs(gch, GCCause::_cms_initial_mark);
   131   VM_CMS_Operation::verify_before_gc();
   133   IsGCActiveMark x; // stop-world GC active
   134   _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial);
   136   VM_CMS_Operation::verify_after_gc();
   137   HS_DTRACE_PROBE(hs_private, cms__initmark__end);
   138 }
   140 //////////////////////////////////////////////////////////
   141 // Methods in class VM_CMS_Final_Remark_Operation
   142 //////////////////////////////////////////////////////////
   143 void VM_CMS_Final_Remark::doit() {
   144   if (lost_race()) {
   145     // Nothing to do.
   146     return;
   147   }
   148   HS_DTRACE_PROBE(hs_private, cms__remark__begin);
   150   GenCollectedHeap* gch = GenCollectedHeap::heap();
   151   GCCauseSetter gccs(gch, GCCause::_cms_final_remark);
   153   VM_CMS_Operation::verify_before_gc();
   155   IsGCActiveMark x; // stop-world GC active
   156   _collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal);
   158   VM_CMS_Operation::verify_after_gc();
   159   HS_DTRACE_PROBE(hs_private, cms__remark__end);
   160 }
   162 // VM operation to invoke a concurrent collection of a
   163 // GenCollectedHeap heap.
   164 void VM_GenCollectFullConcurrent::doit() {
   165   assert(Thread::current()->is_VM_thread(), "Should be VM thread");
   167   GenCollectedHeap* gch = GenCollectedHeap::heap();
   168   if (_gc_count_before == gch->total_collections()) {
   169     // The "full" of do_full_collection call below "forces"
   170     // a collection; the second arg, 0, below ensures that
   171     // only the young gen is collected. XXX In the future,
   172     // we'll probably need to have something in this interface
   173     // to say do this only if we are sure we will not bail
   174     // out to a full collection in this attempt, but that's
   175     // for the future.
   176     assert(SafepointSynchronize::is_at_safepoint(),
   177       "We can only be executing this arm of if at a safepoint");
   178     GCCauseSetter gccs(gch, _gc_cause);
   179     gch->do_full_collection(gch->must_clear_all_soft_refs(),
   180                             0 /* collect only youngest gen */);
   181   } // Else no need for a foreground young gc
   182   assert((_gc_count_before < gch->total_collections()) ||
   183          (GC_locker::is_active() /* gc may have been skipped */
   184           && (_gc_count_before == gch->total_collections())),
   185          "total_collections() should be monotonically increasing");
   187   MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
   188   if (gch->total_full_collections() == _full_gc_count_before) {
   189     // Disable iCMS until the full collection is done.
   190     CMSCollector::disable_icms();
   191     // In case CMS thread was in icms_wait(), wake it up.
   192     CMSCollector::start_icms();
   193     // Nudge the CMS thread to start a concurrent collection
   194     CMSCollector::request_full_gc(_full_gc_count_before);
   195   } else {
   196     FullGCCount_lock->notify_all();  // Inform the Java thread its work is done
   197   }
   198 }
   200 bool VM_GenCollectFullConcurrent::evaluate_at_safepoint() const {
   201   Thread* thr = Thread::current();
   202   assert(thr != NULL, "Unexpected tid");
   203   if (!thr->is_Java_thread()) {
   204     assert(thr->is_VM_thread(), "Expected to be evaluated by VM thread");
   205     GenCollectedHeap* gch = GenCollectedHeap::heap();
   206     if (_gc_count_before != gch->total_collections()) {
   207       // No need to do a young gc, we'll just nudge the CMS thread
   208       // in the doit() method above, to be executed soon.
   209       assert(_gc_count_before < gch->total_collections(),
   210              "total_collections() should be monotnically increasing");
   211       return false;  // no need for foreground young gc
   212     }
   213   }
   214   return true;       // may still need foreground young gc
   215 }
   218 void VM_GenCollectFullConcurrent::doit_epilogue() {
   219   Thread* thr = Thread::current();
   220   assert(thr->is_Java_thread(), "just checking");
   221   JavaThread* jt = (JavaThread*)thr;
   222   // Release the Heap_lock first.
   223   Heap_lock->unlock();
   224   release_and_notify_pending_list_lock();
   226   // It is fine to test whether completed collections has
   227   // exceeded our request count without locking because
   228   // the completion count is monotonically increasing;
   229   // this will break for very long-running apps when the
   230   // count overflows and wraps around. XXX fix me !!!
   231   // e.g. at the rate of 1 full gc per ms, this could
   232   // overflow in about 1000 years.
   233   GenCollectedHeap* gch = GenCollectedHeap::heap();
   234   if (gch->total_full_collections_completed() <= _full_gc_count_before) {
   235     // Now, wait for witnessing concurrent gc cycle to complete,
   236     // but do so in native mode, because we want to lock the
   237     // FullGCEvent_lock, which may be needed by the VM thread
   238     // or by the CMS thread, so we do not want to be suspended
   239     // while holding that lock.
   240     ThreadToNativeFromVM native(jt);
   241     MutexLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
   242     // Either a concurrent or a stop-world full gc is sufficient
   243     // witness to our request.
   244     while (gch->total_full_collections_completed() <= _full_gc_count_before) {
   245       FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
   246     }
   247   }
   248   // Enable iCMS back.
   249   CMSCollector::enable_icms();
   250 }

mercurial