From bdb11b90d741e1270a0d35261ccf7937659dc23c Mon Sep 17 00:00:00 2001 From: Babneet Singh Date: Tue, 12 Sep 2023 00:34:27 -0400 Subject: [PATCH] Handle unmounted carrier thread in ThreadMXBeanImpl.getThreadInfo If a virtual thread is mounted on a carrier thread, then blocker and blockerOwner are the virtual thread, and the vmstate is WAITING for the carrier thread. This behaviour matches the RI, and it also allows us to pass the virtual/CarrierThreadWaits (JTreg test). Related: #18051 Signed-off-by: Babneet Singh --- runtime/jcl/common/mgmtthread.c | 39 ++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/runtime/jcl/common/mgmtthread.c b/runtime/jcl/common/mgmtthread.c index 2b0e95f07a3..3822640b6f2 100644 --- a/runtime/jcl/common/mgmtthread.c +++ b/runtime/jcl/common/mgmtthread.c @@ -1296,7 +1296,32 @@ getThreadInfo(J9VMThread *currentThread, J9VMThread *targetThread, ThreadInfo *i info->thread = vmfns->j9jni_createLocalRef((JNIEnv *)currentThread, threadObject); /* Set the native thread ID available through the thread library. */ info->nativeTID = (jlong) omrthread_get_osId(targetThread->osThread); - info->vmstate = getVMThreadObjectState(targetThread, &monitorObject, &monitorOwner, NULL); + +#if JAVA_SPEC_VERSION >= 19 + if (NULL != continuation) { + j9object_t vThreadObject = targetThread->threadObject; + info->blocker = vmfns->j9jni_createLocalRef((JNIEnv *)currentThread, vThreadObject); + info->blockerOwner = info->blocker; + info->vmstate = J9VMTHREAD_STATE_WAITING; + } else +#endif /* JAVA_SPEC_VERSION >= 19 */ + { + info->vmstate = getVMThreadObjectState(targetThread, &monitorObject, &monitorOwner, NULL); + monitorOwnerObject = monitorOwner? (j9object_t)monitorOwner->threadObject : NULL; + + /* The monitorOwner thread could have exited before we read it. + * Force the thread to be RUNNABLE in this case. + */ + if ((J9VMTHREAD_STATE_BLOCKED == info->vmstate) + && (NULL != monitorOwner) && (NULL == monitorOwnerObject) + ) { + info->vmstate = J9VMTHREAD_STATE_RUNNING; + monitorObject = NULL; + } + info->blocker = vmfns->j9jni_createLocalRef((JNIEnv *)currentThread, monitorObject); + info->blockerOwner = vmfns->j9jni_createLocalRef((JNIEnv *)currentThread, monitorOwnerObject); + } + if (NULL != threadObject) { info->jclThreadState = getJclThreadState( info->vmstate, @@ -1304,18 +1329,6 @@ getThreadInfo(J9VMThread *currentThread, J9VMThread *targetThread, ThreadInfo *i } else { info->jclThreadState = getJclThreadState(info->vmstate, JNI_TRUE); } - monitorOwnerObject = monitorOwner? (j9object_t)monitorOwner->threadObject : NULL; - - /* The monitorOwner thread could have exited before we read it. - * Force the thread to be RUNNABLE in this case. - */ - if ((J9VMTHREAD_STATE_BLOCKED == info->vmstate) && - (NULL != monitorOwner) && (NULL == monitorOwnerObject)) { - info->vmstate = J9VMTHREAD_STATE_RUNNING; - monitorObject = NULL; - } - info->blocker = vmfns->j9jni_createLocalRef((JNIEnv *)currentThread, monitorObject); - info->blockerOwner = vmfns->j9jni_createLocalRef((JNIEnv *)currentThread, monitorOwnerObject); /* this may block on vm->managementDataLock */ getContentionStats(currentThread, targetThread, info);