29
29
import java .util .concurrent .locks .ReentrantLock ;
30
30
31
31
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
32
+ import com .oracle .truffle .api .TruffleLogger ;
32
33
import com .oracle .truffle .api .TruffleSafepoint ;
34
+ import com .oracle .truffle .api .TruffleSafepoint .Interruptible ;
33
35
import com .oracle .truffle .api .nodes .Node ;
36
+ import com .oracle .truffle .espresso .EspressoLanguage ;
34
37
import com .oracle .truffle .espresso .impl .SuppressFBWarnings ;
35
38
import com .oracle .truffle .espresso .meta .Meta ;
39
+ import com .oracle .truffle .espresso .runtime .EspressoContext ;
36
40
import com .oracle .truffle .espresso .runtime .staticobject .StaticObject ;
37
41
38
42
/**
@@ -264,6 +268,7 @@ default boolean await(long timeout, TimeUnit unit) throws GuestInterruptedExcept
264
268
*/
265
269
@ SuppressWarnings ("serial" )
266
270
final class EspressoLockImpl extends ReentrantLock implements EspressoLock {
271
+ private static final TruffleLogger LOGGER = TruffleLogger .getLogger (EspressoLanguage .ID , EspressoLock .class );
267
272
268
273
private static final Node dummy = new Node () {
269
274
@ Override
@@ -322,7 +327,7 @@ public void lockInterruptible() throws GuestInterruptedException {
322
327
// fast-path before involving safepoint support
323
328
return ;
324
329
}
325
- blockingSupport .enterBlockingRegion (EspressoLockImpl :: doLock , dummy , this );
330
+ blockingSupport .enterBlockingRegion (Locker . LOCKER , dummy , this );
326
331
}
327
332
328
333
@ Override
@@ -413,7 +418,7 @@ private void doLock() throws InterruptedException {
413
418
}
414
419
415
420
@ SuppressFBWarnings (value = "UL_UNRELEASED_LOCK" , justification = "this lock is released at the start of the method and re-acquired at the end" )
416
- private void enterWaitInterruptible (InterruptibleWithBooleanResult < EspressoLockImpl > interruptible ) throws GuestInterruptedException {
421
+ private void enterWaitInterruptible (InterruptibleWithBooleanResult interruptible ) throws GuestInterruptedException {
417
422
ensureWaitLockInitialized ();
418
423
boolean enableManagement ;
419
424
Meta meta ;
@@ -448,19 +453,26 @@ private void enterWaitInterruptible(InterruptibleWithBooleanResult<EspressoLockI
448
453
* Signaled exception is thrown.
449
454
*/
450
455
this ::afterSafepointForWait );
456
+ if (consumeSignal ()) {
457
+ throw new Signaled (null );
458
+ }
459
+ interruptible .timedOut (); // Or spurious wake up.
451
460
} catch (Signaled e ) {
461
+ interruptible .signaled ();
452
462
e .maybeRethrow ();
453
463
} catch (Throwable e ) {
454
464
/*
455
465
* Either GuestInterruptedException or an exception thrown by a safepoint. Since at that
456
466
* point, we are still considered in waiting, we may have missed a signal.
457
467
*/
468
+ interruptible .interrupted ();
458
469
consumeSignal ();
459
470
throw e ;
460
471
} finally {
461
472
if (enableManagement ) {
462
473
meta .HIDDEN_THREAD_WAITING_MONITOR .setHiddenObject (interruptible .thread , StaticObject .NULL );
463
474
}
475
+ waiters --;
464
476
waitLock .unlock ();
465
477
// We need to ensure that we re-acquire the lock (even if the guest is getting
466
478
// interrupted)
@@ -481,7 +493,11 @@ private void enterWaitInterruptible(InterruptibleWithBooleanResult<EspressoLockI
481
493
for (int i = 1 ; i < holdCount ; i ++) {
482
494
lock ();
483
495
}
484
- waiters --;
496
+ LOGGER .fine (() -> {
497
+ EspressoContext ctx = EspressoContext .get (null );
498
+ String tName = ctx .getMeta ().toHostString (ctx .getMeta ().java_lang_Thread_name .getObject (ctx .getCurrentPlatformThread ()));
499
+ return "Wait for thread \" " + tName + "\" finished because it was " + interruptible .reason ();
500
+ });
485
501
}
486
502
}
487
503
@@ -530,10 +546,27 @@ public Throwable fillInStackTrace() {
530
546
}
531
547
}
532
548
533
- private abstract static class InterruptibleWithBooleanResult <T > implements TruffleSafepoint .Interruptible <T > {
549
+ private static final class Locker implements Interruptible <EspressoLockImpl > {
550
+ static final Interruptible <EspressoLockImpl > LOCKER = new Locker ();
551
+
552
+ private Locker () {
553
+ }
554
+
555
+ @ Override
556
+ public void apply (EspressoLockImpl lock ) throws InterruptedException {
557
+ lock .doLock ();
558
+ }
559
+ }
560
+
561
+ private abstract static class InterruptibleWithBooleanResult implements Interruptible <EspressoLockImpl > {
562
+ private static final byte SIGNALED = 0x1 ;
563
+ private static final byte INTERRUPTED = 0x2 ;
564
+ private static final byte TIMED_OUT = 0x4 ;
565
+
534
566
private final StaticObject thread ;
535
567
private final StaticObject obj ;
536
568
private boolean result ;
569
+ private byte status = 0 ;
537
570
538
571
InterruptibleWithBooleanResult (StaticObject thread , StaticObject obj ) {
539
572
this .thread = thread ;
@@ -547,9 +580,37 @@ public final boolean getResult() {
547
580
public final void setResult (boolean result ) {
548
581
this .result = result ;
549
582
}
583
+
584
+ public void signaled () {
585
+ assert status == 0 ;
586
+ status = SIGNALED ;
587
+ }
588
+
589
+ public void interrupted () {
590
+ assert status == 0 ;
591
+ status = INTERRUPTED ;
592
+ }
593
+
594
+ public void timedOut () {
595
+ assert status == 0 ;
596
+ status = TIMED_OUT ;
597
+ }
598
+
599
+ public String reason () {
600
+ switch (status ) {
601
+ case SIGNALED :
602
+ return "SIGNALED" ;
603
+ case INTERRUPTED :
604
+ return "INTERRUPTED" ;
605
+ case TIMED_OUT :
606
+ return "COMPLETED" ;
607
+ default :
608
+ return "NONE" ;
609
+ }
610
+ }
550
611
}
551
612
552
- private static final class WaitInterruptible extends InterruptibleWithBooleanResult < EspressoLockImpl > {
613
+ private static final class WaitInterruptible extends InterruptibleWithBooleanResult {
553
614
WaitInterruptible (long timeout , TimeUnit unit , StaticObject thread , StaticObject obj ) {
554
615
super (thread , obj );
555
616
this .nanoTimeout = unit .toNanos (timeout );
@@ -575,9 +636,10 @@ public void apply(EspressoLockImpl lock) throws InterruptedException {
575
636
setResult (lock .waitCondition .await (left , TimeUnit .NANOSECONDS ));
576
637
}
577
638
}
639
+
578
640
}
579
641
580
- private static final class WaitUntilInterruptible extends InterruptibleWithBooleanResult < EspressoLockImpl > {
642
+ private static final class WaitUntilInterruptible extends InterruptibleWithBooleanResult {
581
643
WaitUntilInterruptible (Date date ) {
582
644
super (null , null );
583
645
this .date = date ;
@@ -593,5 +655,6 @@ public void apply(EspressoLockImpl lock) throws InterruptedException {
593
655
// `enterWaitInterruptible`.
594
656
setResult (lock .waitCondition .awaitUntil (date ));
595
657
}
658
+
596
659
}
597
660
}
0 commit comments