Skip to content

Commit

Permalink
loom locking stuff
Browse files Browse the repository at this point in the history
Signed-off-by: Tobi Ajila <atobia@ca.ibm.com>
  • Loading branch information
tajila committed Feb 23, 2024
1 parent 441da50 commit 788449a
Show file tree
Hide file tree
Showing 5 changed files with 489 additions and 3 deletions.
1 change: 1 addition & 0 deletions make/data/hotspot-symbols/symbols-unix
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ JVM_VirtualThreadMount
JVM_VirtualThreadUnmount
JVM_VirtualThreadHideFrames
JVM_VirtualThreadDisableSuspend
JVM_VirtualThreadWaitForPendingList

# Scoped values
JVM_EnsureMaterializedForStackWalk_func
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/include/jvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,9 @@ JVM_VirtualThreadHideFrames(JNIEnv* env, jobject vthread, jboolean hide);
JNIEXPORT void JNICALL
JVM_VirtualThreadDisableSuspend(JNIEnv* env, jobject vthread, jboolean enter);

JNIEXPORT jobject JNICALL
JVM_VirtualThreadWaitForPendingList(JNIEnv* env);

/*
* Core reflection support.
*/
Expand Down
79 changes: 76 additions & 3 deletions src/java.base/share/classes/java/lang/VirtualThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ final class VirtualThread extends BaseVirtualThread {
private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit");
private static final long CARRIER_THREAD = U.objectFieldOffset(VirtualThread.class, "carrierThread");
private static final long TERMINATION = U.objectFieldOffset(VirtualThread.class, "termination");
private static final long ON_WAITING_LIST = U.objectFieldOffset(VirtualThread.class, "onWaitingList");

// scheduler and continuation
private final Executor scheduler;
Expand Down Expand Up @@ -132,6 +133,9 @@ final class VirtualThread extends BaseVirtualThread {
// Thread.yield
private static final int YIELDING = 10;
private static final int YIELDED = 11; // unmounted but runnable
// monitor enter
private static final int BLOCKING = 12;
private static final int BLOCKED = 13;

private static final int TERMINATED = 99; // final state

Expand All @@ -141,12 +145,20 @@ final class VirtualThread extends BaseVirtualThread {
// parking permit
private volatile boolean parkPermit;


// unblocked
private volatile boolean unblocked;

// carrier thread when mounted, accessed by VM
private volatile Thread carrierThread;

// termination object when joining, created lazily if needed
private volatile CountDownLatch termination;

// Next waiting vthread to unpark()
private VirtualThread next;
private byte onWaitingList;

/**
* Returns the continuation scope used for virtual threads.
*/
Expand Down Expand Up @@ -499,6 +511,16 @@ private void afterYield() {
return;
}

// blocking on monitorenter
if (s == BLOCKING) {
setState(BLOCKED);
if (unblocked && compareAndSetState(BLOCKED, UNPARKED)) {
unblocked = false;
submitRunContinuation();
}
return;
}

assert false;
}

Expand Down Expand Up @@ -772,6 +794,19 @@ void unpark() {
}
}

/**
* Re-enables this virtual thread for scheduling after blocking on monitor enter.
* @throws RejectedExecutionException if the scheduler cannot accept a task
*/
private void unblock() {
assert !Thread.currentThread().isVirtual();
unblocked = true;
if (state() == BLOCKED && compareAndSetState(BLOCKED, UNPARKED)) {
unblocked = false;
submitRunContinuation();
}
}

/**
* Attempts to yield the current virtual thread (Thread.yield).
*/
Expand Down Expand Up @@ -924,6 +959,7 @@ Thread.State threadState() {
}
case UNPARKED:
case YIELDED:
case BLOCKING:
// runnable, not mounted
return Thread.State.RUNNABLE;
case RUNNING:
Expand Down Expand Up @@ -952,6 +988,8 @@ Thread.State threadState() {
case TIMED_PARKED:
case TIMED_PINNED:
return State.TIMED_WAITING;
case BLOCKED:
return State.BLOCKED;
case TERMINATED:
return Thread.State.TERMINATED;
default:
Expand Down Expand Up @@ -997,7 +1035,7 @@ private StackTraceElement[] tryGetStackTrace() {
case RUNNING, PINNED, TIMED_PINNED -> {
return null; // mounted
}
case PARKED, TIMED_PARKED -> {
case PARKED, BLOCKED, TIMED_PARKED -> {
// unmounted, not runnable
}
case UNPARKED, YIELDED -> {
Expand Down Expand Up @@ -1028,9 +1066,9 @@ private StackTraceElement[] tryGetStackTrace() {
// resubmit as task may have run while suspended
yield true;
}
case PARKED, TIMED_PARKED -> {
case PARKED, BLOCKED, TIMED_PARKED -> {
// resubmit if unparked while suspended
yield parkPermit && compareAndSetState(initialState, UNPARKED);
yield (parkPermit || unblocked) && compareAndSetState(initialState, UNPARKED);
}
default -> throw new InternalError();
};
Expand Down Expand Up @@ -1119,6 +1157,16 @@ private void setState(int newValue) {
state = newValue; // volatile write
}

private VirtualThread next() {
return next;
}

private void removeFromWaitingList() {
next = null;
boolean res = U.compareAndSetByte(this, ON_WAITING_LIST, (byte)0x01, (byte)0x00);
assert res;
}

private boolean compareAndSetState(int expectedValue, int newValue) {
return U.compareAndSetInt(this, STATE, expectedValue, newValue);
}
Expand Down Expand Up @@ -1244,4 +1292,29 @@ private static int tracePinningMode() {
}
return 0;
}

/**
* Unblock virtual threads that are ready to scheduled again.
*/
private static void processPendingList() {
while (true) {
VirtualThread currentWaitingVThread = waitForPendingList();
VirtualThread nextWaitingVThread = null;
while (currentWaitingVThread != null) {
nextWaitingVThread = currentWaitingVThread.next();
currentWaitingVThread.removeFromWaitingList();
currentWaitingVThread.unpark();
currentWaitingVThread = nextWaitingVThread;
}
}
}

private static native VirtualThread waitForPendingList();

static {
var unblocker = InnocuousThread.newThread("VirtualThread-unblocker",
VirtualThread::processPendingList);
unblocker.setDaemon(true);
unblocker.start();
}
}
1 change: 1 addition & 0 deletions src/java.base/share/native/libjava/VirtualThread.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static JNINativeMethod methods[] = {
{ "notifyJvmtiUnmount", "(Z)V", (void *)&JVM_VirtualThreadUnmount },
{ "notifyJvmtiHideFrames", "(Z)V", (void *)&JVM_VirtualThreadHideFrames },
{ "notifyJvmtiDisableSuspend", "(Z)V", (void *)&JVM_VirtualThreadDisableSuspend },
{ "waitForPendingList", "()" VIRTUAL_THREAD, (void *)&JVM_VirtualThreadWaitForPendingList },
};

JNIEXPORT void JNICALL
Expand Down
Loading

0 comments on commit 788449a

Please sign in to comment.