4343ShenandoahControlThread::ShenandoahControlThread () :
4444 ShenandoahController(),
4545 _requested_gc_cause(GCCause::_no_gc),
46- _degen_point(ShenandoahGC::_degenerated_outside_cycle) {
46+ _degen_point(ShenandoahGC::_degenerated_outside_cycle),
47+ _control_lock(Mutex::nosafepoint - 2 , " ShenandoahGCRequest_lock" , true ) {
4748 set_name (" Shenandoah Control Thread" );
4849 create_and_start ();
4950}
@@ -228,7 +229,9 @@ void ShenandoahControlThread::run_service() {
228229 sleep = MIN2<int >(ShenandoahControlIntervalMax, MAX2 (1 , sleep * 2 ));
229230 last_sleep_adjust_time = current;
230231 }
231- os::naked_short_sleep (sleep);
232+
233+ MonitorLocker ml (&_control_lock, Mutex::_no_safepoint_check_flag);
234+ ml.wait (sleep);
232235 }
233236}
234237
@@ -343,6 +346,16 @@ void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
343346 }
344347}
345348
349+ void ShenandoahControlThread::notify_control_thread (GCCause::Cause cause) {
350+ // Although setting gc request is under _controller_lock, the read side (run_service())
351+ // does not take the lock. We need to enforce following order, so that read side sees
352+ // latest requested gc cause when the flag is set.
353+ MonitorLocker controller (&_control_lock, Mutex::_no_safepoint_check_flag);
354+ _requested_gc_cause = cause;
355+ _gc_requested.set ();
356+ controller.notify ();
357+ }
358+
346359void ShenandoahControlThread::handle_requested_gc (GCCause::Cause cause) {
347360 if (should_terminate ()) {
348361 log_info (gc)(" Control thread is terminating, no more GCs" );
@@ -354,8 +367,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
354367 // The whitebox caller thread will arrange for itself to wait until the GC notifies
355368 // it that has reached the requested breakpoint (phase in the GC).
356369 if (cause == GCCause::_wb_breakpoint) {
357- _requested_gc_cause = cause;
358- _gc_requested.set ();
370+ notify_control_thread (cause);
359371 return ;
360372 }
361373
@@ -372,12 +384,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
372384 size_t current_gc_id = get_gc_id ();
373385 size_t required_gc_id = current_gc_id + 1 ;
374386 while (current_gc_id < required_gc_id && !should_terminate ()) {
375- // Although setting gc request is under _gc_waiters_lock, but read side (run_service())
376- // does not take the lock. We need to enforce following order, so that read side sees
377- // latest requested gc cause when the flag is set.
378- _requested_gc_cause = cause;
379- _gc_requested.set ();
380-
387+ notify_control_thread (cause);
381388 ml.wait ();
382389 current_gc_id = get_gc_id ();
383390 }
0 commit comments