Skip to content

Commit fdf09e0

Browse files
committed
[GR-38039] [GR-64734] [GR-65060] Stricter thread status in Espresso.
PullRequest: graal/20833
2 parents 333b1d0 + 6c1400a commit fdf09e0

34 files changed

+1027
-308
lines changed

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/blocking/BlockingSupport.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ private BlockingSupport(GuestInterrupter<T> guestInterrupter) {
6565
private final GuestInterrupter<T> guestInterrupter;
6666

6767
/**
68-
* Creates an instance of this interface, using the given {@link Interrupter guestInterrupter}
69-
* parameter as how guest interruptions are made observable.
68+
* Creates an instance of this interface, using the given {@link GuestInterrupter
69+
* guestInterrupter} parameter as how guest interruptions are made observable.
7070
* <p>
7171
* This implementation can be as simple as setting a boolean in the guest's representation of
7272
* the thread.
@@ -93,7 +93,7 @@ public static <T> BlockingSupport<T> create(GuestInterrupter<T> guestInterrupter
9393
*
9494
* As such, there are only three ways to retrieve control from a call to this method:
9595
* <ul>
96-
* <li>The given {@linkplain Interruptible blockingRegion} naturally completes</li>
96+
* <li>The given {@link Interruptible blockingRegion} naturally completes</li>
9797
* <li>{@link #guestInterrupt(Thread, Object)} is called for this thread.</li>
9898
* <li>An {@link ThreadLocalAction action} was submitted to this thread, that throws an
9999
* exception that is not an {@link InterruptedException}.</li>

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/blocking/EspressoLock.java

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@
2929
import java.util.concurrent.locks.ReentrantLock;
3030

3131
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
32+
import com.oracle.truffle.api.TruffleLogger;
3233
import com.oracle.truffle.api.TruffleSafepoint;
34+
import com.oracle.truffle.api.TruffleSafepoint.Interruptible;
3335
import com.oracle.truffle.api.nodes.Node;
36+
import com.oracle.truffle.espresso.EspressoLanguage;
3437
import com.oracle.truffle.espresso.impl.SuppressFBWarnings;
3538
import com.oracle.truffle.espresso.meta.Meta;
39+
import com.oracle.truffle.espresso.runtime.EspressoContext;
3640
import 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")
266270
final 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

Comments
 (0)