2929import java .util .concurrent .locks .ReentrantLock ;
3030
3131import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
32+ import com .oracle .truffle .api .TruffleLogger ;
3233import com .oracle .truffle .api .TruffleSafepoint ;
34+ import com .oracle .truffle .api .TruffleSafepoint .Interruptible ;
3335import com .oracle .truffle .api .nodes .Node ;
36+ import com .oracle .truffle .espresso .EspressoLanguage ;
3437import com .oracle .truffle .espresso .impl .SuppressFBWarnings ;
3538import com .oracle .truffle .espresso .meta .Meta ;
39+ import com .oracle .truffle .espresso .runtime .EspressoContext ;
3640import com .oracle .truffle .espresso .runtime .staticobject .StaticObject ;
3741
3842/**
@@ -264,6 +268,7 @@ default boolean await(long timeout, TimeUnit unit) throws GuestInterruptedExcept
264268 */
265269@ SuppressWarnings ("serial" )
266270final class EspressoLockImpl extends ReentrantLock implements EspressoLock {
271+ private static final TruffleLogger LOGGER = TruffleLogger .getLogger (EspressoLanguage .ID , EspressoLock .class );
267272
268273 private static final Node dummy = new Node () {
269274 @ Override
@@ -322,7 +327,7 @@ public void lockInterruptible() throws GuestInterruptedException {
322327 // fast-path before involving safepoint support
323328 return ;
324329 }
325- blockingSupport .enterBlockingRegion (EspressoLockImpl :: doLock , dummy , this );
330+ blockingSupport .enterBlockingRegion (Locker . LOCKER , dummy , this );
326331 }
327332
328333 @ Override
@@ -413,7 +418,7 @@ private void doLock() throws InterruptedException {
413418 }
414419
415420 @ 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 {
417422 ensureWaitLockInitialized ();
418423 boolean enableManagement ;
419424 Meta meta ;
@@ -448,19 +453,26 @@ private void enterWaitInterruptible(InterruptibleWithBooleanResult<EspressoLockI
448453 * Signaled exception is thrown.
449454 */
450455 this ::afterSafepointForWait );
456+ if (consumeSignal ()) {
457+ throw new Signaled (null );
458+ }
459+ interruptible .timedOut (); // Or spurious wake up.
451460 } catch (Signaled e ) {
461+ interruptible .signaled ();
452462 e .maybeRethrow ();
453463 } catch (Throwable e ) {
454464 /*
455465 * Either GuestInterruptedException or an exception thrown by a safepoint. Since at that
456466 * point, we are still considered in waiting, we may have missed a signal.
457467 */
468+ interruptible .interrupted ();
458469 consumeSignal ();
459470 throw e ;
460471 } finally {
461472 if (enableManagement ) {
462473 meta .HIDDEN_THREAD_WAITING_MONITOR .setHiddenObject (interruptible .thread , StaticObject .NULL );
463474 }
475+ waiters --;
464476 waitLock .unlock ();
465477 // We need to ensure that we re-acquire the lock (even if the guest is getting
466478 // interrupted)
@@ -481,7 +493,11 @@ private void enterWaitInterruptible(InterruptibleWithBooleanResult<EspressoLockI
481493 for (int i = 1 ; i < holdCount ; i ++) {
482494 lock ();
483495 }
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+ });
485501 }
486502 }
487503
@@ -530,10 +546,27 @@ public Throwable fillInStackTrace() {
530546 }
531547 }
532548
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+
534566 private final StaticObject thread ;
535567 private final StaticObject obj ;
536568 private boolean result ;
569+ private byte status = 0 ;
537570
538571 InterruptibleWithBooleanResult (StaticObject thread , StaticObject obj ) {
539572 this .thread = thread ;
@@ -547,9 +580,37 @@ public final boolean getResult() {
547580 public final void setResult (boolean result ) {
548581 this .result = result ;
549582 }
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+ }
550611 }
551612
552- private static final class WaitInterruptible extends InterruptibleWithBooleanResult < EspressoLockImpl > {
613+ private static final class WaitInterruptible extends InterruptibleWithBooleanResult {
553614 WaitInterruptible (long timeout , TimeUnit unit , StaticObject thread , StaticObject obj ) {
554615 super (thread , obj );
555616 this .nanoTimeout = unit .toNanos (timeout );
@@ -575,9 +636,10 @@ public void apply(EspressoLockImpl lock) throws InterruptedException {
575636 setResult (lock .waitCondition .await (left , TimeUnit .NANOSECONDS ));
576637 }
577638 }
639+
578640 }
579641
580- private static final class WaitUntilInterruptible extends InterruptibleWithBooleanResult < EspressoLockImpl > {
642+ private static final class WaitUntilInterruptible extends InterruptibleWithBooleanResult {
581643 WaitUntilInterruptible (Date date ) {
582644 super (null , null );
583645 this .date = date ;
@@ -593,5 +655,6 @@ public void apply(EspressoLockImpl lock) throws InterruptedException {
593655 // `enterWaitInterruptible`.
594656 setResult (lock .waitCondition .awaitUntil (date ));
595657 }
658+
596659 }
597660}
0 commit comments