1.1 --- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Mon Jun 28 14:13:18 2010 -0400 1.2 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Mon Jun 28 14:13:17 2010 -0400 1.3 @@ -42,8 +42,65 @@ 1.4 void VM_G1IncCollectionPause::doit() { 1.5 JvmtiGCForAllocationMarker jgcm; 1.6 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 1.7 + assert(!_should_initiate_conc_mark || 1.8 + ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || 1.9 + (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)), 1.10 + "only a GC locker or a System.gc() induced GC should start a cycle"); 1.11 + 1.12 GCCauseSetter x(g1h, _gc_cause); 1.13 - g1h->do_collection_pause_at_safepoint(); 1.14 + if (_should_initiate_conc_mark) { 1.15 + // It's safer to read full_collections_completed() here, given 1.16 + // that noone else will be updating it concurrently. Since we'll 1.17 + // only need it if we're initiating a marking cycle, no point in 1.18 + // setting it earlier. 1.19 + _full_collections_completed_before = g1h->full_collections_completed(); 1.20 + 1.21 + // At this point we are supposed to start a concurrent cycle. We 1.22 + // will do so if one is not already in progress. 1.23 + bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle(); 1.24 + } 1.25 + g1h->do_collection_pause_at_safepoint(_target_pause_time_ms); 1.26 +} 1.27 + 1.28 +void VM_G1IncCollectionPause::doit_epilogue() { 1.29 + VM_GC_Operation::doit_epilogue(); 1.30 + 1.31 + // If the pause was initiated by a System.gc() and 1.32 + // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle 1.33 + // that just started (or maybe one that was already in progress) to 1.34 + // finish. 1.35 + if (_gc_cause == GCCause::_java_lang_system_gc && 1.36 + _should_initiate_conc_mark) { 1.37 + assert(ExplicitGCInvokesConcurrent, 1.38 + "the only way to be here is if ExplicitGCInvokesConcurrent is set"); 1.39 + 1.40 + G1CollectedHeap* g1h = G1CollectedHeap::heap(); 1.41 + 1.42 + // In the doit() method we saved g1h->full_collections_completed() 1.43 + // in the _full_collections_completed_before field. We have to 1.44 + // wait until we observe that g1h->full_collections_completed() 1.45 + // has increased by at least one. This can happen if a) we started 1.46 + // a cycle and it completes, b) a cycle already in progress 1.47 + // completes, or c) a Full GC happens. 1.48 + 1.49 + // If the condition has already been reached, there's no point in 1.50 + // actually taking the lock and doing the wait. 1.51 + if (g1h->full_collections_completed() <= 1.52 + _full_collections_completed_before) { 1.53 + // The following is largely copied from CMS 1.54 + 1.55 + Thread* thr = Thread::current(); 1.56 + assert(thr->is_Java_thread(), "invariant"); 1.57 + JavaThread* jt = (JavaThread*)thr; 1.58 + ThreadToNativeFromVM native(jt); 1.59 + 1.60 + MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); 1.61 + while (g1h->full_collections_completed() <= 1.62 + _full_collections_completed_before) { 1.63 + FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag); 1.64 + } 1.65 + } 1.66 + } 1.67 } 1.68 1.69 void VM_CGC_Operation::doit() {