-
Notifications
You must be signed in to change notification settings - Fork 723
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
Fix to handle suspend/resume of virtual/carrier threads #16943
Fix to handle suspend/resume of virtual/carrier threads #16943
Conversation
2362f58
to
ca18ba7
Compare
@dipak-bagadiya After verifying that sanity.openjdk and extended.openjdk pass, please change PR's state to "Ready for review". |
cb0afcb
to
cdb97e6
Compare
@babsingh I made some changes to the code and ran the build. I'll check the results for sanity. openjdk and extended openjdk, once passed, will modify PR. |
cdb97e6
to
63b7237
Compare
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.
Two key points:
- Code changes should not break older JDK versions; and
- Avoid redundant code via sharing.
Also, please review the commit message in MS Word to fix typos, sentence structure and grammar issues. |
63b7237
to
22d11a7
Compare
@dipak-bagadiya The revised suspend, resume and get thread state logic is posted in #16689 (comment). |
1a19b45
to
57ec6f7
Compare
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.
- Please review the logic thoroughly for functional correctness.
- Some of the previous feedback was unaddressed.
- The commit message and PR description need to reflect the new design.
57ec6f7
to
c204919
Compare
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.
- There are still issues in the logic which will cause functional failures.
- Typo in the first word of the PR description and commit message:
VMTI
->JVMTI
.
c204919
to
b74a222
Compare
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.
- Do the JVMTI tests in extended.openjdk pass for JDK19?
- Also, test compilation with JDK17.
7a5b7b7
to
36b28c2
Compare
5ab4901
to
e8e22fc
Compare
jenkins build sanity,extended.openjdk zlinux,win jdk19,jdk20 |
jenkins test sanity,extended.openjdk zlinux,win jdk19,jdk20 |
jenkins test sanity win jdk8 |
Failures from the below issues are seen in the PR builds:
Further investigation is required for the below failure. The below failure happens in JDK19 and not in JDK20.
Below are failures that look like the known ones, but I did not find any open issues for the same reason, and they seem unrelated to the changes in this PR.
|
JVMTI treats a virtual thread and its carrier thread as two separate threads. If JVMTI suspends a virtual thread, then its carrier thread should not be suspended and vice-versa. Similarly, if JVMTI resumes a virtual thread, then its carrier thread should not be resumed and vice-versa. In OpenJ9, currently, a mounted virtual thread and its carrier thread shared the same J9VMThread. The thread state is derived from the J9VMThread. Due to the sharing of the J9VMThread in the mounted state,if a mounted virtual thread is suspended, then the JVMTI functions will also reflect that its carrier thread is suspended. Currently, "isSuspendedByJVMTI" is the hidden field that holds the suspend status for the virtual thread only, now it made available for carrier thread too, i.e. the scope has changed from "java/lang/VirtualThread" to "java/lang/Thread" threads Also, it is renamed to "isSuspendedInternal" as this hidden field is not just specific to JVMTI. The following functions has changed to set/reset and verify "isSuspendedInternal" status for threads:- 1) SUSPEND THREAD:- suspendhelper.cpp:suspendThread: jvmtiThread.c:jvmtiSuspendResumeCallBack thread.cpp:Java_java_lang_Thread_suspendImpl ->In case of suspend the halt flag (J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND) is set if the thread is mounted, i.e. threadObject == targetThread->threadObject in J9VMThread's publicFlags also the hidden field "isSuspendedInternal" set to a non-zero value for the thread instance in all cases regardless of thread being mounted or unmounted. ->If any of the public flags are already set, then the relevant failure message is assigned. 2) RESUME THREAD:- jvmtiThread.c:resumeThread: jvmtiThread.c:jvmtiSuspendResumeCallBack thread.cpp:Java_java_lang_Thread_resumeImpl ->In case of resume the halt flag (J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND) is cleared if the thread is mounted, i.e. threadObject == targetThread->threadObject in J9VMThread's publicFlags also the hidden field "isSuspendedInternal" set to a zero value for the thread instance in all cases regardless of thread being mounted or unmounted. ->If any of the public flags are already set, then the relevant failure message is assigned. 3) GETSTATE:- jvmtiHelpers.c:getThreadState jvmtiHelpers.c:getVirtualThreadState ->The getThreadState function is changed in such a way that will verify the "isSuspendedInternal" filed to check the thread is suspend or not. The basic concept behind the new changes: [mounted + unmounted] set the "isSuspendedInternal" field [mounted] the halt flag is only modified if the thread object is stored in targetThread->threadObject [unmounted] Delay setting the halt flag until the thread mount. Related: eclipse-openj9#16689 Signed-off-by: Dipak Bagadiya [email protected]
e8e22fc
to
5a37cb1
Compare
jenkins test sanity alinux64 jdk20 |
jenkins compile win jdk8 |
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.
Overall, the code changes LGTM. re #16943 (comment): In the earlier PR builds, mostly known failures are seen. The VM-Access assertion is seen on JDK19 and not on JDK20; this is because JDK19 is out-of-service and has become stale.
Test had been fixed by eclipse-openj9/openj9#16943 Signed-off-by: Dipak Bagadiya [email protected]
Test has been fixed by eclipse-openj9/openj9#16943. Signed-off-by: Dipak Bagadiya [email protected]
Test has been fixed by eclipse-openj9/openj9#16943. Signed-off-by: Dipak Bagadiya [email protected] Signed-off-by: Dipak Bagadiya [email protected]
while (J9_ARE_ALL_BITS_SET(targetThread->publicFlags, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND | J9_PUBLIC_FLAGS_VM_ACCESS)) { | ||
omrthread_monitor_wait(targetThread->publicFlagsMutex); | ||
vmFuncs->setHaltFlag(targetThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND); | ||
} else { |
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.
During the review, I was looking at the code with white-space hidden. So, I missed that the else
block is indented incorrectly. It needs to include the monitor exit and goto calls.
@dipak-bagadiya This might be the potential fix for the assertion seen in #17334.
fyi @pshipton, we will thoroughly test the code before merging again.
Revised code:
...
#if JAVA_SPEC_VERSION >= 19
J9OBJECT_U32_STORE(currentThread, receiverObject, vm->isSuspendedInternalOffset, 1);
if (receiverObject == targetThread->threadObject)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
if (currentThread == targetThread) {
vmFuncs->setHaltFlag(targetThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND);
} else {
vmFuncs->internalExitVMToJNI(currentThread);
omrthread_monitor_enter(targetThread->publicFlagsMutex);
VM_VMAccess::setHaltFlagForVMAccessRelease(targetThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND);
if (VM_VMAccess::mustWaitForVMAccessRelease(targetThread)) {
while (J9_ARE_ALL_BITS_SET(targetThread->publicFlags, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND | J9_PUBLIC_FLAGS_VM_ACCESS)) {
omrthread_monitor_wait(targetThread->publicFlagsMutex);
}
}
omrthread_monitor_exit(targetThread->publicFlagsMutex);
goto vmAccessReleased;
}
}
...
JVMTI treats a virtual thread and its carrier thread as two separate threads.
If JVMTI suspends a virtual thread, then its carrier thread
should not be suspended and vice-versa. Similarly, if JVMTI resumes
a virtual thread, then its carrier thread should not be resumed and
vice-versa.
In OpenJ9, currently, a mounted virtual thread and its carrier thread
shared the same J9VMThread. The thread state is derived from the
J9VMThread. Due to the sharing of the J9VMThread in the mounted
state, if a mounted virtual thread is suspended, then the JVMTI
functions will also reflect that its carrier thread is suspended.
Currently, "isSuspendedByJVMTI" is the hidden field that holds
the suspend status for the virtual thread only, now it made
available for carrier thread too, i.e., the scope has changed
from "java/lang/VirtualThread" to "java/lang/Thread" threads
Also, it is renamed to "isSuspendedInternal" as this hidden field is
not just specific to JVMTI.
The following functions has changed to set/reset and verify
"isSuspendedInternal" status and halt flag for threads: -
1) SUSPEND THREAD:-
suspendhelper.cpp:suspendThread:
jvmtiThread.c:jvmtiSuspendResumeCallBack
thread.cpp:Java_java_lang_Thread_suspendImpl
->In case of suspend the halt flag
(J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND) is set if the thread is
mounted, i.e., threadObject == targetThread->threadObject in
J9VMThread's publicFlags also the hidden field "isSuspendedInternal"
set to a non-zero value for the thread instance in all cases
regardless of thread being mounted or unmounted.
->If any of the public flags are already set, then the relevant
failure message is assigned.
2) RESUME THREAD:-
jvmtiThread.c:resumeThread:
jvmtiThread.c:jvmtiSuspendResumeCallBack
thread.cpp:Java_java_lang_Thread_resumeImpl
->In case of resume the halt flag
(J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND) is cleared if the thread
is mounted, i.e., threadObject == targetThread->threadObject in
J9VMThread's publicFlags also the hidden field "isSuspendedInternal"
set to a zero value for the thread instance in all cases regardless
of thread being mounted or unmounted.
->If any of the public flags are already set, then the relevant
failure message is assigned.
3) GETSTATE:-
jvmtiHelpers.c:getThreadState
jvmtiHelpers.c:getVirtualThreadState
->The getThreadState function is changed in such a way that will
verify the "isSuspendedInternal" filed to check the thread is
suspend or not.
The basic concept behind the new changes:-
[mounted + unmounted] set the "isSuspendedInternal" field
[mounted] the halt flag is only modified if the thread object is
stored in targetThread->threadObject
[unmounted] Delay setting the halt flag until the thread mount.
Related: #16689
Signed-off-by: Dipak Bagadiya [email protected]