67 G1DirtyCardQueue::~G1DirtyCardQueue() {
68 flush();
69 }
70
71 void G1DirtyCardQueue::handle_completed_buffer() {
72 assert(_buf != NULL, "precondition");
73 BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
74 G1DirtyCardQueueSet* dcqs = dirty_card_qset();
75 if (dcqs->process_or_enqueue_completed_buffer(node)) {
76 reset(); // Buffer fully processed, reset index.
77 } else {
78 allocate_buffer(); // Buffer enqueued, get a new one.
79 }
80 }
81
82 G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
83 PtrQueueSet(),
84 _cbl_mon(NULL),
85 _completed_buffers_head(NULL),
86 _completed_buffers_tail(NULL),
87 _num_entries_in_completed_buffers(0),
88 _process_completed_buffers_threshold(ProcessCompletedBuffersThresholdNever),
89 _process_completed_buffers(false),
90 _notify_when_complete(notify_when_complete),
91 _max_completed_buffers(MaxCompletedBuffersUnlimited),
92 _completed_buffers_padding(0),
93 _free_ids(NULL),
94 _processed_buffers_mut(0),
95 _processed_buffers_rs_thread(0)
96 {
97 _all_active = true;
98 }
99
100 G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
101 abandon_completed_buffers();
102 delete _free_ids;
103 }
104
105 // Determines how many mutator threads can process the buffers in parallel.
106 uint G1DirtyCardQueueSet::num_par_ids() {
107 return (uint)os::initial_active_processor_count();
108 }
109
110 void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
111 BufferNode::Allocator* allocator,
112 bool init_free_ids) {
116 if (init_free_ids) {
117 _free_ids = new G1FreeIdSet(0, num_par_ids());
118 }
119 }
120
121 void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) {
122 G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
123 }
124
125 void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
126 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
127 cbn->set_next(NULL);
128 if (_completed_buffers_tail == NULL) {
129 assert(_completed_buffers_head == NULL, "Well-formedness");
130 _completed_buffers_head = cbn;
131 _completed_buffers_tail = cbn;
132 } else {
133 _completed_buffers_tail->set_next(cbn);
134 _completed_buffers_tail = cbn;
135 }
136 _num_entries_in_completed_buffers += buffer_size() - cbn->index();
137
138 if (!process_completed_buffers() &&
139 (num_completed_buffers() > process_completed_buffers_threshold())) {
140 set_process_completed_buffers(true);
141 if (_notify_when_complete) {
142 _cbl_mon->notify_all();
143 }
144 }
145 verify_num_entries_in_completed_buffers();
146 }
147
148 BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) {
149 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
150
151 if (num_completed_buffers() <= stop_at) {
152 return NULL;
153 }
154
155 assert(num_completed_buffers() > 0, "invariant");
156 assert(_completed_buffers_head != NULL, "invariant");
157 assert(_completed_buffers_tail != NULL, "invariant");
158
159 BufferNode* bn = _completed_buffers_head;
160 _num_entries_in_completed_buffers -= buffer_size() - bn->index();
161 _completed_buffers_head = bn->next();
162 if (_completed_buffers_head == NULL) {
163 assert(num_completed_buffers() == 0, "invariant");
164 _completed_buffers_tail = NULL;
165 set_process_completed_buffers(false);
166 }
167 verify_num_entries_in_completed_buffers();
168 bn->set_next(NULL);
169 return bn;
170 }
171
172 #ifdef ASSERT
173 void G1DirtyCardQueueSet::verify_num_entries_in_completed_buffers() const {
174 size_t actual = 0;
175 BufferNode* cur = _completed_buffers_head;
176 while (cur != NULL) {
177 actual += buffer_size() - cur->index();
178 cur = cur->next();
179 }
180 assert(actual == _num_entries_in_completed_buffers,
181 "Num entries in completed buffers should be " SIZE_FORMAT " but are " SIZE_FORMAT,
182 _num_entries_in_completed_buffers, actual);
183 }
184 #endif
185
186 void G1DirtyCardQueueSet::abandon_completed_buffers() {
187 BufferNode* buffers_to_delete = NULL;
188 {
189 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
190 buffers_to_delete = _completed_buffers_head;
191 _completed_buffers_head = NULL;
192 _completed_buffers_tail = NULL;
193 _num_entries_in_completed_buffers = 0;
194 set_process_completed_buffers(false);
195 }
196 while (buffers_to_delete != NULL) {
197 BufferNode* bn = buffers_to_delete;
198 buffers_to_delete = bn->next();
199 bn->set_next(NULL);
200 deallocate_buffer(bn);
201 }
202 }
203
204 void G1DirtyCardQueueSet::notify_if_necessary() {
205 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
206 if (num_completed_buffers() > process_completed_buffers_threshold()) {
207 set_process_completed_buffers(true);
208 if (_notify_when_complete)
209 _cbl_mon->notify();
210 }
211 }
212
213 // Merge lists of buffers. Notify the processing threads.
214 // The source queue is emptied as a result. The queues
215 // must share the monitor.
216 void G1DirtyCardQueueSet::merge_bufferlists(G1RedirtyCardsQueueSet* src) {
217 assert(allocator() == src->allocator(), "precondition");
218 const G1RedirtyCardsBufferList from = src->take_all_completed_buffers();
219 if (from._head == NULL) return;
220
221 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
222 if (_completed_buffers_tail == NULL) {
223 assert(_completed_buffers_head == NULL, "Well-formedness");
224 _completed_buffers_head = from._head;
225 _completed_buffers_tail = from._tail;
226 } else {
227 assert(_completed_buffers_head != NULL, "Well formedness");
228 _completed_buffers_tail->set_next(from._head);
229 _completed_buffers_tail = from._tail;
230 }
231 _num_entries_in_completed_buffers += from._entry_count;
232
233 assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
234 _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
235 "Sanity");
236 verify_num_entries_in_completed_buffers();
237 }
238
239 bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
240 BufferNode* node,
241 uint worker_i) {
242 if (cl == NULL) return true;
243 bool result = true;
244 void** buf = BufferNode::make_buffer_from_node(node);
245 size_t i = node->index();
246 size_t limit = buffer_size();
247 for ( ; i < limit; ++i) {
248 CardTable::CardValue* card_ptr = static_cast<CardTable::CardValue*>(buf[i]);
249 assert(card_ptr != NULL, "invariant");
250 if (!cl->do_card_ptr(card_ptr, worker_i)) {
251 result = false; // Incomplete processing.
252 break;
253 }
254 }
255 assert(i <= buffer_size(), "invariant");
256 node->set_index(i);
260 #ifndef ASSERT
261 #define assert_fully_consumed(node, buffer_size)
262 #else
263 #define assert_fully_consumed(node, buffer_size) \
264 do { \
265 size_t _afc_index = (node)->index(); \
266 size_t _afc_size = (buffer_size); \
267 assert(_afc_index == _afc_size, \
268 "Buffer was not fully consumed as claimed: index: " \
269 SIZE_FORMAT ", size: " SIZE_FORMAT, \
270 _afc_index, _afc_size); \
271 } while (0)
272 #endif // ASSERT
273
274 bool G1DirtyCardQueueSet::process_or_enqueue_completed_buffer(BufferNode* node) {
275 if (Thread::current()->is_Java_thread()) {
276 // If the number of buffers exceeds the limit, make this Java
277 // thread do the processing itself. We don't lock to access
278 // buffer count or padding; it is fine to be imprecise here. The
279 // add of padding could overflow, which is treated as unlimited.
280 size_t max_buffers = max_completed_buffers();
281 size_t limit = max_buffers + completed_buffers_padding();
282 if ((num_completed_buffers() > limit) && (limit >= max_buffers)) {
283 if (mut_process_buffer(node)) {
284 return true;
285 }
286 }
287 }
288 enqueue_completed_buffer(node);
289 return false;
290 }
291
292 bool G1DirtyCardQueueSet::mut_process_buffer(BufferNode* node) {
293 guarantee(_free_ids != NULL, "must be");
294
295 uint worker_i = _free_ids->claim_par_id(); // temporarily claim an id
296 G1RefineCardConcurrentlyClosure cl;
297 bool result = apply_closure_to_buffer(&cl, node, worker_i);
298 _free_ids->release_par_id(worker_i); // release the id
299
300 if (result) {
301 assert_fully_consumed(node, buffer_size());
302 Atomic::inc(&_processed_buffers_mut);
341 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
342 abandon_completed_buffers();
343
344 // Since abandon is done only at safepoints, we can safely manipulate
345 // these queues.
346 struct AbandonThreadLogClosure : public ThreadClosure {
347 virtual void do_thread(Thread* t) {
348 G1ThreadLocalData::dirty_card_queue(t).reset();
349 }
350 } closure;
351 Threads::threads_do(&closure);
352
353 G1BarrierSet::shared_dirty_card_queue().reset();
354 }
355
356 void G1DirtyCardQueueSet::concatenate_logs() {
357 // Iterate over all the threads, if we find a partial log add it to
358 // the global list of logs. Temporarily turn off the limit on the number
359 // of outstanding buffers.
360 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
361 size_t old_limit = max_completed_buffers();
362 set_max_completed_buffers(MaxCompletedBuffersUnlimited);
363
364 struct ConcatenateThreadLogClosure : public ThreadClosure {
365 virtual void do_thread(Thread* t) {
366 G1DirtyCardQueue& dcq = G1ThreadLocalData::dirty_card_queue(t);
367 if (!dcq.is_empty()) {
368 dcq.flush();
369 }
370 }
371 } closure;
372 Threads::threads_do(&closure);
373
374 G1BarrierSet::shared_dirty_card_queue().flush();
375 set_max_completed_buffers(old_limit);
376 }
|
67 G1DirtyCardQueue::~G1DirtyCardQueue() {
68 flush();
69 }
70
71 void G1DirtyCardQueue::handle_completed_buffer() {
72 assert(_buf != NULL, "precondition");
73 BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
74 G1DirtyCardQueueSet* dcqs = dirty_card_qset();
75 if (dcqs->process_or_enqueue_completed_buffer(node)) {
76 reset(); // Buffer fully processed, reset index.
77 } else {
78 allocate_buffer(); // Buffer enqueued, get a new one.
79 }
80 }
81
82 G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
83 PtrQueueSet(),
84 _cbl_mon(NULL),
85 _completed_buffers_head(NULL),
86 _completed_buffers_tail(NULL),
87 _num_cards(0),
88 _process_cards_threshold(ProcessCardsThresholdNever),
89 _process_completed_buffers(false),
90 _notify_when_complete(notify_when_complete),
91 _max_cards(MaxCardsUnlimited),
92 _max_cards_padding(0),
93 _free_ids(NULL),
94 _processed_buffers_mut(0),
95 _processed_buffers_rs_thread(0)
96 {
97 _all_active = true;
98 }
99
100 G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
101 abandon_completed_buffers();
102 delete _free_ids;
103 }
104
105 // Determines how many mutator threads can process the buffers in parallel.
106 uint G1DirtyCardQueueSet::num_par_ids() {
107 return (uint)os::initial_active_processor_count();
108 }
109
110 void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
111 BufferNode::Allocator* allocator,
112 bool init_free_ids) {
116 if (init_free_ids) {
117 _free_ids = new G1FreeIdSet(0, num_par_ids());
118 }
119 }
120
121 void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) {
122 G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
123 }
124
125 void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
126 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
127 cbn->set_next(NULL);
128 if (_completed_buffers_tail == NULL) {
129 assert(_completed_buffers_head == NULL, "Well-formedness");
130 _completed_buffers_head = cbn;
131 _completed_buffers_tail = cbn;
132 } else {
133 _completed_buffers_tail->set_next(cbn);
134 _completed_buffers_tail = cbn;
135 }
136 _num_cards += buffer_size() - cbn->index();
137
138 if (!process_completed_buffers() &&
139 (num_cards() > process_cards_threshold())) {
140 set_process_completed_buffers(true);
141 if (_notify_when_complete) {
142 _cbl_mon->notify_all();
143 }
144 }
145 verify_num_cards();
146 }
147
148 BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) {
149 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
150
151 if (num_cards() <= stop_at) {
152 return NULL;
153 }
154
155 assert(num_cards() > 0, "invariant");
156 assert(_completed_buffers_head != NULL, "invariant");
157 assert(_completed_buffers_tail != NULL, "invariant");
158
159 BufferNode* bn = _completed_buffers_head;
160 _num_cards -= buffer_size() - bn->index();
161 _completed_buffers_head = bn->next();
162 if (_completed_buffers_head == NULL) {
163 assert(num_cards() == 0, "invariant");
164 _completed_buffers_tail = NULL;
165 set_process_completed_buffers(false);
166 }
167 verify_num_cards();
168 bn->set_next(NULL);
169 return bn;
170 }
171
172 #ifdef ASSERT
173 void G1DirtyCardQueueSet::verify_num_cards() const {
174 size_t actual = 0;
175 BufferNode* cur = _completed_buffers_head;
176 while (cur != NULL) {
177 actual += buffer_size() - cur->index();
178 cur = cur->next();
179 }
180 assert(actual == _num_cards,
181 "Num entries in completed buffers should be " SIZE_FORMAT " but are " SIZE_FORMAT,
182 _num_cards, actual);
183 }
184 #endif
185
186 void G1DirtyCardQueueSet::abandon_completed_buffers() {
187 BufferNode* buffers_to_delete = NULL;
188 {
189 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
190 buffers_to_delete = _completed_buffers_head;
191 _completed_buffers_head = NULL;
192 _completed_buffers_tail = NULL;
193 _num_cards = 0;
194 set_process_completed_buffers(false);
195 }
196 while (buffers_to_delete != NULL) {
197 BufferNode* bn = buffers_to_delete;
198 buffers_to_delete = bn->next();
199 bn->set_next(NULL);
200 deallocate_buffer(bn);
201 }
202 }
203
204 void G1DirtyCardQueueSet::notify_if_necessary() {
205 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
206 if (num_cards() > process_cards_threshold()) {
207 set_process_completed_buffers(true);
208 if (_notify_when_complete)
209 _cbl_mon->notify();
210 }
211 }
212
213 // Merge lists of buffers. Notify the processing threads.
214 // The source queue is emptied as a result. The queues
215 // must share the monitor.
216 void G1DirtyCardQueueSet::merge_bufferlists(G1RedirtyCardsQueueSet* src) {
217 assert(allocator() == src->allocator(), "precondition");
218 const G1RedirtyCardsBufferList from = src->take_all_completed_buffers();
219 if (from._head == NULL) return;
220
221 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
222 if (_completed_buffers_tail == NULL) {
223 assert(_completed_buffers_head == NULL, "Well-formedness");
224 _completed_buffers_head = from._head;
225 _completed_buffers_tail = from._tail;
226 } else {
227 assert(_completed_buffers_head != NULL, "Well formedness");
228 _completed_buffers_tail->set_next(from._head);
229 _completed_buffers_tail = from._tail;
230 }
231 _num_cards += from._entry_count;
232
233 assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
234 _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
235 "Sanity");
236 verify_num_cards();
237 }
238
239 bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
240 BufferNode* node,
241 uint worker_i) {
242 if (cl == NULL) return true;
243 bool result = true;
244 void** buf = BufferNode::make_buffer_from_node(node);
245 size_t i = node->index();
246 size_t limit = buffer_size();
247 for ( ; i < limit; ++i) {
248 CardTable::CardValue* card_ptr = static_cast<CardTable::CardValue*>(buf[i]);
249 assert(card_ptr != NULL, "invariant");
250 if (!cl->do_card_ptr(card_ptr, worker_i)) {
251 result = false; // Incomplete processing.
252 break;
253 }
254 }
255 assert(i <= buffer_size(), "invariant");
256 node->set_index(i);
260 #ifndef ASSERT
261 #define assert_fully_consumed(node, buffer_size)
262 #else
263 #define assert_fully_consumed(node, buffer_size) \
264 do { \
265 size_t _afc_index = (node)->index(); \
266 size_t _afc_size = (buffer_size); \
267 assert(_afc_index == _afc_size, \
268 "Buffer was not fully consumed as claimed: index: " \
269 SIZE_FORMAT ", size: " SIZE_FORMAT, \
270 _afc_index, _afc_size); \
271 } while (0)
272 #endif // ASSERT
273
274 bool G1DirtyCardQueueSet::process_or_enqueue_completed_buffer(BufferNode* node) {
275 if (Thread::current()->is_Java_thread()) {
276 // If the number of buffers exceeds the limit, make this Java
277 // thread do the processing itself. We don't lock to access
278 // buffer count or padding; it is fine to be imprecise here. The
279 // add of padding could overflow, which is treated as unlimited.
280 size_t limit = max_cards() + max_cards_padding();
281 if ((num_cards() > limit) && (limit >= max_cards())) {
282 if (mut_process_buffer(node)) {
283 return true;
284 }
285 }
286 }
287 enqueue_completed_buffer(node);
288 return false;
289 }
290
291 bool G1DirtyCardQueueSet::mut_process_buffer(BufferNode* node) {
292 guarantee(_free_ids != NULL, "must be");
293
294 uint worker_i = _free_ids->claim_par_id(); // temporarily claim an id
295 G1RefineCardConcurrentlyClosure cl;
296 bool result = apply_closure_to_buffer(&cl, node, worker_i);
297 _free_ids->release_par_id(worker_i); // release the id
298
299 if (result) {
300 assert_fully_consumed(node, buffer_size());
301 Atomic::inc(&_processed_buffers_mut);
340 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
341 abandon_completed_buffers();
342
343 // Since abandon is done only at safepoints, we can safely manipulate
344 // these queues.
345 struct AbandonThreadLogClosure : public ThreadClosure {
346 virtual void do_thread(Thread* t) {
347 G1ThreadLocalData::dirty_card_queue(t).reset();
348 }
349 } closure;
350 Threads::threads_do(&closure);
351
352 G1BarrierSet::shared_dirty_card_queue().reset();
353 }
354
355 void G1DirtyCardQueueSet::concatenate_logs() {
356 // Iterate over all the threads, if we find a partial log add it to
357 // the global list of logs. Temporarily turn off the limit on the number
358 // of outstanding buffers.
359 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
360 size_t old_limit = max_cards();
361 set_max_cards(MaxCardsUnlimited);
362
363 struct ConcatenateThreadLogClosure : public ThreadClosure {
364 virtual void do_thread(Thread* t) {
365 G1DirtyCardQueue& dcq = G1ThreadLocalData::dirty_card_queue(t);
366 if (!dcq.is_empty()) {
367 dcq.flush();
368 }
369 }
370 } closure;
371 Threads::threads_do(&closure);
372
373 G1BarrierSet::shared_dirty_card_queue().flush();
374 set_max_cards(old_limit);
375 }
|