< prev index next >
src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
Print this page
rev 58057 : imported patch improved_paused_handling
*** 226,248 ****
_primary_refinement_thread->activate();
}
}
BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) {
! enqueue_previous_paused_buffers();
!
! // Check for insufficient cards to satisfy request. We only do this once,
! // up front, rather than on each iteration below, since the test is racy
! // regardless of when we do it.
! if (Atomic::load_acquire(&_num_cards) <= stop_at) {
return NULL;
}
BufferNode* result = _completed.pop();
! if (result != NULL) {
! Atomic::sub(&_num_cards, buffer_size() - result->index());
}
return result;
}
#ifdef ASSERT
void G1DirtyCardQueueSet::verify_num_cards() const {
--- 226,246 ----
_primary_refinement_thread->activate();
}
}
BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) {
! if (Atomic::load_acquire(&_num_cards) < stop_at) {
return NULL;
}
BufferNode* result = _completed.pop();
! if (result == NULL) { // Unlikely if no paused buffers.
! enqueue_previous_paused_buffers();
! result = _completed.pop();
! if (result == NULL) return NULL;
}
+ Atomic::sub(&_num_cards, buffer_size() - result->index());
return result;
}
#ifdef ASSERT
void G1DirtyCardQueueSet::verify_num_cards() const {
*** 296,330 ****
G1DirtyCardQueueSet::PausedBuffers::PausedBuffers() : _plist(NULL) {}
#ifdef ASSERT
G1DirtyCardQueueSet::PausedBuffers::~PausedBuffers() {
! assert(is_empty(), "invariant");
}
#endif // ASSERT
- bool G1DirtyCardQueueSet::PausedBuffers::is_empty() const {
- return Atomic::load(&_plist) == NULL;
- }
-
void G1DirtyCardQueueSet::PausedBuffers::add(BufferNode* node) {
assert_not_at_safepoint();
PausedList* plist = Atomic::load_acquire(&_plist);
! if (plist != NULL) {
! // Already have a next list, so use it. We know it's a next list because
! // of the precondition that take_previous() has already been called.
! assert(plist->is_next(), "invariant");
! } else {
// Try to install a new next list.
plist = new PausedList();
PausedList* old_plist = Atomic::cmpxchg(&_plist, (PausedList*)NULL, plist);
if (old_plist != NULL) {
// Some other thread installed a new next list. Use it instead.
delete plist;
plist = old_plist;
}
}
plist->add(node);
}
G1DirtyCardQueueSet::HeadTail G1DirtyCardQueueSet::PausedBuffers::take_previous() {
assert_not_at_safepoint();
--- 294,321 ----
G1DirtyCardQueueSet::PausedBuffers::PausedBuffers() : _plist(NULL) {}
#ifdef ASSERT
G1DirtyCardQueueSet::PausedBuffers::~PausedBuffers() {
! assert(Atomic::load(&_plist) == NULL, "invariant");
}
#endif // ASSERT
void G1DirtyCardQueueSet::PausedBuffers::add(BufferNode* node) {
assert_not_at_safepoint();
PausedList* plist = Atomic::load_acquire(&_plist);
! if (plist == NULL) {
// Try to install a new next list.
plist = new PausedList();
PausedList* old_plist = Atomic::cmpxchg(&_plist, (PausedList*)NULL, plist);
if (old_plist != NULL) {
// Some other thread installed a new next list. Use it instead.
delete plist;
plist = old_plist;
}
}
+ assert(plist->is_next(), "invariant");
plist->add(node);
}
G1DirtyCardQueueSet::HeadTail G1DirtyCardQueueSet::PausedBuffers::take_previous() {
assert_not_at_safepoint();
*** 364,373 ****
--- 355,366 ----
}
void G1DirtyCardQueueSet::record_paused_buffer(BufferNode* node) {
assert_not_at_safepoint();
assert(node->next() == NULL, "precondition");
+ // Ensure there aren't any paused buffers from a previous safepoint.
+ enqueue_previous_paused_buffers();
// Cards for paused buffers are included in count, to contribute to
// notification checking after the coming safepoint if it doesn't GC.
// Note that this means the queue's _num_cards differs from the number
// of cards in the queued buffers when there are paused buffers.
Atomic::add(&_num_cards, buffer_size() - node->index());
*** 382,410 ****
}
}
void G1DirtyCardQueueSet::enqueue_previous_paused_buffers() {
assert_not_at_safepoint();
- // The fast-path still satisfies the precondition for record_paused_buffer
- // and PausedBuffers::add, even with a racy test. If there are paused
- // buffers from a previous safepoint, is_empty() will return false; there
- // will have been a safepoint between recording and test, so there can't be
- // a false negative (is_empty() returns true) while such buffers are present.
- // If is_empty() is false, there are two cases:
- //
- // (1) There were paused buffers from a previous safepoint. A concurrent
- // caller may take and enqueue them first, but that's okay; the precondition
- // for a possible later record_paused_buffer by this thread will still hold.
- //
- // (2) There are paused buffers for a requested next safepoint.
- //
- // In each of those cases some effort may be spent detecting and dealing
- // with those circumstances; any wasted effort in such cases is expected to
- // be well compensated by the fast path.
- if (!_paused.is_empty()) {
enqueue_paused_buffers_aux(_paused.take_previous());
- }
}
void G1DirtyCardQueueSet::enqueue_all_paused_buffers() {
assert_at_safepoint();
enqueue_paused_buffers_aux(_paused.take_all());
--- 375,385 ----
< prev index next >