Skip to content

Commit bc535a4

Browse files
authored
Merge pull request #18439 from babsingh/main1
Spin during VirtualThread MountBegin and UnmountBegin
2 parents f9dffe6 + feac356 commit bc535a4

File tree

3 files changed

+52
-21
lines changed

3 files changed

+52
-21
lines changed

runtime/j9vm/javanextvmi.cpp

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ extern "C" {
4040

4141
#if JAVA_SPEC_VERSION >= 19
4242
extern J9JavaVM *BFUjavaVM;
43+
44+
extern IDATA (*f_threadSleep)(I_64 millis);
4345
#endif /* JAVA_SPEC_VERSION >= 19 */
4446

4547
/* Define for debug
@@ -328,6 +330,27 @@ virtualThreadMountBegin(JNIEnv *env, jobject thread)
328330
}
329331

330332
enterVThreadTransitionCritical(currentThread, thread);
333+
334+
/* Virtual thread is being mounted but it has been suspended. Spin until the
335+
* virtual thread is resumed. The virtual thread should not be mounted until
336+
* it is resumed.
337+
*/
338+
J9JavaVM *vm = currentThread->javaVM;
339+
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
340+
threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
341+
while (0 != J9OBJECT_U32_LOAD(currentThread, threadObj, vm->isSuspendedInternalOffset)) {
342+
exitVThreadTransitionCritical(currentThread, threadObj);
343+
vmFuncs->internalReleaseVMAccess(currentThread);
344+
/* Spin is used instead of the halt flag; otherwise, the carrier thread will
345+
* show as suspended.
346+
*
347+
* TODO: Dynamically increase the sleep time to a bounded maximum.
348+
*/
349+
f_threadSleep(10);
350+
vmFuncs->internalAcquireVMAccess(currentThread);
351+
enterVThreadTransitionCritical(currentThread, thread);
352+
threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
353+
}
331354
}
332355

333356
/* Caller must have VMAccess. */
@@ -354,15 +377,6 @@ virtualThreadMountEnd(JNIEnv *env, jobject thread)
354377
J9VMJDKINTERNALVMCONTINUATION_VMREF(currentThread, continuationObj));
355378
}
356379

357-
/* Virtual thread is being mounted but it has been suspended. Thus,
358-
* set J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND flag. At this
359-
* point, virtual thread object is stored in targetThread->threadObject.
360-
*/
361-
if (0 != J9OBJECT_U32_LOAD(currentThread, threadObj, vm->isSuspendedInternalOffset)) {
362-
Assert_SC_true(threadObj == currentThread->threadObject);
363-
vm->internalVMFunctions->setHaltFlag(currentThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND);
364-
}
365-
366380
/* Allow thread to be inspected again. */
367381
exitVThreadTransitionCritical(currentThread, threadObj);
368382

@@ -396,6 +410,28 @@ virtualThreadUnmountBegin(JNIEnv *env, jobject thread)
396410

397411
enterVThreadTransitionCritical(currentThread, thread);
398412
VM_VMHelpers::virtualThreadHideFrames(currentThread, JNI_TRUE);
413+
414+
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
415+
j9object_t carrierThreadObject = currentThread->carrierThreadObject;
416+
threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
417+
/* Virtual thread is being umounted. If its carrier thread is suspended, spin until
418+
* the carrier thread is resumed. The carrier thread should not be mounted until it
419+
* is resumed.
420+
*/
421+
while (0 != J9OBJECT_U32_LOAD(currentThread, carrierThreadObject, vm->isSuspendedInternalOffset)) {
422+
exitVThreadTransitionCritical(currentThread, threadObj);
423+
vmFuncs->internalReleaseVMAccess(currentThread);
424+
/* Spin is used instead of the halt flag; otherwise, the virtual thread will
425+
* show as suspended.
426+
*
427+
* TODO: Dynamically increase the sleep time to a bounded maximum.
428+
*/
429+
f_threadSleep(10);
430+
vmFuncs->internalAcquireVMAccess(currentThread);
431+
enterVThreadTransitionCritical(currentThread, thread);
432+
carrierThreadObject = currentThread->carrierThreadObject;
433+
threadObj = J9_JNI_UNWRAP_REFERENCE(thread);
434+
}
399435
}
400436

401437
/* Caller must have VMAccess. */
@@ -429,15 +465,6 @@ virtualThreadUnmountEnd(JNIEnv *env, jobject thread)
429465
vmFuncs->freeTLS(currentThread, threadObj);
430466
}
431467

