Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 5963:64bf7c8270cb
7147724: G1: hang in SurrogateLockerThread::manipulatePLL
Summary: Attempting to initiate a marking cycle when allocating a humongous object can, if a marking cycle is successfully initiated by another thread, result in the allocating thread spinning until the marking cycle is complete. Eliminate a deadlock between the main ConcurrentMarkThread, the SurrogateLocker thread, the VM thread, and a mutator thread waiting on the SecondaryFreeList_lock (while free regions are going to become available) by not manipulating the pending list lock during the prologue and epilogue of the cleanup pause.
Reviewed-by: brutisso, jcoomes, tonyp
author | johnc |
---|---|
date | Mon, 12 Mar 2012 14:59:00 -0700 |
parents | a9647476d1a4 |
children | 500023bd0818 |
comparison
equal
deleted
inserted
replaced
5962:8a729074feae | 5963:64bf7c8270cb |
---|---|
991 // first attempt (without holding the Heap_lock) here and the | 991 // first attempt (without holding the Heap_lock) here and the |
992 // follow-on attempt will be at the start of the next loop | 992 // follow-on attempt will be at the start of the next loop |
993 // iteration (after taking the Heap_lock). | 993 // iteration (after taking the Heap_lock). |
994 result = _mutator_alloc_region.attempt_allocation(word_size, | 994 result = _mutator_alloc_region.attempt_allocation(word_size, |
995 false /* bot_updates */); | 995 false /* bot_updates */); |
996 if (result != NULL ){ | 996 if (result != NULL) { |
997 return result; | 997 return result; |
998 } | 998 } |
999 | 999 |
1000 // Give a warning if we seem to be looping forever. | 1000 // Give a warning if we seem to be looping forever. |
1001 if ((QueuedAllocationWarningCount > 0) && | 1001 if ((QueuedAllocationWarningCount > 0) && |
2435 VM_G1IncCollectionPause op(gc_count_before, | 2435 VM_G1IncCollectionPause op(gc_count_before, |
2436 0, /* word_size */ | 2436 0, /* word_size */ |
2437 true, /* should_initiate_conc_mark */ | 2437 true, /* should_initiate_conc_mark */ |
2438 g1_policy()->max_pause_time_ms(), | 2438 g1_policy()->max_pause_time_ms(), |
2439 cause); | 2439 cause); |
2440 | |
2440 VMThread::execute(&op); | 2441 VMThread::execute(&op); |
2441 if (!op.pause_succeeded()) { | 2442 if (!op.pause_succeeded()) { |
2442 // Another GC got scheduled and prevented us from scheduling | |
2443 // the initial-mark GC. It's unlikely that the GC that | |
2444 // pre-empted us was also an initial-mark GC. So, we'll retry | |
2445 // the initial-mark GC. | |
2446 | |
2447 if (full_gc_count_before == total_full_collections()) { | 2443 if (full_gc_count_before == total_full_collections()) { |
2448 retry_gc = true; | 2444 retry_gc = op.should_retry_gc(); |
2449 } else { | 2445 } else { |
2450 // A Full GC happened while we were trying to schedule the | 2446 // A Full GC happened while we were trying to schedule the |
2451 // initial-mark GC. No point in starting a new cycle given | 2447 // initial-mark GC. No point in starting a new cycle given |
2452 // that the whole heap was collected anyway. | 2448 // that the whole heap was collected anyway. |
2449 } | |
2450 | |
2451 if (retry_gc) { | |
2452 if (GC_locker::is_active_and_needs_gc()) { | |
2453 GC_locker::stall_until_clear(); | |
2454 } | |
2453 } | 2455 } |
2454 } | 2456 } |
2455 } else { | 2457 } else { |
2456 if (cause == GCCause::_gc_locker | 2458 if (cause == GCCause::_gc_locker |
2457 DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) { | 2459 DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) { |