Skip to content
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

Update the fully mounted check in JVMTI Suspend/Resume Thread #18448

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions runtime/jvmti/jvmtiHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr,
BOOLEAN isThreadAlive = FALSE;
#if JAVA_SPEC_VERSION >= 19
BOOLEAN isVirtualThread = FALSE;
J9InternalVMFunctions const * const vmfuncs = vm->internalVMFunctions;
#endif /* JAVA_SPEC_VERSION >= 19 */

if (NULL == thread) {
Expand Down Expand Up @@ -155,14 +156,20 @@ getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr,
if (isVirtualThread) {
jint vthreadState = 0;
j9object_t carrierThread = NULL;
vm->internalVMFunctions->acquireVThreadInspector(currentThread, thread, TRUE);

vmfuncs->acquireVThreadInspector(currentThread, thread, TRUE);

/* Re-fetch threadObject since acquireVThreadInspector can release and reacquire VM access. */
threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
vthreadState = J9VMJAVALANGVIRTUALTHREAD_STATE(currentThread, threadObject);
carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, threadObject);
if (NULL != carrierThread) {

if ((NULL != carrierThread)
&& vmfuncs->isVThreadFullyMounted(currentThread, threadObject)
) {
targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, carrierThread);
}

vthreadState = J9VMJAVALANGVIRTUALTHREAD_STATE(currentThread, threadObject);
isThreadAlive = (JVMTI_VTHREAD_STATE_NEW != vthreadState) && (JVMTI_VTHREAD_STATE_TERMINATED != vthreadState);
} else
#endif /* JAVA_SPEC_VERSION >= 19 */
Expand All @@ -175,7 +182,7 @@ getVMThread(J9VMThread *currentThread, jthread thread, J9VMThread **vmThreadPtr,
if (OMR_ARE_ANY_BITS_SET(flags, J9JVMTI_GETVMTHREAD_ERROR_ON_DEAD_THREAD)) {
#if JAVA_SPEC_VERSION >= 19
if (isVirtualThread) {
vm->internalVMFunctions->releaseVThreadInspector(currentThread, thread);
vmfuncs->releaseVThreadInspector(currentThread, thread);
}
#endif /* JAVA_SPEC_VERSION >= 19 */
omrthread_monitor_exit(vm->vmThreadListMutex);
Expand Down
14 changes: 9 additions & 5 deletions runtime/jvmti/jvmtiThread.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,10 +1139,9 @@ resumeThread(J9VMThread *currentThread, jthread thread)
J9JavaVM *vm = currentThread->javaVM;
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
/* The J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND will be cleared only
* if the thread is resumed and it has been mounted
* i.e. threadObject == targetThread->threadObject.
* if the thread is resumed and it has been mounted.
*/
if ((NULL != targetThread) && (threadObject == targetThread->threadObject))
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
if (OMR_ARE_ANY_BITS_SET(targetThread->publicFlags, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND)) {
Expand Down Expand Up @@ -1341,12 +1340,17 @@ jvmtiSuspendResumeCallBack(J9VMThread *vmThread, J9MM_IterateObjectDescriptor *o
J9JavaVM *vm = vmThread->javaVM;
J9VMThread *targetThread = NULL;
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(vmThread, vthread);
BOOLEAN isFullyMounted = FALSE;
if (NULL != carrierThread) {
targetThread = J9VMJAVALANGTHREAD_THREADREF(vmThread, carrierThread);
if (NULL != targetThread) {
isFullyMounted = vm->internalVMFunctions->isVThreadFullyMounted(vmThread, vthread);
}
Assert_JVMTI_notNull(targetThread);
}
if (data->is_suspend) {
if ((NULL != targetThread) && (vthread == targetThread->threadObject)) {
/* Suspend the virtual thread. */
if ((NULL != targetThread) && isFullyMounted) {
if (OMR_ARE_NO_BITS_SET(targetThread->publicFlags, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND | J9_PUBLIC_FLAGS_STOPPED)) {
setHaltFlag(targetThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND);
Trc_JVMTI_threadSuspended(targetThread);
Expand All @@ -1355,7 +1359,7 @@ jvmtiSuspendResumeCallBack(J9VMThread *vmThread, J9MM_IterateObjectDescriptor *o
J9OBJECT_U32_STORE(vmThread, vthread, vm->isSuspendedInternalOffset, 1);
} else {
/* Resume the virtual thread. */
if ((NULL != targetThread) && (vthread == targetThread->threadObject)) {
if ((NULL != targetThread) && isFullyMounted) {
if (OMR_ARE_ANY_BITS_SET(targetThread->publicFlags, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND)) {
clearHaltFlag(targetThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND);
Trc_JVMTI_threadResumed(targetThread);
Expand Down
2 changes: 1 addition & 1 deletion runtime/jvmti/suspendhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ suspendThread(J9VMThread *currentThread, jthread thread, BOOLEAN allowNull, BOOL
/* The J9 PUBLIC FLAGS HALT THREAD JAVA SUSPEND flag will be set
* if the thread is mounted.
*/
if ((NULL != targetThread) && (threadObject == targetThread->threadObject))
if (NULL != targetThread)
#endif /* JAVA_SPEC_VERSION >= 19 */
{
if (OMR_ARE_ANY_BITS_SET(targetThread->publicFlags, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND)) {
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -5059,6 +5059,7 @@ typedef struct J9InternalVMFunctions {
UDATA (*walkAllStackFrames)(struct J9VMThread *currentThread, J9StackWalkState *walkState);
BOOLEAN (*acquireVThreadInspector)(struct J9VMThread *currentThread, jobject thread, BOOLEAN spin);
void (*releaseVThreadInspector)(struct J9VMThread *currentThread, jobject thread);
BOOLEAN (*isVThreadFullyMounted)(struct J9VMThread *currentThread, j9object_t vThread);
#endif /* JAVA_SPEC_VERSION >= 19 */
UDATA (*checkArgsConsumed)(struct J9JavaVM * vm, struct J9PortLibrary* portLibrary, struct J9VMInitArgs* j9vm_args);
#if defined(J9VM_ZOS_3164_INTEROPERABILITY) && (JAVA_SPEC_VERSION >= 17)
Expand Down
11 changes: 11 additions & 0 deletions runtime/oti/vm_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -4518,6 +4518,17 @@ acquireVThreadInspector(J9VMThread *currentThread, jobject thread, BOOLEAN spin)
*/
void
releaseVThreadInspector(J9VMThread *currentThread, jobject thread);

/**
* @brief Check if the virtual thread is fully mounted. If a virtual thread
* is not provided, FALSE is returned.
*
* @param currentThread current thread
* @param vThread the virtual thread
* @return TRUE if it is mounted and FALSE if unmounted
*/
BOOLEAN
isVThreadFullyMounted(J9VMThread *currentThread, j9object_t vThread);
#endif /* JAVA_SPEC_VERSION >= 19 */

/* ---------------- hookableAsync.c ---------------- */
Expand Down
13 changes: 13 additions & 0 deletions runtime/vm/ContinuationHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,4 +585,17 @@ releaseVThreadInspector(J9VMThread *currentThread, jobject thread)
vthreadInspectorCount = J9OBJECT_I64_LOAD(currentThread, threadObj, vm->virtualThreadInspectorCountOffset);
}
}

BOOLEAN
isVThreadFullyMounted(J9VMThread *currentThread, j9object_t vThread)
{
if (IS_JAVA_LANG_VIRTUALTHREAD(currentThread, vThread)) {
/* Return FALSE if a virtual thread is not provided. */
return FALSE;
}

j9object_t continuationObj = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CONT(currentThread, vThread);
ContinuationState continuationState = J9VMJDKINTERNALVMCONTINUATION_STATE(currentThread, continuationObj);
return VM_ContinuationHelpers::isFullyMounted(continuationState);
}
} /* extern "C" */
1 change: 1 addition & 0 deletions runtime/vm/intfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ J9InternalVMFunctions J9InternalFunctions = {
walkAllStackFrames,
acquireVThreadInspector,
releaseVThreadInspector,
isVThreadFullyMounted,
#endif /* JAVA_SPEC_VERSION >= 19 */
checkArgsConsumed,
#if defined(J9VM_ZOS_3164_INTEROPERABILITY) && (JAVA_SPEC_VERSION >= 17)
Expand Down