On Thu, 17 Oct 2024 14:28:30 GMT, Patricio Chilano Mateo 
<pchilanom...@openjdk.org> wrote:

> This is the implementation of JEP 491: Synchronize Virtual Threads without 
> Pinning. See [JEP 491](https://bugs.openjdk.org/browse/JDK-8337395) for 
> further details.
> 
> In order to make the code review easier the changes have been split into the 
> following initial 4 commits:
> 
> - Changes to allow unmounting a virtual thread that is currently holding 
> monitors.
> - Changes to allow unmounting a virtual thread blocked on synchronized trying 
> to acquire the monitor.
> - Changes to allow unmounting a virtual thread blocked in `Object.wait()` and 
> its timed-wait variants.
> - Changes to tests, JFR pinned event, and other changes in the JDK libraries.
> 
> The changes fix pinning issues for all 4 ports that currently implement 
> continuations: x64, aarch64, riscv and ppc. Note: ppc changes were added 
> recently and stand in its own commit after the initial ones.
> 
> The changes fix pinning issues when using `LM_LIGHTWEIGHT`, i.e. the default 
> locking mode, (and `LM_MONITOR` which comes for free), but not when using 
> `LM_LEGACY` mode. Note that the `LockingMode` flag has already been 
> deprecated ([JDK-8334299](https://bugs.openjdk.org/browse/JDK-8334299)), with 
> the intention to remove `LM_LEGACY` code in future releases.
> 
> 
> ## Summary of changes
> 
> ### Unmount virtual thread while holding monitors
> 
> As stated in the JEP, currently when a virtual thread enters a synchronized 
> method or block, the JVM records the virtual thread's carrier platform thread 
> as holding the monitor, not the virtual thread itself. This prevents the 
> virtual thread from being unmounted from its carrier, as ownership 
> information would otherwise go wrong. In order to fix this limitation we will 
> do two things:
> 
> - We copy the oops stored in the LockStack of the carrier to the stackChunk 
> when freezing (and clear the LockStack). We copy the oops back to the 
> LockStack of the next carrier when thawing for the first time (and clear them 
> from the stackChunk). Note that we currently assume carriers don't hold 
> monitors while mounting virtual threads.
> 
> - For inflated monitors we now record the `java.lang.Thread.tid` of the owner 
> in the ObjectMonitor's `_owner` field instead of a JavaThread*. This allows 
> us to tie the owner of the monitor to a `java.lang.Thread` instance, rather 
> than to a JavaThread which is only created per platform thread. The tid is 
> already a 64 bit field so we can ignore issues of the counter wrapping around.
> 
> #### General notes about this part:
> 
> - Since virtual threads don't need to worry about holding monitors anymo...

src/hotspot/cpu/x86/stubGenerator_x86_64.hpp line 602:

> 600: 
> 601:   address generate_cont_preempt_stub();
> 602:   address generate_cont_resume_monitor_operation();

The declaration of `generate_cont_resume_monitor_operation` seems to be unused.

src/hotspot/share/runtime/javaThread.hpp line 166:

> 164:   // current _vthread object, except during creation of the primordial 
> and JNI
> 165:   // attached thread cases where this field can have a temporary value.
> 166:   int64_t _lock_id;

Following the review I wanted to better understand when `_lock_id` changes. 
There seems to be another exception to the rule that `_lock_id` is equal to the 
`tid` of the current `_vthread`. I think they won't be equal when switching 
temporarily from the virtual to the carrier thread in 
`VirtualThread::switchToCarrierThread()`.

src/hotspot/share/runtime/objectMonitor.hpp line 202:

> 200: 
> 201:   // Used in LM_LEGACY mode to store BasicLock* in case of inflation by 
> contending thread.
> 202:   BasicLock* volatile _stack_locker;

IIUC the new field `_stack_locker` is needed because we cannot store the 
`BasicLock*` anymore in the `_owner` field as it could be interpreted as a 
thread id by mistake.
Wouldn't it be an option to have only odd thread ids? Then we could store the 
`BasicLock*` in the `_owner` field without loosing the information if it is a 
`BasicLock*` or a thread id. I think this would reduce complexity quite a bit, 
woudn't it?

src/hotspot/share/runtime/synchronizer.cpp line 1559:

> 1557:         // and set the stack locker field in the monitor.
> 1558:         m->set_stack_locker(mark.locker());
> 1559:         m->set_anonymous_owner();  // second

Is it important that this is done after the stack locker is set? I think I saw 
another comment that indicated that order is important but I cannot find it now.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/21565#discussion_r1818523530
PR Review Comment: https://git.openjdk.org/jdk/pull/21565#discussion_r1812377293
PR Review Comment: https://git.openjdk.org/jdk/pull/21565#discussion_r1819029029
PR Review Comment: https://git.openjdk.org/jdk/pull/21565#discussion_r1818521820

Reply via email to