6940310: G1: MT-unsafe calls to CM::region_stack_push() / CM::region_stack_pop()

Calling the methods region_stack_push() and region_stack_pop() concurrent is not MT-safe. The assumption is that we will only call region_stack_push() during a GC pause and region_stack_pop() during marking. Unfortunately, we also call region_stack_push() during marking which seems to be introducing subtle marking failures. This change introduces lock-based methods for pushing / popping to be called during marking.

Reviewed-by: iveresov, johnc
This commit is contained in:
Antonios Printezis 2010-04-05 12:19:22 -04:00
parent 9545c0521e
commit 2e3363d109
4 changed files with 87 additions and 4 deletions

View file

@ -297,6 +297,11 @@ void CMRegionStack::push(MemRegion mr) {
}
}
// Currently we do not call this at all. Normally we would call it
// during the concurrent marking / remark phases but we now call
// the lock-based version instead. But we might want to resurrect this
// code in the future. So, we'll leave it here commented out.
#if 0
MemRegion CMRegionStack::pop() {
while (true) {
// Otherwise...
@ -321,6 +326,41 @@ MemRegion CMRegionStack::pop() {
// Otherwise, we need to try again.
}
}
#endif // 0
void CMRegionStack::push_with_lock(MemRegion mr) {
assert(mr.word_size() > 0, "Precondition");
MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag);
if (isFull()) {
_overflow = true;
return;
}
_base[_index] = mr;
_index += 1;
}
MemRegion CMRegionStack::pop_with_lock() {
MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag);
while (true) {
if (_index == 0) {
return MemRegion();
}
_index -= 1;
MemRegion mr = _base[_index];
if (mr.start() != NULL) {
assert(mr.end() != NULL, "invariant");
assert(mr.word_size() > 0, "invariant");
return mr;
} else {
// that entry was invalidated... let's skip it
assert(mr.end() == NULL, "invariant");
}
}
}
bool CMRegionStack::invalidate_entries_into_cset() {
bool result = false;
@ -3363,7 +3403,7 @@ void CMTask::drain_region_stack(BitMapClosure* bc) {
gclog_or_tty->print_cr("[%d] draining region stack, size = %d",
_task_id, _cm->region_stack_size());
MemRegion mr = _cm->region_stack_pop();
MemRegion mr = _cm->region_stack_pop_with_lock();
// it returns MemRegion() if the pop fails
statsOnly(if (mr.start() != NULL) ++_region_stack_pops );
@ -3384,7 +3424,7 @@ void CMTask::drain_region_stack(BitMapClosure* bc) {
if (has_aborted())
mr = MemRegion();
else {
mr = _cm->region_stack_pop();
mr = _cm->region_stack_pop_with_lock();
// it returns MemRegion() if the pop fails
statsOnly(if (mr.start() != NULL) ++_region_stack_pops );
}
@ -3417,7 +3457,7 @@ void CMTask::drain_region_stack(BitMapClosure* bc) {
}
// Now push the part of the region we didn't scan on the
// region stack to make sure a task scans it later.
_cm->region_stack_push(newRegion);
_cm->region_stack_push_with_lock(newRegion);
}
// break from while
mr = MemRegion();