src/share/vm/gc_implementation/g1/concurrentMark.cpp

Print this page
rev 6345 : 8040803: G1: Concurrent mark hangs when mark stack overflows
Reviewed-by: TDB

*** 976,1003 **** } if (concurrent()) { SuspendibleThreadSet::leave(); } ! _first_overflow_barrier_sync.enter(); if (concurrent()) { SuspendibleThreadSet::join(); } // at this point everyone should have synced up and not be doing any // more work if (verbose_low()) { gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id); } // If we're executing the concurrent phase of marking, reset the marking // state; otherwise the marking state is reset after reference processing, // during the remark pause. // If we reset here as a result of an overflow during the remark we will // see assertion failures from any subsequent set_concurrency_and_phase() // calls. ! if (concurrent()) { // let the task associated with with worker 0 do this if (worker_id == 0) { // task 0 is responsible for clearing the global data structures // We should be here because of an overflow. During STW we should // not clear the overflow flag since we rely on it being true when --- 976,1012 ---- } if (concurrent()) { SuspendibleThreadSet::leave(); } ! ! bool barrier_aborted = !_first_overflow_barrier_sync.enter(); ! if (concurrent()) { SuspendibleThreadSet::join(); } // at this point everyone should have synced up and not be doing any // more work if (verbose_low()) { + if (barrier_aborted) { + gclog_or_tty->print_cr("[%u] aborted first barrier", worker_id); + } else { gclog_or_tty->print_cr("[%u] leaving first barrier", worker_id); } + } // If we're executing the concurrent phase of marking, reset the marking // state; otherwise the marking state is reset after reference processing, // during the remark pause. // If we reset here as a result of an overflow during the remark we will // see assertion failures from any subsequent set_concurrency_and_phase() // calls. ! // If the barrier aborted we don't need to reset the marking state here ! // since ConcurrentMark::abort() did that for us and we will now ignore ! // the overflow condition and just abort the whole marking phase. ! if (!barrier_aborted && concurrent()) { // let the task associated with with worker 0 do this if (worker_id == 0) { // task 0 is responsible for clearing the global data structures // We should be here because of an overflow. During STW we should // not clear the overflow flag since we rely on it being true when
*** 1024,1042 **** } if (concurrent()) { SuspendibleThreadSet::leave(); } ! _second_overflow_barrier_sync.enter(); if (concurrent()) { SuspendibleThreadSet::join(); } // at this point everything should be re-initialized and ready to go if (verbose_low()) { gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id); } } #ifndef PRODUCT void ForceOverflowSettings::init() { _num_remaining = G1ConcMarkForceOverflow; --- 1033,1057 ---- } if (concurrent()) { SuspendibleThreadSet::leave(); } ! ! bool barrier_aborted = !_second_overflow_barrier_sync.enter(); ! if (concurrent()) { SuspendibleThreadSet::join(); } // at this point everything should be re-initialized and ready to go if (verbose_low()) { + if (barrier_aborted) { + gclog_or_tty->print_cr("[%u] aborted second barrier", worker_id); + } else { gclog_or_tty->print_cr("[%u] leaving second barrier", worker_id); } + } } #ifndef PRODUCT void ForceOverflowSettings::init() { _num_remaining = G1ConcMarkForceOverflow;
*** 3238,3247 **** --- 3253,3264 ---- // Empty mark stack reset_marking_state(); for (uint i = 0; i < _max_worker_id; ++i) { _tasks[i]->clear_region_fields(); } + _first_overflow_barrier_sync.abort(); + _second_overflow_barrier_sync.abort(); _has_aborted = true; SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); satb_mq_set.abandon_partial_marking(); // This can be called either during or outside marking, we'll read