Skip to content

Commit

Permalink
Update jvmtiGetThreadListStackTraces to support virtual thread
Browse files Browse the repository at this point in the history
Traverse the thread list before acquireExclusiveVMAccess and
after releaseExclusiveVMAccess to ensure virtual thread transition
completion.

Update live thread check for virtual thread

Update surrounding code style

Issues: eclipse-openj9#15759 eclipse-openj9#15183

Signed-off-by: Gengchen Tuo <gengchen.tuo@ibm.com>
  • Loading branch information
thallium committed Sep 21, 2022
1 parent 32d53c0 commit 43ceb07
Showing 1 changed file with 86 additions and 16 deletions.
102 changes: 86 additions & 16 deletions runtime/jvmti/jvmtiStackFrame.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,17 +187,21 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,
jint max_frame_count,
jvmtiStackInfo** stack_info_ptr)
{
J9JavaVM * vm = JAVAVM_FROM_ENV(env);
jvmtiError rc;
J9VMThread * currentThread;
PORT_ACCESS_FROM_JAVAVM(vm);
J9JavaVM *vm = JAVAVM_FROM_ENV(env);
jvmtiError rc = JVMTI_ERROR_NONE;
J9VMThread *currentThread = NULL;
jvmtiStackInfo *rv_stack_info = NULL;
PORT_ACCESS_FROM_JAVAVM(vm);

Trc_JVMTI_jvmtiGetThreadListStackTraces_Entry(env);

rc = getCurrentVMThread(vm, &currentThread);
if (rc == JVMTI_ERROR_NONE) {
jvmtiStackInfo * stackInfo;
jvmtiStackInfo *stackInfo = NULL;
#if JAVA_SPEC_VERSION >= 19
const jint originalThreadCount = thread_count;
const jthread *originalThreadList = thread_list;
#endif /* JAVA_SPEC_VERSION >= 19 */

vm->internalVMFunctions->internalEnterVMFromJNI(currentThread);

Expand All @@ -208,33 +212,70 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,
ENSURE_NON_NEGATIVE(max_frame_count);
ENSURE_NON_NULL(stack_info_ptr);

#if JAVA_SPEC_VERSION >= 19
while (0 != thread_count) {
jthread thread = *thread_list;

if ((NULL != thread) && IS_VIRTUAL_THREAD(currentThread, J9_JNI_UNWRAP_REFERENCE(thread))) {
J9VMThread *targetThread = NULL;
getVMThread(currentThread, thread, &targetThread, TRUE, FALSE);
}
++thread_list;
--thread_count;
}
#endif /* JAVA_SPEC_VERSION >= 19 */

vm->internalVMFunctions->acquireExclusiveVMAccess(currentThread);

#if JAVA_SPEC_VERSION >= 19
thread_count = originalThreadCount;
thread_list = originalThreadList;
#endif /* JAVA_SPEC_VERSION >= 19 */

stackInfo = j9mem_allocate_memory(((sizeof(jvmtiStackInfo) + (max_frame_count * sizeof(jvmtiFrameInfo))) * thread_count) + sizeof(jlocation), J9MEM_CATEGORY_JVMTI_ALLOCATE);
if (stackInfo == NULL) {
rc = JVMTI_ERROR_OUT_OF_MEMORY;
} else {
jvmtiFrameInfo * currentFrameInfo = (jvmtiFrameInfo *) ((((UDATA) (stackInfo + thread_count)) + sizeof(jlocation)) & ~sizeof(jlocation));
jvmtiStackInfo * currentStackInfo = stackInfo;
jvmtiFrameInfo *currentFrameInfo = (jvmtiFrameInfo *)((((UDATA)(stackInfo + thread_count)) + sizeof(jlocation)) & ~sizeof(jlocation));
jvmtiStackInfo *currentStackInfo = stackInfo;

while (thread_count != 0) {
while (0 != thread_count) {
jthread thread = *thread_list;
J9VMThread * targetThread;
j9object_t threadObject;
J9VMThread *targetThread = NULL;
j9object_t threadObject = NULL;
BOOLEAN isThreadAlive = FALSE;
#if JAVA_SPEC_VERSION >= 19
BOOLEAN isVirtual = FALSE;
#endif /* JAVA_SPEC_VERSION >= 19 */

if (thread == NULL) {
if (NULL == thread) {
rc = JVMTI_ERROR_NULL_POINTER;
goto deallocate;
}

if (!isSameOrSuperClassOf(J9VMJAVALANGTHREAD_OR_NULL(vm), J9OBJECT_CLAZZ(currentThread, *((j9object_t *) thread)))) {
threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
if (!isSameOrSuperClassOf(J9VMJAVALANGTHREAD_OR_NULL(vm), J9OBJECT_CLAZZ(currentThread, threadObject))) {
rc = JVMTI_ERROR_INVALID_THREAD;
goto deallocate;
}

threadObject = *((j9object_t*) thread);
targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, threadObject);
if (targetThread == NULL) {
#if JAVA_SPEC_VERSION >= 19
if (IS_VIRTUAL_THREAD(currentThread, threadObject)) {
isVirtual = TRUE;
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, threadObject);
jint vthreadState = J9VMJAVALANGVIRTUALTHREAD_STATE(currentThread, threadObject);
if (NULL != carrierThread) {
targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, carrierThread);
}
isThreadAlive = (JVMTI_VTHREAD_STATE_NEW != vthreadState) && (JVMTI_VTHREAD_STATE_TERMINATED != vthreadState);
} else
#endif /* JAVA_SPEC_VERSION >= 19 */
{
targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, threadObject);
isThreadAlive = (NULL != targetThread);
}

if (!isThreadAlive) {
currentStackInfo->frame_count = 0;
} else {
rc = jvmtiInternalGetStackTrace(
Expand All @@ -253,7 +294,14 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,
}
}
currentStackInfo->thread = thread;
currentStackInfo->state = getThreadState(currentThread, threadObject);
#if JAVA_SPEC_VERSION >= 19
if (isVirtual) {
currentStackInfo->state = getVirtualThreadState(currentThread, thread);
} else
#endif /* JAVA_SPEC_VERSION >= 19 */
{
currentStackInfo->state = getThreadState(currentThread, threadObject);
}
currentStackInfo->frame_buffer = currentFrameInfo;

++thread_list;
Expand All @@ -267,6 +315,28 @@ jvmtiGetThreadListStackTraces(jvmtiEnv* env,
fail:
vm->internalVMFunctions->releaseExclusiveVMAccess(currentThread);

#if JAVA_SPEC_VERSION >= 19
thread_count = originalThreadCount;
thread_list = originalThreadList;
while (0 != thread_count) {
jthread thread = *thread_list;

if (NULL != thread) {
j9object_t threadObject = J9_JNI_UNWRAP_REFERENCE(thread);
if (IS_VIRTUAL_THREAD(currentThread, threadObject)) {
J9VMThread *targetThread = NULL;
j9object_t carrierThread = (j9object_t)J9VMJAVALANGVIRTUALTHREAD_CARRIERTHREAD(currentThread, threadObject);
if (NULL != carrierThread) {
targetThread = J9VMJAVALANGTHREAD_THREADREF(currentThread, carrierThread);
}
releaseVMThread(currentThread, targetThread, thread);
}
}
++thread_list;
--thread_count;
}
#endif /* JAVA_SPEC_VERSION >= 19 */

done:
vm->internalVMFunctions->internalExitVMToJNI(currentThread);
}
Expand Down

0 comments on commit 43ceb07

Please sign in to comment.