Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp @ 1090:fa357420e7d2
6899058: G1: Internal error in ptrQueue.cpp:201 in nightly tests
Summary: Fixes a race on the dirty card queue completed buffer list between worker thread(s) performing a flush of a deferred store barrier (enqueueing a newly completed buffer) and worker thread(s) in the RSet updating code claiming completed buffers. Removed the routine that removes elements from the completed update buffer queue using a CAS.
Reviewed-by: ysr, tonyp
author | johnc |
---|---|
date | Tue, 24 Nov 2009 15:19:30 -0800 |
parents | 7f807f55161a |
children | 44f61c24ddab |
comparison
equal
deleted
inserted
replaced
1089:db0d5eba9d20 | 1090:fa357420e7d2 |
---|---|
153 } | 153 } |
154 return b; | 154 return b; |
155 } | 155 } |
156 | 156 |
157 DirtyCardQueueSet::CompletedBufferNode* | 157 DirtyCardQueueSet::CompletedBufferNode* |
158 DirtyCardQueueSet::get_completed_buffer_lock(int stop_at) { | 158 DirtyCardQueueSet::get_completed_buffer(int stop_at) { |
159 CompletedBufferNode* nd = NULL; | 159 CompletedBufferNode* nd = NULL; |
160 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); | 160 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
161 | 161 |
162 if ((int)_n_completed_buffers <= stop_at) { | 162 if ((int)_n_completed_buffers <= stop_at) { |
163 _process_completed = false; | 163 _process_completed = false; |
171 _completed_buffers_tail = NULL; | 171 _completed_buffers_tail = NULL; |
172 _n_completed_buffers--; | 172 _n_completed_buffers--; |
173 } | 173 } |
174 debug_only(assert_completed_buffer_list_len_correct_locked()); | 174 debug_only(assert_completed_buffer_list_len_correct_locked()); |
175 return nd; | 175 return nd; |
176 } | |
177 | |
178 // We only do this in contexts where there is no concurrent enqueueing. | |
179 DirtyCardQueueSet::CompletedBufferNode* | |
180 DirtyCardQueueSet::get_completed_buffer_CAS() { | |
181 CompletedBufferNode* nd = _completed_buffers_head; | |
182 | |
183 while (nd != NULL) { | |
184 CompletedBufferNode* next = nd->next; | |
185 CompletedBufferNode* result = | |
186 (CompletedBufferNode*)Atomic::cmpxchg_ptr(next, | |
187 &_completed_buffers_head, | |
188 nd); | |
189 if (result == nd) { | |
190 return result; | |
191 } else { | |
192 nd = _completed_buffers_head; | |
193 } | |
194 } | |
195 assert(_completed_buffers_head == NULL, "Loop post"); | |
196 _completed_buffers_tail = NULL; | |
197 return NULL; | |
198 } | 176 } |
199 | 177 |
200 bool DirtyCardQueueSet:: | 178 bool DirtyCardQueueSet:: |
201 apply_closure_to_completed_buffer_helper(int worker_i, | 179 apply_closure_to_completed_buffer_helper(int worker_i, |
202 CompletedBufferNode* nd) { | 180 CompletedBufferNode* nd) { |
220 } | 198 } |
221 } | 199 } |
222 | 200 |
223 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, | 201 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, |
224 int stop_at, | 202 int stop_at, |
225 bool with_CAS) | 203 bool during_pause) |
226 { | 204 { |
227 CompletedBufferNode* nd = NULL; | 205 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); |
228 if (with_CAS) { | 206 CompletedBufferNode* nd = get_completed_buffer(stop_at); |
229 guarantee(stop_at == 0, "Precondition"); | |
230 nd = get_completed_buffer_CAS(); | |
231 } else { | |
232 nd = get_completed_buffer_lock(stop_at); | |
233 } | |
234 bool res = apply_closure_to_completed_buffer_helper(worker_i, nd); | 207 bool res = apply_closure_to_completed_buffer_helper(worker_i, nd); |
235 if (res) Atomic::inc(&_processed_buffers_rs_thread); | 208 if (res) Atomic::inc(&_processed_buffers_rs_thread); |
236 return res; | 209 return res; |
237 } | 210 } |
238 | 211 |