< prev index next >
src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
Print this page
rev 55389 : [mq]: satb_lock_free
*** 76,86 ****
allocate_buffer(); // Buffer enqueued, get a new one.
}
}
G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
! PtrQueueSet(notify_when_complete),
_max_completed_buffers(MaxCompletedBuffersUnlimited),
_completed_buffers_padding(0),
_free_ids(NULL),
_processed_buffers_mut(0),
_processed_buffers_rs_thread(0),
--- 76,93 ----
allocate_buffer(); // Buffer enqueued, get a new one.
}
}
G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
! PtrQueueSet(),
! _cbl_mon(NULL),
! _completed_buffers_head(NULL),
! _completed_buffers_tail(NULL),
! _n_completed_buffers(0),
! _process_completed_buffers_threshold(ProcessCompletedBuffersThresholdNever),
! _process_completed_buffers(false),
! _notify_when_complete(notify_when_complete),
_max_completed_buffers(MaxCompletedBuffersUnlimited),
_completed_buffers_padding(0),
_free_ids(NULL),
_processed_buffers_mut(0),
_processed_buffers_rs_thread(0),
*** 88,97 ****
--- 95,105 ----
{
_all_active = true;
}
G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
+ abandon_completed_buffers();
delete _free_ids;
}
// Determines how many mutator threads can process the buffers in parallel.
uint G1DirtyCardQueueSet::num_par_ids() {
*** 99,118 ****
}
void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
BufferNode::Allocator* allocator,
bool init_free_ids) {
! PtrQueueSet::initialize(cbl_mon, allocator);
if (init_free_ids) {
_free_ids = new G1FreeIdSet(0, num_par_ids());
}
}
void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) {
G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
}
bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
BufferNode* node,
bool consume,
uint worker_i) {
if (cl == NULL) return true;
--- 107,245 ----
}
void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
BufferNode::Allocator* allocator,
bool init_free_ids) {
! PtrQueueSet::initialize(allocator);
! assert(_cbl_mon == NULL, "Init order issue?");
! _cbl_mon = cbl_mon;
if (init_free_ids) {
_free_ids = new G1FreeIdSet(0, num_par_ids());
}
}
void G1DirtyCardQueueSet::handle_zero_index_for_thread(Thread* t) {
G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
}
+ void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ cbn->set_next(NULL);
+ if (_completed_buffers_tail == NULL) {
+ assert(_completed_buffers_head == NULL, "Well-formedness");
+ _completed_buffers_head = cbn;
+ _completed_buffers_tail = cbn;
+ } else {
+ _completed_buffers_tail->set_next(cbn);
+ _completed_buffers_tail = cbn;
+ }
+ _n_completed_buffers++;
+
+ if (!process_completed_buffers() &&
+ (_n_completed_buffers > process_completed_buffers_threshold())) {
+ set_process_completed_buffers(true);
+ if (_notify_when_complete) {
+ _cbl_mon->notify_all();
+ }
+ }
+ assert_completed_buffers_list_len_correct_locked();
+ }
+
+ BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+
+ if (_n_completed_buffers <= stop_at) {
+ return NULL;
+ }
+
+ assert(_n_completed_buffers > 0, "invariant");
+ assert(_completed_buffers_head != NULL, "invariant");
+ assert(_completed_buffers_tail != NULL, "invariant");
+
+ BufferNode* bn = _completed_buffers_head;
+ _n_completed_buffers--;
+ _completed_buffers_head = bn->next();
+ if (_completed_buffers_head == NULL) {
+ assert(_n_completed_buffers == 0, "invariant");
+ _completed_buffers_tail = NULL;
+ set_process_completed_buffers(false);
+ }
+ assert_completed_buffers_list_len_correct_locked();
+ bn->set_next(NULL);
+ return bn;
+ }
+
+ void G1DirtyCardQueueSet::abandon_completed_buffers() {
+ BufferNode* buffers_to_delete = NULL;
+ {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ buffers_to_delete = _completed_buffers_head;
+ _completed_buffers_head = NULL;
+ _completed_buffers_tail = NULL;
+ _n_completed_buffers = 0;
+ set_process_completed_buffers(false);
+ }
+ while (buffers_to_delete != NULL) {
+ BufferNode* bn = buffers_to_delete;
+ buffers_to_delete = bn->next();
+ bn->set_next(NULL);
+ deallocate_buffer(bn);
+ }
+ }
+
+ void G1DirtyCardQueueSet::notify_if_necessary() {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ if (_n_completed_buffers > process_completed_buffers_threshold()) {
+ set_process_completed_buffers(true);
+ if (_notify_when_complete)
+ _cbl_mon->notify();
+ }
+ }
+
+ #ifdef ASSERT
+ void G1DirtyCardQueueSet::assert_completed_buffers_list_len_correct_locked() {
+ assert_lock_strong(_cbl_mon);
+ size_t n = 0;
+ for (BufferNode* bn = _completed_buffers_head; bn != NULL; bn = bn->next()) {
+ ++n;
+ }
+ assert(n == _n_completed_buffers,
+ "Completed buffer length is wrong: counted: " SIZE_FORMAT
+ ", expected: " SIZE_FORMAT, n, _n_completed_buffers);
+ }
+ #endif // ASSERT
+
+ // Merge lists of buffers. Notify the processing threads.
+ // The source queue is emptied as a result. The queues
+ // must share the monitor.
+ void G1DirtyCardQueueSet::merge_bufferlists(G1DirtyCardQueueSet *src) {
+ assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ if (_completed_buffers_tail == NULL) {
+ assert(_completed_buffers_head == NULL, "Well-formedness");
+ _completed_buffers_head = src->_completed_buffers_head;
+ _completed_buffers_tail = src->_completed_buffers_tail;
+ } else {
+ assert(_completed_buffers_head != NULL, "Well formedness");
+ if (src->_completed_buffers_head != NULL) {
+ _completed_buffers_tail->set_next(src->_completed_buffers_head);
+ _completed_buffers_tail = src->_completed_buffers_tail;
+ }
+ }
+ _n_completed_buffers += src->_n_completed_buffers;
+
+ src->_n_completed_buffers = 0;
+ src->_completed_buffers_head = NULL;
+ src->_completed_buffers_tail = NULL;
+ src->set_process_completed_buffers(false);
+
+ assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
+ _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
+ "Sanity");
+ assert_completed_buffers_list_len_correct_locked();
+ }
+
bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
BufferNode* node,
bool consume,
uint worker_i) {
if (cl == NULL) return true;
< prev index next >