8345750: Shenandoah: Test TestJcmdHeapDump.java#aggressive intermittent assert(gc_cause() == GCCause::_no_gc) failed: Over-writing cause

Reviewed-by: ysr
Backport-of: 6a29a8110ec38b4adc8163ba8651cbc935353f1d
This commit is contained in:
William Kemper 2025-01-21 23:10:22 +00:00
parent 1495f7addb
commit febcfd69ff
4 changed files with 22 additions and 8 deletions

View File

@ -140,8 +140,8 @@ void VM_GC_Operation::doit_epilogue() {
}
bool VM_GC_HeapInspection::doit_prologue() {
if (_full_gc && UseZGC) {
// ZGC cannot perform a synchronous GC cycle from within the VM thread.
if (_full_gc && (UseZGC || UseShenandoahGC)) {
// ZGC and Shenandoah cannot perform a synchronous GC cycle from within the VM thread.
// So VM_GC_HeapInspection::collect() is a noop. To respect the _full_gc
// flag a synchronous GC cycle is performed from the caller thread in the
// prologue.

View File

@ -1468,6 +1468,18 @@ size_t ShenandoahHeap::max_tlab_size() const {
return ShenandoahHeapRegion::max_tlab_size_words();
}
void ShenandoahHeap::collect_as_vm_thread(GCCause::Cause cause) {
// These requests are ignored because we can't easily have Shenandoah jump into
// a synchronous (degenerated or full) cycle while it is in the middle of a concurrent
// cycle. We _could_ cancel the concurrent cycle and then try to run a cycle directly
// on the VM thread, but this would confuse the control thread mightily and doesn't
// seem worth the trouble. Instead, we will have the caller thread run (and wait for) a
// concurrent cycle in the prologue of the heap inspect/dump operation. This is how
// other concurrent collectors in the JVM handle this scenario as well.
assert(Thread::current()->is_VM_thread(), "Should be the VM thread");
guarantee(cause == GCCause::_heap_dump || cause == GCCause::_heap_inspection, "Invalid cause");
}
void ShenandoahHeap::collect(GCCause::Cause cause) {
control_thread()->request_gc(cause);
}
@ -1548,7 +1560,9 @@ void ShenandoahHeap::set_active_generation() {
void ShenandoahHeap::on_cycle_start(GCCause::Cause cause, ShenandoahGeneration* generation) {
shenandoah_policy()->record_collection_cause(cause);
assert(gc_cause() == GCCause::_no_gc, "Over-writing cause");
const GCCause::Cause current = gc_cause();
assert(current == GCCause::_no_gc, "Over-writing cause: %s, with: %s",
GCCause::to_string(current), GCCause::to_string(cause));
assert(_gc_generation == nullptr, "Over-writing _gc_generation");
set_gc_cause(cause);

View File

@ -608,6 +608,7 @@ public:
MemRegion reserved_region() const { return _reserved; }
bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); }
void collect_as_vm_thread(GCCause::Cause cause) override;
void collect(GCCause::Cause cause) override;
void do_full_collection(bool clear_all_soft_refs) override;

View File

@ -2349,11 +2349,10 @@ void VM_HeapDumper::dump_threads(AbstractDumpWriter* writer) {
}
bool VM_HeapDumper::doit_prologue() {
if (_gc_before_heap_dump && UseZGC) {
// ZGC cannot perform a synchronous GC cycle from within the VM thread.
// So ZCollectedHeap::collect_as_vm_thread() is a noop. To respect the
// _gc_before_heap_dump flag a synchronous GC cycle is performed from
// the caller thread in the prologue.
if (_gc_before_heap_dump && (UseZGC || UseShenandoahGC)) {
// ZGC and Shenandoah cannot perform a synchronous GC cycle from within the VM thread.
// So collect_as_vm_thread() is a noop. To respect the _gc_before_heap_dump flag a
// synchronous GC cycle is performed from the caller thread in the prologue.
Universe::heap()->collect(GCCause::_heap_dump);
}
return VM_GC_Operation::doit_prologue();