mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-09 18:08:31 +00:00
8264851: Shenandoah: Rework control loop mechanics to use timed waits
Reviewed-by: kdnilsen, shade
This commit is contained in:
parent
ac73e688b1
commit
92f2ab2e1b
@ -43,7 +43,8 @@
|
||||
ShenandoahControlThread::ShenandoahControlThread() :
|
||||
ShenandoahController(),
|
||||
_requested_gc_cause(GCCause::_no_gc),
|
||||
_degen_point(ShenandoahGC::_degenerated_outside_cycle) {
|
||||
_degen_point(ShenandoahGC::_degenerated_outside_cycle),
|
||||
_control_lock(Mutex::nosafepoint - 2, "ShenandoahGCRequest_lock", true) {
|
||||
set_name("Shenandoah Control Thread");
|
||||
create_and_start();
|
||||
}
|
||||
@ -228,7 +229,9 @@ void ShenandoahControlThread::run_service() {
|
||||
sleep = MIN2<int>(ShenandoahControlIntervalMax, MAX2(1, sleep * 2));
|
||||
last_sleep_adjust_time = current;
|
||||
}
|
||||
os::naked_short_sleep(sleep);
|
||||
|
||||
MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag);
|
||||
ml.wait(sleep);
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,6 +346,16 @@ void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
|
||||
}
|
||||
}
|
||||
|
||||
void ShenandoahControlThread::notify_control_thread(GCCause::Cause cause) {
|
||||
// Although setting gc request is under _controller_lock, the read side (run_service())
|
||||
// does not take the lock. We need to enforce following order, so that read side sees
|
||||
// latest requested gc cause when the flag is set.
|
||||
MonitorLocker controller(&_control_lock, Mutex::_no_safepoint_check_flag);
|
||||
_requested_gc_cause = cause;
|
||||
_gc_requested.set();
|
||||
controller.notify();
|
||||
}
|
||||
|
||||
void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
|
||||
if (should_terminate()) {
|
||||
log_info(gc)("Control thread is terminating, no more GCs");
|
||||
@ -354,8 +367,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
|
||||
// The whitebox caller thread will arrange for itself to wait until the GC notifies
|
||||
// it that has reached the requested breakpoint (phase in the GC).
|
||||
if (cause == GCCause::_wb_breakpoint) {
|
||||
_requested_gc_cause = cause;
|
||||
_gc_requested.set();
|
||||
notify_control_thread(cause);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -372,12 +384,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
|
||||
size_t current_gc_id = get_gc_id();
|
||||
size_t required_gc_id = current_gc_id + 1;
|
||||
while (current_gc_id < required_gc_id && !should_terminate()) {
|
||||
// Although setting gc request is under _gc_waiters_lock, but read side (run_service())
|
||||
// does not take the lock. We need to enforce following order, so that read side sees
|
||||
// latest requested gc cause when the flag is set.
|
||||
_requested_gc_cause = cause;
|
||||
_gc_requested.set();
|
||||
|
||||
notify_control_thread(cause);
|
||||
ml.wait();
|
||||
current_gc_id = get_gc_id();
|
||||
}
|
||||
|
||||
@ -45,6 +45,9 @@ private:
|
||||
GCCause::Cause _requested_gc_cause;
|
||||
ShenandoahGC::ShenandoahDegenPoint _degen_point;
|
||||
|
||||
// This lock is used to coordinate waking up the control thread
|
||||
Monitor _control_lock;
|
||||
|
||||
public:
|
||||
ShenandoahControlThread();
|
||||
|
||||
@ -54,6 +57,8 @@ public:
|
||||
void request_gc(GCCause::Cause cause) override;
|
||||
|
||||
private:
|
||||
// Sets the requested cause and flag and notifies the control thread
|
||||
void notify_control_thread(GCCause::Cause cause);
|
||||
|
||||
bool check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point);
|
||||
void service_concurrent_normal_cycle(GCCause::Cause cause);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user