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

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

mercurial