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