149 }
150
151 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
152 PtrQueueSet(notify_when_complete),
153 _mut_process_closure(NULL),
154 _shared_dirty_card_queue(this, true /* permanent */),
155 _free_ids(NULL),
156 _processed_buffers_mut(0), _processed_buffers_rs_thread(0)
157 {
158 _all_active = true;
159 }
160
161 // Determines how many mutator threads can process the buffers in parallel.
162 uint DirtyCardQueueSet::num_par_ids() {
163 return (uint)os::processor_count();
164 }
165
166 void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl,
167 Monitor* cbl_mon,
168 Mutex* fl_lock,
169 int process_completed_threshold,
170 int max_completed_queue,
171 Mutex* lock,
172 DirtyCardQueueSet* fl_owner,
173 bool init_free_ids) {
174 _mut_process_closure = cl;
175 PtrQueueSet::initialize(cbl_mon,
176 fl_lock,
177 process_completed_threshold,
178 max_completed_queue,
179 fl_owner);
180 set_buffer_size(G1UpdateBufferSize);
181 _shared_dirty_card_queue.set_lock(lock);
182 if (init_free_ids) {
183 _free_ids = new FreeIdSet(num_par_ids(), _cbl_mon);
184 }
185 }
186
187 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
188 t->dirty_card_queue().handle_zero_index();
189 }
190
191 bool DirtyCardQueueSet::mut_process_buffer(void** buf) {
192 guarantee(_free_ids != NULL, "must be");
193
194 // claim a par id
195 uint worker_i = _free_ids->claim_par_id();
196
197 bool b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0,
198 _sz, true, worker_i);
199 if (b) {
200 Atomic::inc(&_processed_buffers_mut);
201 }
202
203 // release the id
204 _free_ids->release_par_id(worker_i);
205
206 return b;
207 }
208
209
210 BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) {
211 BufferNode* nd = NULL;
212 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
213
214 if ((int)_n_completed_buffers <= stop_at) {
215 _process_completed = false;
216 return NULL;
217 }
218
219 if (_completed_buffers_head != NULL) {
220 nd = _completed_buffers_head;
221 _completed_buffers_head = nd->next();
222 if (_completed_buffers_head == NULL)
223 _completed_buffers_tail = NULL;
224 _n_completed_buffers--;
225 assert(_n_completed_buffers >= 0, "Invariant");
226 }
227 DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
228 return nd;
229 }
230
231 bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
232 uint worker_i,
233 BufferNode* nd) {
234 if (nd != NULL) {
235 void **buf = BufferNode::make_buffer_from_node(nd);
236 size_t index = nd->index();
237 bool b =
238 DirtyCardQueue::apply_closure_to_buffer(cl, buf,
239 index, _sz,
240 true, worker_i);
241 if (b) {
242 deallocate_buffer(buf);
243 return true; // In normal case, go on to next buffer.
244 } else {
245 enqueue_complete_buffer(buf, index);
246 return false;
247 }
248 } else {
249 return false;
250 }
251 }
252
253 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
254 uint worker_i,
255 int stop_at,
256 bool during_pause) {
257 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
258 BufferNode* nd = get_completed_buffer(stop_at);
259 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd);
260 if (res) Atomic::inc(&_processed_buffers_rs_thread);
261 return res;
262 }
263
264 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
265 BufferNode* nd = _completed_buffers_head;
266 while (nd != NULL) {
267 bool b =
268 DirtyCardQueue::apply_closure_to_buffer(cl,
269 BufferNode::make_buffer_from_node(nd),
270 0, _sz, false);
271 guarantee(b, "Should not stop early.");
272 nd = nd->next();
273 }
274 }
275
313 }
314
315 }
316
317 void DirtyCardQueueSet::abandon_logs() {
318 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
319 clear();
320 // Since abandon is done only at safepoints, we can safely manipulate
321 // these queues.
322 for (JavaThread* t = Threads::first(); t; t = t->next()) {
323 t->dirty_card_queue().reset();
324 }
325 shared_dirty_card_queue()->reset();
326 }
327
328
329 void DirtyCardQueueSet::concatenate_logs() {
330 // Iterate over all the threads, if we find a partial log add it to
331 // the global list of logs. Temporarily turn off the limit on the number
332 // of outstanding buffers.
333 int save_max_completed_queue = _max_completed_queue;
334 _max_completed_queue = max_jint;
335 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
336 for (JavaThread* t = Threads::first(); t; t = t->next()) {
337 DirtyCardQueue& dcq = t->dirty_card_queue();
338 if (dcq.size() != 0) {
339 void** buf = dcq.get_buf();
340 // We must NULL out the unused entries, then enqueue.
341 size_t limit = dcq.byte_index_to_index(dcq.get_index());
342 for (size_t i = 0; i < limit; ++i) {
343 buf[i] = NULL;
344 }
345 enqueue_complete_buffer(dcq.get_buf(), dcq.get_index());
346 dcq.reinitialize();
347 }
348 }
349 if (_shared_dirty_card_queue.size() != 0) {
350 enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(),
351 _shared_dirty_card_queue.get_index());
352 _shared_dirty_card_queue.reinitialize();
353 }
|
149 }
150
151 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
152 PtrQueueSet(notify_when_complete),
153 _mut_process_closure(NULL),
154 _shared_dirty_card_queue(this, true /* permanent */),
155 _free_ids(NULL),
156 _processed_buffers_mut(0), _processed_buffers_rs_thread(0)
157 {
158 _all_active = true;
159 }
160
161 // Determines how many mutator threads can process the buffers in parallel.
162 uint DirtyCardQueueSet::num_par_ids() {
163 return (uint)os::processor_count();
164 }
165
166 void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl,
167 Monitor* cbl_mon,
168 Mutex* fl_lock,
169 size_t process_completed_threshold,
170 size_t max_completed_queue,
171 Mutex* lock,
172 DirtyCardQueueSet* fl_owner,
173 bool init_free_ids) {
174 _mut_process_closure = cl;
175 PtrQueueSet::initialize(cbl_mon,
176 fl_lock,
177 process_completed_threshold,
178 max_completed_queue,
179 fl_owner);
180 set_buffer_size(G1UpdateBufferSize);
181 _shared_dirty_card_queue.set_lock(lock);
182 if (init_free_ids) {
183 _free_ids = new FreeIdSet(num_par_ids(), _cbl_mon);
184 }
185 }
186
187 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
188 t->dirty_card_queue().handle_zero_index();
189 }
190
191 bool DirtyCardQueueSet::mut_process_buffer(void** buf) {
192 guarantee(_free_ids != NULL, "must be");
193
194 // claim a par id
195 uint worker_i = _free_ids->claim_par_id();
196
197 bool b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0,
198 _sz, true, worker_i);
199 if (b) {
200 Atomic::inc(&_processed_buffers_mut);
201 }
202
203 // release the id
204 _free_ids->release_par_id(worker_i);
205
206 return b;
207 }
208
209
210 BufferNode* DirtyCardQueueSet::get_completed_buffer(size_t stop_at) {
211 BufferNode* nd = NULL;
212 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag);
213
214 if ((size_t)_n_completed_buffers <= stop_at) {
215 _process_completed = false;
216 return NULL;
217 }
218
219 if (_completed_buffers_head != NULL) {
220 nd = _completed_buffers_head;
221 _completed_buffers_head = nd->next();
222 if (_completed_buffers_head == NULL)
223 _completed_buffers_tail = NULL;
224 assert(_n_completed_buffers > 0, "Invariant");
225 _n_completed_buffers--;
226 }
227 DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked());
228 return nd;
229 }
230
231 bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
232 uint worker_i,
233 BufferNode* nd) {
234 if (nd != NULL) {
235 void **buf = BufferNode::make_buffer_from_node(nd);
236 size_t index = nd->index();
237 bool b =
238 DirtyCardQueue::apply_closure_to_buffer(cl, buf,
239 index, _sz,
240 true, worker_i);
241 if (b) {
242 deallocate_buffer(buf);
243 return true; // In normal case, go on to next buffer.
244 } else {
245 enqueue_complete_buffer(buf, index);
246 return false;
247 }
248 } else {
249 return false;
250 }
251 }
252
253 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
254 uint worker_i,
255 size_t stop_at,
256 bool during_pause) {
257 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
258 BufferNode* nd = get_completed_buffer(stop_at);
259 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd);
260 if (res) Atomic::inc(&_processed_buffers_rs_thread);
261 return res;
262 }
263
264 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
265 BufferNode* nd = _completed_buffers_head;
266 while (nd != NULL) {
267 bool b =
268 DirtyCardQueue::apply_closure_to_buffer(cl,
269 BufferNode::make_buffer_from_node(nd),
270 0, _sz, false);
271 guarantee(b, "Should not stop early.");
272 nd = nd->next();
273 }
274 }
275
313 }
314
315 }
316
317 void DirtyCardQueueSet::abandon_logs() {
318 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
319 clear();
320 // Since abandon is done only at safepoints, we can safely manipulate
321 // these queues.
322 for (JavaThread* t = Threads::first(); t; t = t->next()) {
323 t->dirty_card_queue().reset();
324 }
325 shared_dirty_card_queue()->reset();
326 }
327
328
329 void DirtyCardQueueSet::concatenate_logs() {
330 // Iterate over all the threads, if we find a partial log add it to
331 // the global list of logs. Temporarily turn off the limit on the number
332 // of outstanding buffers.
333 size_t save_max_completed_queue = _max_completed_queue;
334 _max_completed_queue = max_jint;
335 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
336 for (JavaThread* t = Threads::first(); t; t = t->next()) {
337 DirtyCardQueue& dcq = t->dirty_card_queue();
338 if (dcq.size() != 0) {
339 void** buf = dcq.get_buf();
340 // We must NULL out the unused entries, then enqueue.
341 size_t limit = dcq.byte_index_to_index(dcq.get_index());
342 for (size_t i = 0; i < limit; ++i) {
343 buf[i] = NULL;
344 }
345 enqueue_complete_buffer(dcq.get_buf(), dcq.get_index());
346 dcq.reinitialize();
347 }
348 }
349 if (_shared_dirty_card_queue.size() != 0) {
350 enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(),
351 _shared_dirty_card_queue.get_index());
352 _shared_dirty_card_queue.reinitialize();
353 }
|