432-
j9object_t carrierThreadObject = currentThread->carrierThreadObject;
433-
/* The J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND will be set for the virtual
434-
* thread's carrier thread if it was suspended while the virtual thread was mounted.
435-
*/
436-
if (0 != J9OBJECT_U32_LOAD(currentThread, carrierThreadObject, vm->isSuspendedInternalOffset)) {
437-
Assert_SC_true((currentThread->threadObject == carrierThreadObject) && (NULL == currentThread->currentContinuation));
438-
vmFuncs->setHaltFlag(currentThread, J9_PUBLIC_FLAGS_HALT_THREAD_JAVA_SUSPEND);
439-
}
440-
441468
/* Allow thread to be inspected again. */
442469
exitVThreadTransitionCritical(currentThread, threadObj);
443470
}

runtime/j9vm/jvm.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ typedef IDATA (*MonitorDestroy)(omrthread_monitor_t monitor);
212212
typedef IDATA (* ThreadLibControl)(const char * key, UDATA value);
213213
typedef IDATA (*SetCategory)(omrthread_t thread, UDATA category, UDATA type);
214214
typedef IDATA (*LibEnableCPUMonitor)(omrthread_t thread);
215+
typedef IDATA (*ThreadSleep)(I_64 millis);
215216

216217
typedef I_32 (*PortInitLibrary)(J9PortLibrary *portLib, J9PortLibraryVersion *version, UDATA size);
217218
typedef UDATA (*PortGetSize)(struct J9PortLibraryVersion *version);
@@ -260,6 +261,7 @@ static pNewStringPlatform globalNewStringPlatform;
260261
static p_a2e_vsprintf global_a2e_vsprintf;
261262
#endif
262263

264+
ThreadSleep f_threadSleep;
263265
static ThreadGlobal f_threadGlobal;
264266
static ThreadAttachEx f_threadAttachEx;
265267
static ThreadDetach f_threadDetach;
@@ -1015,8 +1017,9 @@ preloadLibraries(void)
10151017
f_threadLibControl = (ThreadLibControl) GetProcAddress (threadDLL, (LPCSTR) "omrthread_lib_control");
10161018
f_setCategory = (SetCategory) GetProcAddress (threadDLL, (LPCSTR) "omrthread_set_category");
10171019
f_libEnableCPUMonitor = (LibEnableCPUMonitor) GetProcAddress (threadDLL, (LPCSTR) "omrthread_lib_enable_cpu_monitor");
1020+
f_threadSleep = (ThreadSleep) GetProcAddress (threadDLL, (LPCSTR) "omrthread_sleep");
10181021
if (!f_threadGlobal || !f_threadAttachEx || !f_threadDetach || !f_monitorEnter || !f_monitorExit || !f_monitorInit
1019-
|| !f_monitorDestroy || !f_threadLibControl || !f_setCategory || !f_libEnableCPUMonitor
1022+
|| !f_monitorDestroy || !f_threadLibControl || !f_setCategory || !f_libEnableCPUMonitor || !f_threadSleep
10201023
) {
10211024
FreeLibrary(vmDLL);
10221025
FreeLibrary(threadDLL);
@@ -1442,8 +1445,9 @@ preloadLibraries(void)
14421445
f_threadLibControl = (ThreadLibControl) dlsym (threadDLL, "omrthread_lib_control");
14431446
f_setCategory = (SetCategory) dlsym (threadDLL, "omrthread_set_category");
14441447
f_libEnableCPUMonitor = (LibEnableCPUMonitor) dlsym (threadDLL, "omrthread_lib_enable_cpu_monitor");
1448+
f_threadSleep = (ThreadSleep) dlsym (threadDLL, "omrthread_sleep");
14451449
if (!f_threadGlobal || !f_threadAttachEx || !f_threadDetach || !f_monitorEnter || !f_monitorExit || !f_monitorInit
1446-
|| !f_monitorDestroy || !f_threadLibControl || !f_setCategory || !f_libEnableCPUMonitor
1450+
|| !f_monitorDestroy || !f_threadLibControl || !f_setCategory || !f_libEnableCPUMonitor || !f_threadSleep
14471451
) {
14481452
dlclose(vmDLL);
14491453
#ifdef J9ZOS390

runtime/jvmti/jvmtiThread.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,7 @@ jvmtiSuspendResumeCallBack(J9VMThread *vmThread, J9MM_IterateObjectDescriptor *o
13261326
{
13271327
j9object_t continuationObj = object->object;
13281328
j9object_t vthread = J9VMJDKINTERNALVMCONTINUATION_VTHREAD(vmThread, continuationObj);
1329-
ContinuationState continuationState = J9VMJDKINTERNALVMCONTINUATION_STATE(vmThread, continuationObj);;
1329+
ContinuationState continuationState = J9VMJDKINTERNALVMCONTINUATION_STATE(vmThread, continuationObj);
13301330

13311331
if ((NULL != vthread) && J9_ARE_NO_BITS_SET(continuationState, J9_GC_CONTINUATION_STATE_LAST_UNMOUNT)) {
13321332
jvmtiVThreadCallBackData *data = (jvmtiVThreadCallBackData*)userData;

0 commit comments

Comments
 (0)