-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning #21565
Conversation
👋 Welcome back pchilanomate! A progress list of the required criteria for merging this PR into |
@pchilano This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 12 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
@pchilano The following labels will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command. |
/contributor add @pchilano |
@pchilano |
@pchilano |
@pchilano |
@pchilano |
@pchilano |
/label remove security |
@pchilano |
/contributor add @reinrich |
@pchilano |
I merged with master, including the changes for JEP 450, and run it through tiers1-8 in mach5 with no related failures. I would like to integrate tomorrow if I could get some re-approvals. Also, I filed JDK-8343957 to possibly improve the naming of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still good. Thanks
Many thanks to all reviewers and contributors of this JEP! |
/integrate |
Going to push as commit 78b8015.
Your commit was automatically rebased without conflicts. |
…ds without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…ds without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…ds without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
…without Pinning Fixes: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Fixes: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Follow-up: 78b8015 ("8338383: Implement JEP 491: Synchronize Virtual Threads without Pinning") Follow-up: c113f82 ("8343957: Rename ObjectMonitor::owner_from() and JavaThread::_lock_id") Link: openjdk#21565 Link: openjdk#22524 Signed-off-by: Bingwu Zhang <xtex@aosc.io>
This is the implementation of JEP 491: Synchronize Virtual Threads without Pinning. See JEP 491 for further details.
In order to make the code review easier the changes have been split into the following initial 4 commits:
Object.wait()
and its timed-wait variants.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, (andLM_MONITOR
which comes for free), but not when usingLM_LEGACY
mode. Note that theLockingMode
flag has already been deprecated (JDK-8334299), with the intention to removeLM_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 ajava.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:
LM_LEGACY
. So the majority of the platform dependent changes in this commit have to do with correcting this.LM_LEGACY
.LOOM_MONITOR_SUPPORT
was added at the time to exclude ports that implement continuations but don't yet implement monitor support. It is removed later with the ppc commit changes.GetOwnedMonitorInfo
andGetOwnedMonitorStackDepthInfo
had to be adapted.Notes specific to the tid changes:
_lock_id
. It is set on JavaThread creation and changed on mount/unmount._owner
and_succ
fromvoid*
andJavaThread*
respectively toint64_t
.LM_LEGACY
the tid changes apply to it as well since the inflated path is shared. Thus, in case of inflation by a contending thread, theBasicLock*
cannot be stored in the_owner
field as before. The_owner
is instead set to anonymous as we do inLM_LIGHTWEIGHT
, and theBasicLock*
is stored in the new field_stack_locker
.cmpxchg
(JDK-8318776) so the shared code can stay the same. The assembly code for the c2 fast paths has to be adapted though. On arm (32bits) we already jump directly to the slow path on inflated monitor case so there is nothing to do. For x86 (32bits), since the port is moving towards deprecation (JDK-8338285) there is no point in trying to optimize, so the code was changed to do the same thing we do for arm (32bits).Unmounting a virtual thread blocked on synchronized
Currently virtual thread unmounting is always started from Java, either because of a voluntarily call to
Thread.yield()
or because of performing some blocking operation such as I/O. Now we allow to unmount from inside the VM too, specifically when facing contention trying to acquire a Java monitor.On failure to acquire a monitor inside
ObjectMonitor::enter
a virtual thread will call freeze to copy all Java frames to the heap. We will add the virtual thread to the ObjectMonitor's queue and return back to Java. Instead of continue execution in Java though, the virtual thread will jump to a preempt stub which will clear the frames copied from the physical stack, and will return toContinuation.run()
to proceed with the unmount logic. Once the owner releases the monitor and selects it as the next successor the virtual thread will be added again to the scheduler queue to run again. The virtual thread will run and attempt to acquire the monitor again. If it succeeds then it will thaw frames as usual to continue execution back were it left off. If it fails it will unmount and wait again to be unblocked.General notes about this part:
jni_enter()
orObjectLocker
since we would need to freeze native frames._cxq
the virtual thread could have successfully acquired the monitor. In that case we mark the preemption as cancelled. The virtual thread will still need to go back to the preempt stub to cleanup the physical stack but instead of unmounting it will call thaw to continue execution.call_VM_preemptable()
.Notes specific to JVMTI changes:
VirtualThread.yieldContinuation()
. This means that we have to execute the equivalent ofnotifyJvmtiUnmount(/*hide*/true)
for unmount, and ofnotifyJvmtiMount(/*hide*/false)
for mount in the VM. The former is implemented withJvmtiUnmountBeginMark
inContinuation::try_preempt()
. The latter is implemented in methodjvmti_mount_end()
inContinuationFreezeThaw
at the end of thaw.VirtualThread.yieldContinuation()
. When unmounting from the VM we only post the event once we know the freeze succeeded. Since at that point we are in the middle of the VTMS transition, posting the event is done inJvmtiVTMSTransitionDisabler::VTMS_unmount_end()
after the transition finishes. Maybe the same thing should be done when unmounting from Java.Unmounting a virtual thread blocked on
Object.wait()
This commit just extends the previous mechanism to be able to unmount inside the VM on
ObjectMonitor::wait
.General notes about this part:
_thread_in_Java
.Note specific to JVMTI changes:
Test changes + JFR Updates + Library code changes
Tests
java/lang/Thread/virtual
are updated to add more tests for monitor enter/exit and Object.wait/notify. New tests are added for JFR events, synchronized native methods, and stress testing for several scenarios.test/hotspot/gtest/nmt/test_vmatree.cpp
is changed due to an alias that conflicts.test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java
andtest/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002
, are updated so they are in sync with the JDK code.Diagnosing remaining pinning issues
jdk.tracePinnedThreads
is removed.jdk.VirtualThreadPinned
event is changed so that it's now recorded in the VM, and for the following cases: parking when pinned, blocking in monitor enter when pinned, Object.wait when pinned, and waiting for a class to be initialized by another thread. The changes to object monitors should mean that only a few events are recorded. Future work may change this to a sampling approach.Other changes to VirtualThread class
The VirtualThread implementation includes a few robustness changes. The
park/parkNanos
methods now park on the carrier if the freeze throws OOME. Moreover, the use of transitions is reduced so that the call out to the scheduler no longer requires a temporary transition.Other changes to libraries:
ReferenceQueue
is reverted to usesynchronized
, the subclass based onReentrantLock
is removed. This change is done now because the changes for object monitors impact this area when there is preemption polling a reference queue.java.io
is reverted to usesynchronized
. This change has been important for testing virtual threads. There will be follow-up cleanup in main-line after the JEP is integrated to removeInternalLock
and its uses injava.io
.sun.security.ssl.X509TrustManagerImpl
is changed to eagerly initialize AnchorCertificates, a forced change due to deadlocks in this code when testing.Testing
The changes have been running in the Loom pipeline for several months now. They have also been included in EA builds throughout the year at different stages (EA builds from earlier this year did not had Object.wait() support yet but more recent ones did) so there has been some external exposure too.
The current patch has been run through mach5 tiers 1-8. I'll keep running tests periodically until integration time.
Progress
Issues
Reviewers
Contributors
<pchilanomate@openjdk.org>
<alanb@openjdk.org>
<aph@openjdk.org>
<fyang@openjdk.org>
<coleenp@openjdk.org>
<rrich@openjdk.org>
<mdoerr@openjdk.org>
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/21565/head:pull/21565
$ git checkout pull/21565
Update a local copy of the PR:
$ git checkout pull/21565
$ git pull https://git.openjdk.org/jdk.git pull/21565/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 21565
View PR using the GUI difftool:
$ git pr show -t 21565
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/21565.diff
Using Webrev
Link to Webrev Comment