comparison src/share/vm/gc_implementation/g1/vm_operations_g1.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 9509c20bba28
children 5c86f8211d1e
comparison
equal deleted inserted replaced
5962:8a729074feae 5963:64bf7c8270cb
32 #include "runtime/interfaceSupport.hpp" 32 #include "runtime/interfaceSupport.hpp"
33 33
34 VM_G1CollectForAllocation::VM_G1CollectForAllocation( 34 VM_G1CollectForAllocation::VM_G1CollectForAllocation(
35 unsigned int gc_count_before, 35 unsigned int gc_count_before,
36 size_t word_size) 36 size_t word_size)
37 : VM_G1OperationWithAllocRequest(gc_count_before, word_size) { 37 : VM_G1OperationWithAllocRequest(gc_count_before, word_size,
38 GCCause::_allocation_failure) {
38 guarantee(word_size > 0, "an allocation should always be requested"); 39 guarantee(word_size > 0, "an allocation should always be requested");
39 } 40 }
40 41
41 void VM_G1CollectForAllocation::doit() { 42 void VM_G1CollectForAllocation::doit() {
42 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 43 G1CollectedHeap* g1h = G1CollectedHeap::heap();
55 unsigned int gc_count_before, 56 unsigned int gc_count_before,
56 size_t word_size, 57 size_t word_size,
57 bool should_initiate_conc_mark, 58 bool should_initiate_conc_mark,
58 double target_pause_time_ms, 59 double target_pause_time_ms,
59 GCCause::Cause gc_cause) 60 GCCause::Cause gc_cause)
60 : VM_G1OperationWithAllocRequest(gc_count_before, word_size), 61 : VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause),
61 _should_initiate_conc_mark(should_initiate_conc_mark), 62 _should_initiate_conc_mark(should_initiate_conc_mark),
62 _target_pause_time_ms(target_pause_time_ms), 63 _target_pause_time_ms(target_pause_time_ms),
64 _should_retry_gc(false),
63 _full_collections_completed_before(0) { 65 _full_collections_completed_before(0) {
64 guarantee(target_pause_time_ms > 0.0, 66 guarantee(target_pause_time_ms > 0.0,
65 err_msg("target_pause_time_ms = %1.6lf should be positive", 67 err_msg("target_pause_time_ms = %1.6lf should be positive",
66 target_pause_time_ms)); 68 target_pause_time_ms));
67 guarantee(word_size == 0 || gc_cause == GCCause::_g1_inc_collection_pause, 69 guarantee(word_size == 0 || gc_cause == GCCause::_g1_inc_collection_pause,
68 "we can only request an allocation if the GC cause is for " 70 "we can only request an allocation if the GC cause is for "
69 "an incremental GC pause"); 71 "an incremental GC pause");
70 _gc_cause = gc_cause; 72 _gc_cause = gc_cause;
73 }
74
75 bool VM_G1IncCollectionPause::doit_prologue() {
76 bool res = VM_GC_Operation::doit_prologue();
77 if (!res) {
78 if (_should_initiate_conc_mark) {
79 // The prologue can fail for a couple of reasons. The first is that another GC
80 // got scheduled and prevented the scheduling of the initial mark GC. The
81 // second is that the GC locker may be active and the heap can't be expanded.
82 // In both cases we want to retry the GC so that the initial mark pause is
83 // actually scheduled. In the second case, however, we should stall until
84 // until the GC locker is no longer active and then retry the initial mark GC.
85 _should_retry_gc = true;
86 }
87 }
88 return res;
71 } 89 }
72 90
73 void VM_G1IncCollectionPause::doit() { 91 void VM_G1IncCollectionPause::doit() {
74 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 92 G1CollectedHeap* g1h = G1CollectedHeap::heap();
75 assert(!_should_initiate_conc_mark || 93 assert(!_should_initiate_conc_mark ||
104 122
105 // The above routine returns true if we were able to force the 123 // The above routine returns true if we were able to force the
106 // next GC pause to be an initial mark; it returns false if a 124 // next GC pause to be an initial mark; it returns false if a
107 // marking cycle is already in progress. 125 // marking cycle is already in progress.
108 // 126 //
109 // If a marking cycle is already in progress just return and skip 127 // If a marking cycle is already in progress just return and skip the
110 // the pause - the requesting thread should block in doit_epilogue 128 // pause below - if the reason for requesting this initial mark pause
111 // until the marking cycle is complete. 129 // was due to a System.gc() then the requesting thread should block in
130 // doit_epilogue() until the marking cycle is complete.
131 //
132 // If this initial mark pause was requested as part of a humongous
133 // allocation then we know that the marking cycle must just have
134 // been started by another thread (possibly also allocating a humongous
135 // object) as there was no active marking cycle when the requesting
136 // thread checked before calling collect() in
137 // attempt_allocation_humongous(). Retrying the GC, in this case,
138 // will cause the requesting thread to spin inside collect() until the
139 // just started marking cycle is complete - which may be a while. So
140 // we do NOT retry the GC.
112 if (!res) { 141 if (!res) {
113 assert(_word_size == 0, "ExplicitGCInvokesConcurrent shouldn't be allocating"); 142 assert(_word_size == 0, "Concurrent Full GC/Humongous Object IM shouldn't be allocating");
143 if (_gc_cause != GCCause::_g1_humongous_allocation) {
144 _should_retry_gc = true;
145 }
114 return; 146 return;
115 } 147 }
116 } 148 }
117 149
118 _pause_succeeded = 150 _pause_succeeded =
121 // An allocation had been requested. 153 // An allocation had been requested.
122 _result = g1h->attempt_allocation_at_safepoint(_word_size, 154 _result = g1h->attempt_allocation_at_safepoint(_word_size,
123 true /* expect_null_cur_alloc_region */); 155 true /* expect_null_cur_alloc_region */);
124 } else { 156 } else {
125 assert(_result == NULL, "invariant"); 157 assert(_result == NULL, "invariant");
158 if (!_pause_succeeded) {
159 // Another possible reason reason for the pause to not be successful
160 // is that, again, the GC locker is active (and has become active
161 // since the prologue was executed). In this case we should retry
162 // the pause after waiting for the GC locker to become inactive.
163 _should_retry_gc = true;
164 }
126 } 165 }
127 } 166 }
128 167
129 void VM_G1IncCollectionPause::doit_epilogue() { 168 void VM_G1IncCollectionPause::doit_epilogue() {
130 VM_GC_Operation::doit_epilogue(); 169 VM_GC_Operation::doit_epilogue();
166 } 205 }
167 } 206 }
168 } 207 }
169 208
170 void VM_CGC_Operation::acquire_pending_list_lock() { 209 void VM_CGC_Operation::acquire_pending_list_lock() {
210 assert(_needs_pll, "don't call this otherwise");
171 // The caller may block while communicating 211 // The caller may block while communicating
172 // with the SLT thread in order to acquire/release the PLL. 212 // with the SLT thread in order to acquire/release the PLL.
173 ConcurrentMarkThread::slt()-> 213 ConcurrentMarkThread::slt()->
174 manipulatePLL(SurrogateLockerThread::acquirePLL); 214 manipulatePLL(SurrogateLockerThread::acquirePLL);
175 } 215 }
176 216
177 void VM_CGC_Operation::release_and_notify_pending_list_lock() { 217 void VM_CGC_Operation::release_and_notify_pending_list_lock() {
218 assert(_needs_pll, "don't call this otherwise");
178 // The caller may block while communicating 219 // The caller may block while communicating
179 // with the SLT thread in order to acquire/release the PLL. 220 // with the SLT thread in order to acquire/release the PLL.
180 ConcurrentMarkThread::slt()-> 221 ConcurrentMarkThread::slt()->
181 manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL); 222 manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
182 } 223 }
196 } 237 }
197 238
198 bool VM_CGC_Operation::doit_prologue() { 239 bool VM_CGC_Operation::doit_prologue() {
199 // Note the relative order of the locks must match that in 240 // Note the relative order of the locks must match that in
200 // VM_GC_Operation::doit_prologue() or deadlocks can occur 241 // VM_GC_Operation::doit_prologue() or deadlocks can occur
201 acquire_pending_list_lock(); 242 if (_needs_pll) {
243 acquire_pending_list_lock();
244 }
202 245
203 Heap_lock->lock(); 246 Heap_lock->lock();
204 SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true; 247 SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true;
205 return true; 248 return true;
206 } 249 }
208 void VM_CGC_Operation::doit_epilogue() { 251 void VM_CGC_Operation::doit_epilogue() {
209 // Note the relative order of the unlocks must match that in 252 // Note the relative order of the unlocks must match that in
210 // VM_GC_Operation::doit_epilogue() 253 // VM_GC_Operation::doit_epilogue()
211 SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false; 254 SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false;
212 Heap_lock->unlock(); 255 Heap_lock->unlock();
213 release_and_notify_pending_list_lock(); 256 if (_needs_pll) {
214 } 257 release_and_notify_pending_list_lock();
258 }
259 }