On Mon, 28 Oct 2024 08:34:14 GMT, Alan Bateman <al...@openjdk.org> wrote:

> This is an update to the Virtual thread implementation that we'd like to 
> integrate in advance of JEP 491.
> 
> The update removes the use of  "temporary transitions", basically cases where 
> the thread identity switches to the carrier thread to do something in the 
> context of the carrier while a virtual thread is mounted. These cases create 
> complexity for JVMTI and observability tools. It has also attracted attention 
> in the review of the JEP 491 implementation as the object monitor changes 
> have to deal with the possibility of entering monitors while in this state. 
> There are 3 usages changes:
> 
> 1. In submitRunContinuation the submit to the scheduler is changed so that it 
> executes in the context of a virtual thread for cases where one virtual 
> thread unparks another. This requires pinning to prevent preemption during 
> this sensitive operation. ForkJoinPool.poolSubmit is changed so that it uses 
> the identity of the carrier. This change has no impact on the uses of 
> lazySubmit or externalSubmit.
> 2. Timed-park. The current implementation schedules/cancels the timer task 
> with the virtual thread mounted. This runs in the context of the carrier as 
> any contention would infer with thread state, park blocker and the parking 
> permit. The implementation is changed to schedule the timeout after 
> unmounting, and to cancel before re-mounting. The downside of this is that it 
> will scheduled later (maybe 200us later than before). We could capture the 
> time and adjust but it doesn't seem worth it.
> 3. jdk.tracePinnedThreads. This is a diagnostic option for finding usages of 
> thread locals in code executed by virtual threads. This is changed so use a 
> thread local to detect reentrancy.
> 
> The changes means that notifyJvmtiHideFrames, its intrinsic, and the JVMTI 
> "tmp VTMS_transition" bit go away.

Hotspot cleanup looks great! It is really good to see this temporary transition 
logic go away.

src/java.base/share/classes/java/lang/ThreadLocal.java line 813:

> 811: 
> 812:     /**
> 813:      * Print the print stack of the current thread, skipping the 
> printStackTrace frame.

Suggestion:

     * Print the stack of the current thread, skipping the printStackTrace 
frame.

src/java.base/share/classes/java/lang/VirtualThread.java line 537:

> 535:                 assert parkTimeout > 0;
> 536:                 timeoutTask = schedule(this::unpark, parkTimeout, 
> NANOSECONDS);
> 537:                 setState(newState = TIMED_PARKED);

Just to be clear here, if the timeout expires before we can call `setState`, 
the unpark is basically a no-op, and we will see that we have been unparked at 
line 541 and set the state correctly to UNPARKED.

test/jdk/java/lang/Thread/virtual/ParkWithFixedThreadPool.java line 93:

> 91:             } finally {
> 92:                 // ExecutorService::execute may consume parking permit
> 93:                 LockSupport.unpark(Thread.currentThread());

This seems a bit odd - why would the current thread need to unpark itself? Why 
should it have a park permit available here?

-------------

Marked as reviewed by dholmes (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/21735#pullrequestreview-2406915529
PR Review Comment: https://git.openjdk.org/jdk/pull/21735#discussion_r1823761637
PR Review Comment: https://git.openjdk.org/jdk/pull/21735#discussion_r1823766067
PR Review Comment: https://git.openjdk.org/jdk/pull/21735#discussion_r1823767061

Reply via email to