233 }
234 OrderAccess::release_store(&_transfer_lock, false);
235 return true;
236 }
237
238 size_t BufferNode::Allocator::reduce_free_list(size_t remove_goal) {
239 try_transfer_pending();
240 size_t removed = 0;
241 for ( ; removed < remove_goal; ++removed) {
242 BufferNode* node = _free_list.pop();
243 if (node == NULL) break;
244 BufferNode::deallocate(node);
245 }
246 size_t new_count = Atomic::sub(removed, &_free_count);
247 log_debug(gc, ptrqueue, freelist)
248 ("Reduced %s free list by " SIZE_FORMAT " to " SIZE_FORMAT,
249 name(), removed, new_count);
250 return removed;
251 }
252
253 PtrQueueSet::PtrQueueSet(bool notify_when_complete) :
254 _allocator(NULL),
255 _cbl_mon(NULL),
256 _completed_buffers_head(NULL),
257 _completed_buffers_tail(NULL),
258 _n_completed_buffers(0),
259 _process_completed_buffers_threshold(ProcessCompletedBuffersThresholdNever),
260 _process_completed_buffers(false),
261 _notify_when_complete(notify_when_complete),
262 _all_active(false)
263 {}
264
265 PtrQueueSet::~PtrQueueSet() {
266 // There are presently only a couple (derived) instances ever
267 // created, and they are permanent, so no harm currently done by
268 // doing nothing here.
269 }
270
271 void PtrQueueSet::initialize(Monitor* cbl_mon,
272 BufferNode::Allocator* allocator) {
273 assert(cbl_mon != NULL && allocator != NULL, "Init order issue?");
274 _cbl_mon = cbl_mon;
275 _allocator = allocator;
276 }
277
278 void** PtrQueueSet::allocate_buffer() {
279 BufferNode* node = _allocator->allocate();
280 return BufferNode::make_buffer_from_node(node);
281 }
282
283 void PtrQueueSet::deallocate_buffer(BufferNode* node) {
284 _allocator->release(node);
285 }
286
287 void PtrQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
288 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
289 cbn->set_next(NULL);
290 if (_completed_buffers_tail == NULL) {
291 assert(_completed_buffers_head == NULL, "Well-formedness");
292 _completed_buffers_head = cbn;
293 _completed_buffers_tail = cbn;
294 } else {
295 _completed_buffers_tail->set_next(cbn);
296 _completed_buffers_tail = cbn;
297 }
298 _n_completed_buffers++;
299
300 if (!_process_completed_buffers &&
301 (_n_completed_buffers > _process_completed_buffers_threshold)) {
302 _process_completed_buffers = true;
303 if (_notify_when_complete) {
304 _cbl_mon->notify();
305 }
306 }
307 assert_completed_buffers_list_len_correct_locked();
308 }
309
310 BufferNode* PtrQueueSet::get_completed_buffer(size_t stop_at) {
311 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
312
313 if (_n_completed_buffers <= stop_at) {
314 return NULL;
315 }
316
317 assert(_n_completed_buffers > 0, "invariant");
318 assert(_completed_buffers_head != NULL, "invariant");
319 assert(_completed_buffers_tail != NULL, "invariant");
320
321 BufferNode* bn = _completed_buffers_head;
322 _n_completed_buffers--;
323 _completed_buffers_head = bn->next();
324 if (_completed_buffers_head == NULL) {
325 assert(_n_completed_buffers == 0, "invariant");
326 _completed_buffers_tail = NULL;
327 _process_completed_buffers = false;
328 }
329 assert_completed_buffers_list_len_correct_locked();
330 bn->set_next(NULL);
331 return bn;
332 }
333
334 void PtrQueueSet::abandon_completed_buffers() {
335 BufferNode* buffers_to_delete = NULL;
336 {
337 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
338 buffers_to_delete = _completed_buffers_head;
339 _completed_buffers_head = NULL;
340 _completed_buffers_tail = NULL;
341 _n_completed_buffers = 0;
342 _process_completed_buffers = false;
343 }
344 while (buffers_to_delete != NULL) {
345 BufferNode* bn = buffers_to_delete;
346 buffers_to_delete = bn->next();
347 bn->set_next(NULL);
348 deallocate_buffer(bn);
349 }
350 }
351
352 #ifdef ASSERT
353
354 void PtrQueueSet::assert_completed_buffers_list_len_correct_locked() {
355 assert_lock_strong(_cbl_mon);
356 size_t n = 0;
357 for (BufferNode* bn = _completed_buffers_head; bn != NULL; bn = bn->next()) {
358 ++n;
359 }
360 assert(n == _n_completed_buffers,
361 "Completed buffer length is wrong: counted: " SIZE_FORMAT
362 ", expected: " SIZE_FORMAT, n, _n_completed_buffers);
363 }
364
365 #endif // ASSERT
366
367 // Merge lists of buffers. Notify the processing threads.
368 // The source queue is emptied as a result. The queues
369 // must share the monitor.
370 void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) {
371 assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
372 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
373 if (_completed_buffers_tail == NULL) {
374 assert(_completed_buffers_head == NULL, "Well-formedness");
375 _completed_buffers_head = src->_completed_buffers_head;
376 _completed_buffers_tail = src->_completed_buffers_tail;
377 } else {
378 assert(_completed_buffers_head != NULL, "Well formedness");
379 if (src->_completed_buffers_head != NULL) {
380 _completed_buffers_tail->set_next(src->_completed_buffers_head);
381 _completed_buffers_tail = src->_completed_buffers_tail;
382 }
383 }
384 _n_completed_buffers += src->_n_completed_buffers;
385
386 src->_n_completed_buffers = 0;
387 src->_completed_buffers_head = NULL;
388 src->_completed_buffers_tail = NULL;
389 src->_process_completed_buffers = false;
390
391 assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
392 _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
393 "Sanity");
394 assert_completed_buffers_list_len_correct_locked();
395 }
396
397 void PtrQueueSet::notify_if_necessary() {
398 MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
399 if (_n_completed_buffers > _process_completed_buffers_threshold) {
400 _process_completed_buffers = true;
401 if (_notify_when_complete)
402 _cbl_mon->notify();
403 }
404 }
|
233 }
234 OrderAccess::release_store(&_transfer_lock, false);
235 return true;
236 }
237
238 size_t BufferNode::Allocator::reduce_free_list(size_t remove_goal) {
239 try_transfer_pending();
240 size_t removed = 0;
241 for ( ; removed < remove_goal; ++removed) {
242 BufferNode* node = _free_list.pop();
243 if (node == NULL) break;
244 BufferNode::deallocate(node);
245 }
246 size_t new_count = Atomic::sub(removed, &_free_count);
247 log_debug(gc, ptrqueue, freelist)
248 ("Reduced %s free list by " SIZE_FORMAT " to " SIZE_FORMAT,
249 name(), removed, new_count);
250 return removed;
251 }
252
253 PtrQueueSet::PtrQueueSet() :
254 _allocator(NULL),
255 _all_active(false)
256 {}
257
258 PtrQueueSet::~PtrQueueSet() {}
259
260 void PtrQueueSet::initialize(BufferNode::Allocator* allocator) {
261 assert(allocator != NULL, "Init order issue?");
262 _allocator = allocator;
263 }
264
265 void** PtrQueueSet::allocate_buffer() {
266 BufferNode* node = _allocator->allocate();
267 return BufferNode::make_buffer_from_node(node);
268 }
269
270 void PtrQueueSet::deallocate_buffer(BufferNode* node) {
271 _allocator->release(node);
272 }
273
|