< 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 >