--- old/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp 2020-08-18 18:23:26.428277425 +0200 +++ new/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.cpp 2020-08-18 18:23:26.296275550 +0200 @@ -42,6 +42,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/vmThread.hpp" #include "utilities/debug.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/ticks.hpp" G1ConcurrentMarkThread::G1ConcurrentMarkThread(G1ConcurrentMark* cm) : @@ -55,6 +56,31 @@ create_and_start(); } +void G1ConcurrentMarkThread::set_idle() { + assert(_state != StartMark && _state != StartUndo, "must not be starting a new cycle"); + _state = Idle; +} + +void G1ConcurrentMarkThread::set_started(bool full_cycle) { + assert(_state == Idle, "cycle in progress"); + _state = full_cycle ? StartMark : StartUndo; +} + +void G1ConcurrentMarkThread::set_in_progress() { + assert(_state == StartMark || _state == StartUndo, "must be starting a cycle"); + _state = InProgress; +} + +bool G1ConcurrentMarkThread::idle() const { return _state == Idle; } + +bool G1ConcurrentMarkThread::started() const { + return _state == StartMark || _state == StartUndo; +} + +bool G1ConcurrentMarkThread::in_progress() const { + return _state == InProgress; +} + class CMRemark : public VoidClosure { G1ConcurrentMark* _cm; public: @@ -135,16 +161,25 @@ _vtime_start = os::elapsedVTime(); while (!should_terminate()) { - if (wait_for_next_cycle()) { + Command cmd = wait_for_next_cycle(); + if (cmd == Terminate) { break; } GCIdMark gc_id_mark; - GCTraceConcTime(Info, gc) tt("Concurrent Cycle"); + GCTraceConcTime(Info, gc) tt(FormatBuffer<128>("Concurrent %s Cycle", + cmd == MarkCycle ? "Mark" : "Undo")); concurrent_cycle_start(); - full_concurrent_cycle_do(); - concurrent_cycle_end(); + + if (cmd == MarkCycle) { + mark_concurrent_cycle_do(); + } else { + assert(cmd == UndoCycle, "Must be command to undo concurrent start but is %d", cmd); + undo_concurrent_cycle_do(); + } + + concurrent_cycle_end(cmd == MarkCycle && !_cm->has_aborted()); _vtime_accum = (os::elapsedVTime() - _vtime_start); } @@ -156,7 +191,7 @@ CGC_lock->notify_all(); } -bool G1ConcurrentMarkThread::wait_for_next_cycle() { +G1ConcurrentMarkThread::Command G1ConcurrentMarkThread::wait_for_next_cycle() { assert(!in_progress(), "should have been cleared"); MonitorLocker ml(CGC_lock, Mutex::_no_safepoint_check_flag); @@ -164,11 +199,23 @@ ml.wait(); } + Command result; + if (should_terminate()) { + result = Terminate; + } else if (_state == StartMark) { + result = MarkCycle; + } else if (_state == StartUndo) { + result = UndoCycle; + } else { + log_error(gc)("Invalid command for concurrent cycle"); + ShouldNotReachHere(); + } + if (started()) { set_in_progress(); } - return should_terminate(); + return result; } bool G1ConcurrentMarkThread::phase_clear_cld_claimed_marks() { @@ -238,7 +285,7 @@ _cm->concurrent_cycle_start(); } -void G1ConcurrentMarkThread::full_concurrent_cycle_do() { +void G1ConcurrentMarkThread::mark_concurrent_cycle_do() { HandleMark hm(Thread::current()); ResourceMark rm; @@ -294,14 +341,26 @@ phase_clear_bitmap_for_next_mark(); } -void G1ConcurrentMarkThread::concurrent_cycle_end() { +void G1ConcurrentMarkThread::undo_concurrent_cycle_do() { + HandleMark hm(Thread::current()); + ResourceMark rm; + + // We can (and should) abort if there has been a concurrent cycle abort for + // some reason. + if (_cm->has_aborted()) { return; } + + // Phase 1: Clear bitmap for next mark. + phase_clear_bitmap_for_next_mark(); +} + +void G1ConcurrentMarkThread::concurrent_cycle_end(bool mark_cycle_completed) { // Update the number of full collections that have been // completed. This will also notify the G1OldGCCount_lock in case a // Java thread is waiting for a full GC to happen (e.g., it // called System.gc() with +ExplicitGCInvokesConcurrent). SuspendibleThreadSetJoiner sts_join; G1CollectedHeap::heap()->increment_old_marking_cycles_completed(true /* concurrent */, - !_cm->has_aborted()); + mark_cycle_completed /* heap_examined */); _cm->concurrent_cycle_end(); ConcurrentGCBreakpoints::notify_active_to_idle();