28
28
#include " gc/shenandoah/shenandoahHeap.inline.hpp"
29
29
#include " gc/shenandoah/shenandoahPacer.hpp"
30
30
#include " runtime/atomic.hpp"
31
+ #include " runtime/mutexLocker.hpp"
31
32
32
33
/*
33
34
* In normal concurrent cycle, we have to pace the application to let GC finish.
@@ -239,7 +240,7 @@ void ShenandoahPacer::pace_for_alloc(size_t words) {
239
240
}
240
241
241
242
// Threads that are attaching should not block at all: they are not
242
- // fully initialized yet. Calling sleep() on them would be awkward.
243
+ // fully initialized yet. Blocking them would be awkward.
243
244
// This is probably the path that allocates the thread oop itself.
244
245
// Forcefully claim without waiting.
245
246
if (JavaThread::current ()->is_attaching_via_jni ()) {
@@ -264,7 +265,7 @@ void ShenandoahPacer::pace_for_alloc(size_t words) {
264
265
}
265
266
cur = MAX2<size_t >(1 , cur);
266
267
267
- JavaThread::current ()-> sleep (cur);
268
+ wait (cur);
268
269
269
270
double end = os::elapsedTime ();
270
271
total = (size_t )((end - start) * 1000 );
@@ -289,6 +290,19 @@ void ShenandoahPacer::pace_for_alloc(size_t words) {
289
290
}
290
291
}
291
292
293
+ void ShenandoahPacer::wait (long time_ms) {
294
+ // Perform timed wait. It works like like sleep(), except without modifying
295
+ // the thread interruptible status. MonitorLocker also checks for safepoints.
296
+ assert (time_ms > 0 , " Should not call this with zero argument, as it would stall until notify" );
297
+ MonitorLocker locker (_wait_monitor);
298
+ _wait_monitor->wait (time_ms);
299
+ }
300
+
301
+ void ShenandoahPacer::notify_waiters () {
302
+ MonitorLocker locker (_wait_monitor);
303
+ _wait_monitor->notify_all ();
304
+ }
305
+
292
306
void ShenandoahPacer::print_on (outputStream* out) const {
293
307
out->print_cr (" ALLOCATION PACING:" );
294
308
out->cr ();
0 commit comments