diff --git a/runtime/jvmti/jvmtiHelpers.cpp b/runtime/jvmti/jvmtiHelpers.cpp index a5d3b300a50..0dd337e4f2a 100644 --- a/runtime/jvmti/jvmtiHelpers.cpp +++ b/runtime/jvmti/jvmtiHelpers.cpp @@ -739,19 +739,35 @@ getThreadStateHelper(J9VMThread *currentThread, j9object_t threadObject, J9VMThr if (vmstate & J9VMTHREAD_STATE_SUSPENDED) { state |= JVMTI_THREAD_STATE_SUSPENDED; } + + if (vmstate & J9VMTHREAD_STATE_INTERRUPTED) { + state |= JVMTI_THREAD_STATE_INTERRUPTED; + } + #if JAVA_SPEC_VERSION >= 19 - /* Based on the isSuspendedInternal field, set the JVMTI - * thread state to suspended for the corresponding thread. + /* Based on the isSuspendedInternal field, set the JVMTI thread state to suspended for + * the corresponding thread. */ if (0 != J9OBJECT_U32_LOAD(currentThread, threadObject, currentThread->javaVM->isSuspendedInternalOffset)) { state |= JVMTI_THREAD_STATE_SUSPENDED; } else { state &= ~JVMTI_THREAD_STATE_SUSPENDED; } -#endif /* JAVA_SPEC_VERSION >= 19 */ - if (vmstate & J9VMTHREAD_STATE_INTERRUPTED) { + + /* Thread.deadInterrupt is Thread.interrupted in OJDK's Thread implementation. In JDK19+, + * OJDK's Thread implementation is used, and multiple thread objects can be associated to + * a J9VMThread: a virtual thread and its carrier thread. If a virtual thread is mounted, + * then the carrier thread is unmounted and vice-versa. In such cases, J9VMThread's state + * should not be used to determine if a thread object is interrupted. Instead, + * Thread.interrupted is used to determine if a thread object is interrupted. + */ + if (J9VMJAVALANGTHREAD_DEADINTERRUPT(currentThread, threadObject)) { state |= JVMTI_THREAD_STATE_INTERRUPTED; + } else { + state &= ~JVMTI_THREAD_STATE_INTERRUPTED; } +#endif /* JAVA_SPEC_VERSION >= 19 */ + #if defined(J9VM_INTERP_ATOMIC_FREE_JNI) if (vmThread->inNative) { state |= JVMTI_THREAD_STATE_IN_NATIVE; @@ -891,6 +907,19 @@ getVirtualThreadState(J9VMThread *currentThread, jthread thread) } else { rc &= ~JVMTI_THREAD_STATE_SUSPENDED; } + + /* Thread.deadInterrupt is Thread.interrupted in OJDK's Thread implementation. In JDK19+, + * OJDK's Thread implementation is used, and multiple thread objects can be associated to + * a J9VMThread: a virtual thread and its carrier thread. If a virtual thread is mounted, + * then the carrier thread is unmounted and vice-versa. In such cases, J9VMThread's state + * should not be used to determine if a thread object is interrupted. Instead, + * Thread.interrupted is used to determine if a thread object is interrupted. + */ + if (J9VMJAVALANGTHREAD_DEADINTERRUPT(currentThread, vThreadObject)) { + rc |= JVMTI_THREAD_STATE_INTERRUPTED; + } else { + rc &= ~JVMTI_THREAD_STATE_INTERRUPTED; + } releaseVMThread(currentThread, targetThread, thread); } else { /* This is unreachable. */ diff --git a/runtime/oti/VMHelpers.hpp b/runtime/oti/VMHelpers.hpp index 2d2e4f8bc32..6e37341a74c 100644 --- a/runtime/oti/VMHelpers.hpp +++ b/runtime/oti/VMHelpers.hpp @@ -1410,8 +1410,24 @@ class VM_VMHelpers { J9VMThread *targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, threadObject); bool result = false; +#if JAVA_SPEC_VERSION >= 19 + /* Check if the mounted thread is suspended. */ + U_32 isSuspended = 0; + if (NULL != targetThread) { + isSuspended = J9OBJECT_U32_LOAD(currentThread, targetThread->threadObject, currentThread->javaVM->isSuspendedInternalOffset); + } +#endif /* JAVA_SPEC_VERSION >= 19 */ /* If the thread is alive, ask the OS thread. Otherwise, answer false. */ - if (J9VMJAVALANGTHREAD_STARTED(currentThread, threadObject) && (NULL != targetThread)) { + if ((NULL != targetThread) + && J9VMJAVALANGTHREAD_STARTED(currentThread, threadObject) +#if JAVA_SPEC_VERSION >= 19 + /* Thread.deadInterrupt is Thread.interrupted in OJDK's Thread implementation. + * In JDK19+, OJDK's Thread implementation is used. If the mounted thread is + * suspended, use Thread.interrupted to derive if the thread is interrupted. + */ + && (0 == isSuspended) +#endif /* JAVA_SPEC_VERSION >= 19 */ + ) { if (omrthread_interrupted(targetThread->osThread)) { result = true; } @@ -2043,8 +2059,26 @@ class VM_VMHelpers threadInterruptImpl(J9VMThread *currentThread, j9object_t targetObject) { J9VMThread *targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, targetObject); - if (J9VMJAVALANGTHREAD_STARTED(currentThread, targetObject) && (NULL != targetThread)) { - void (*sidecarInterruptFunction)(J9VMThread*) = currentThread->javaVM->sidecarInterruptFunction; + J9JavaVM *vm = currentThread->javaVM; +#if JAVA_SPEC_VERSION >= 19 + /* Check if the mounted thread is suspended. */ + U_32 isSuspended = 0; + if (NULL != targetThread) { + isSuspended = J9OBJECT_U32_LOAD(currentThread, targetThread->threadObject, vm->isSuspendedInternalOffset); + } +#endif /* JAVA_SPEC_VERSION >= 19 */ + if ((NULL != targetThread) + && J9VMJAVALANGTHREAD_STARTED(currentThread, targetObject) +#if JAVA_SPEC_VERSION >= 19 + /* Thread.deadInterrupt is Thread.interrupted in OJDK's Thread implementation. + * In JDK19+, OJDK's Thread implementation is used. If the mounted thread is + * suspended, only set Thread.interrupted to TRUE and do not wake/interrupt + * the thread. + */ + && (0 == isSuspended) +#endif /* JAVA_SPEC_VERSION >= 19 */ + ) { + void (*sidecarInterruptFunction)(J9VMThread*) = vm->sidecarInterruptFunction; if (NULL != sidecarInterruptFunction) { sidecarInterruptFunction(targetThread); }