Block Virtual Threads for JVMTI Inspection - #15766
Conversation
|
FYI @EricYangIBM I approved the original PR #15690 |
|
after discussion with Jack a few things:
For inspector:
|
|
Per discussion with @tajila we have come up with a new way of blocking vthread mount/unmount to avoid any timing issue between threadstate updates and thread stack swap in continuation: notifyJVMTIMountBegin() {
omrthread_monitor_enter(vm->liveVirtualThreadListMutex);
while (inspectorCount != 0) {
omrthread_monitor_wait(vm->liveVirtualThreadListMutex);
}
inspectorCount = -1;
omrthread_monitor_exit(vm->liveVirtualThreadListMutex);
}
notifyJVMTIMountEnd() {
omrthread_monitor_enter(vm->liveVirtualThreadListMutex);
inspectorCount = 0;
omrthread_monitor_notify_all(vm->liveVirtualThreadListMutex);
omrthread_monitor_exit(vm->liveVirtualThreadListMutex);
}same logic applies to unmountBegin/End for getVMThread {
if (currentThread->threadObject != threadObject) {
omrthread_monitor_enter(vm->liveVirtualThreadListMutex);
while (inspectorCount == -1) {
omrthread_monitor_wait(vm->liveVirtualThreadListMutex);
}
inspectorCount += 1;
omrthread_monitor_exit(vm->liveVirtualThreadListMutex);
}
}
releaseVMThread {
if (currentThread->threadObject != threadObject) {
omrthread_monitor_enter(vm->liveVirtualThreadListMutex);
assert(inspectorCount > 0)
inspectorCount -= 1;
omrthread_monitor_notify_all(vm->liveVirtualThreadListMutex);
omrthread_monitor_exit(vm->liveVirtualThreadListMutex);
}
} |
|
@gacholio ^^ |
|
At a glance this seems reasonable - I'll have to look in a bit more detail. I also had comments in the old PR which may or may not still apply - will do a full review. |
I think this still applies. not sure why NULL is being passed, @fengxue-IS do you know why?
I dont quite understand this one. Most of the code that calls |
Two cases are because virtual threads are not supported with the operation ( |
I'm not sure why you believe this - the obvious case of Thread.getStackTrace() clearly must halt the target thread before walking it's stack. |
This is unnecessarily confusing for no gain - why not simply follow the pattern? |
If |
Agreed |
Right - the code has to work for all types of threads (for the calls that don't exclude virtual). |
What I mean when getting a stack trace, we are not acquiring the stack while the thread is running, it must be halted (this is what I meant by point in time). So youll never observe the vthread related changes between the start and end of the operation since the thread cannot change. For get/releaseVMThread however, the thread is still active within that window, hence why it needs more safe guards. |
|
Please let me know when you've implemented the new solution and I'll do the review. |
|
The Thread code does not use JVMTI - it calls halt directly. The stack trace code will presumably need to be updated (to get the stack of unmounted continuations) at some point, but it will still be halting in the same fashion and must prevent mount/unmount or any other change to the java stack being inspected. |
if the virtual thread is mounted, then haltThreadForInspection should prevent any operation including unmount |
|
I suppose the stack swaps always occur while holding VM access, so the normal halt would indeed prevent that from happening. |
f92ad80 to
08564a6
Compare
|
The new approach has been implemented @gacholio |
|
Please squash the commits before testing. |
- Return the corresponding J9VMThread for a virtual thread from
getVMThread.
- Prevent the virtual thread from (un)mounting using the inspectorCount
approach.
- The (un)mountBegin/(un)mountEnd natives lock the mount/unmount section
and prevent inspectors from inspecting during that time.
- For a virtual thread, even the underlying J9VMThread is prevented from
terminating using the inspectorCount approach.
- Moved code from notifyJvmtiUnmountEnd to notifyJvmtiUnmountBegin for blocking
before unmount. Also, VirtualThread.carrierThread is set to NULL in unmount.
So, removing the VirtualThread from the linked list before the last unmount
in notifyJvmtiUnmountBegin seems correct.
- Block mount after yield if a virtual thread is being inspected.
- In getVMThread:
- targetThread will be NULL for a yielded virtual thread.
- JVMTI_ERROR_NONE will be returned for a yielded virtual thread.
- virtualThreadInspectorCount will be incremented for the yielded
virtual thread.
- If a virtual thread is in the process of mounting/unmounting, wait
until it is done before inspecting.
Related: eclipse-openj9#15183. This impacts all JVMTI functions that rely on getVMThread and
releaseVMThread.
Original PR: eclipse-openj9#15690
Co-authored-by: Babneet Singh <sbabneet@ca.ibm.com>
Signed-off-by: Eric Yang <eric.yang@ibm.com>
ce77c06 to
54c65d0
Compare
|
Squashed |
|
jenkins test sanity.functional plinux jdk19 |
|
jenkins compile win jdk8 |
|
@fengxue-IS Have all of your concerns been addressed? |
|
fyi plinux is down atm (and xlinux, mac). |
|
jenkins test sanity amac jdk19 |
mac includes amac ( |
|
jenkins test sanity win jdk19 |
getVMThread.
approach.
and prevent inspectors from inspecting during that time.
terminating using the inspectorCount approach.
before unmount. Also, VirtualThread.carrierThread is set to NULL in unmount.
So, removing the VirtualThread from the linked list before the last unmount
in notifyJvmtiUnmountBegin seems correct.
virtual thread.
until it is done before inspecting.
Related: #15183. This impacts all JVMTI functions that rely on getVMThread and
releaseVMThread.
Original PR: #15690
Co-authored-by: Babneet Singh sbabneet@ca.ibm.com
Signed-off-by: Eric Yang eric.yang@ibm.com