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