8293613: need to properly handle and hide tmp VTMS transitions

Reviewed-by: cjplummer, lmesnik
This commit is contained in:
Serguei Spitsyn 2022-09-28 04:44:43 +00:00
parent 5e1e449c11
commit 79ccc791f2
10 changed files with 145 additions and 68 deletions

View file

@ -354,6 +354,39 @@ final class VirtualThread extends BaseVirtualThread {
carrier.clearInterrupt();
}
/**
* Sets the current thread to the current carrier thread.
* @return true if JVMTI was notified
*/
@ChangesCurrentThread
@JvmtiMountTransition
private boolean switchToCarrierThread() {
boolean notifyJvmti = notifyJvmtiEvents;
if (notifyJvmti) {
notifyJvmtiHideFrames(true);
}
Thread carrier = this.carrierThread;
assert Thread.currentThread() == this
&& carrier == Thread.currentCarrierThread();
carrier.setCurrentThread(carrier);
return notifyJvmti;
}
/**
* Sets the current thread to the given virtual thread.
* If {@code notifyJvmti} is true then JVMTI is notified.
*/
@ChangesCurrentThread
@JvmtiMountTransition
private void switchToVirtualThread(VirtualThread vthread, boolean notifyJvmti) {
Thread carrier = vthread.carrierThread;
assert carrier == Thread.currentCarrierThread();
carrier.setCurrentThread(vthread);
if (notifyJvmti) {
notifyJvmtiHideFrames(false);
}
}
/**
* Unmounts this virtual thread, invokes Continuation.yield, and re-mounts the
* thread when continued. When enabled, JVMTI must be notified from this method.
@ -526,7 +559,7 @@ final class VirtualThread extends BaseVirtualThread {
long startTime = System.nanoTime();
boolean yielded;
Future<?> unparker = scheduleUnpark(nanos);
Future<?> unparker = scheduleUnpark(this::unpark, nanos);
setState(PARKING);
try {
yielded = yieldContinuation();
@ -579,17 +612,16 @@ final class VirtualThread extends BaseVirtualThread {
}
/**
* Schedules this thread to be unparked after the given delay.
* Schedule an unpark task to run after a given delay.
*/
@ChangesCurrentThread
private Future<?> scheduleUnpark(long nanos) {
Thread carrier = this.carrierThread;
// need to switch to current platform thread to avoid nested parking
carrier.setCurrentThread(carrier);
private Future<?> scheduleUnpark(Runnable unparker, long nanos) {
// need to switch to current carrier thread to avoid nested parking
boolean notifyJvmti = switchToCarrierThread();
try {
return UNPARKER.schedule(() -> unpark(), nanos, NANOSECONDS);
return UNPARKER.schedule(unparker, nanos, NANOSECONDS);
} finally {
carrier.setCurrentThread(this);
switchToVirtualThread(this, notifyJvmti);
}
}
@ -599,13 +631,12 @@ final class VirtualThread extends BaseVirtualThread {
@ChangesCurrentThread
private void cancel(Future<?> future) {
if (!future.isDone()) {
Thread carrier = this.carrierThread;
// need to switch to current platform thread to avoid nested parking
carrier.setCurrentThread(carrier);
// need to switch to current carrier thread to avoid nested parking
boolean notifyJvmti = switchToCarrierThread();
try {
future.cancel(false);
} finally {
carrier.setCurrentThread(this);
switchToVirtualThread(this, notifyJvmti);
}
}
}
@ -625,12 +656,11 @@ final class VirtualThread extends BaseVirtualThread {
int s = state();
if (s == PARKED && compareAndSetState(PARKED, RUNNABLE)) {
if (currentThread instanceof VirtualThread vthread) {
Thread carrier = vthread.carrierThread;
carrier.setCurrentThread(carrier);
boolean notifyJvmti = vthread.switchToCarrierThread();
try {
submitRunContinuation();
} finally {
carrier.setCurrentThread(vthread);
switchToVirtualThread(vthread, notifyJvmti);
}
} else {
submitRunContinuation();
@ -1005,6 +1035,9 @@ final class VirtualThread extends BaseVirtualThread {
@JvmtiMountTransition
private native void notifyJvmtiUnmountEnd(boolean lastUnmount);
@JvmtiMountTransition
private native void notifyJvmtiHideFrames(boolean hide);
private static native void registerNatives();
static {
registerNatives();