From fab1bbd20c0dae1fd0868e8ef379de660ff73a51 Mon Sep 17 00:00:00 2001 From: Babneet Singh Date: Wed, 13 Mar 2024 14:38:41 -0400 Subject: [PATCH 1/2] Update ScopedMemoryAccess_closeScope0 for JDK22 In JDK22, the definition has changed to native void closeScope0(MemorySessionImpl session, ScopedAccessError error); The return type has changed from boolean to void, and a second parameter is re-introduced: "ScopedAccessError error". Previously, closeScope0 would be retried until it returned true, which suggested that the scope/session was not found on any thread's stack. The new behaviour sets an asynchronous exception for all threads, which have the scope/session on their stack. The second parameter, error, is the asynchronous exception, which is thrown. Before throwing the error, the thread verifies if the scope/session is still on the stack. If not, the asynchronous exception is cleared and not thrown. Related: https://github.com/eclipse-openj9/openj9/issues/13211#issuecomment-1984768250 Signed-off-by: Babneet Singh --- runtime/gc_structs/VMThreadSlotIterator.cpp | 6 ++ .../jdk_internal_misc_ScopedMemoryAccess.cpp | 75 +++++++--------- runtime/oti/j9consts.h | 2 +- runtime/oti/j9nonbuilder.h | 5 ++ runtime/oti/jclprots.h | 10 ++- runtime/oti/vm_api.h | 10 +++ runtime/vm/AsyncMessageHandler.cpp | 89 +++++++++++++++++++ runtime/vm/intfunc.c | 1 + 8 files changed, 151 insertions(+), 47 deletions(-) diff --git a/runtime/gc_structs/VMThreadSlotIterator.cpp b/runtime/gc_structs/VMThreadSlotIterator.cpp index 2511c3b4c22..5a09e380592 100644 --- a/runtime/gc_structs/VMThreadSlotIterator.cpp +++ b/runtime/gc_structs/VMThreadSlotIterator.cpp @@ -65,6 +65,12 @@ GC_VMThreadSlotIterator::nextSlot() case 11: return &(_vmThread->scopedValueCache); #endif /* JAVA_SPEC_VERSION >= 19 */ +#if JAVA_SPEC_VERSION >= 22 + case 12: + return &(_vmThread->scopedError); + case 13: + return &(_vmThread->closeScopeObj); +#endif /* JAVA_SPEC_VERSION >= 22 */ default: break; } diff --git a/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp b/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp index 855b6373127..e61a595e393 100644 --- a/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp +++ b/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp @@ -37,49 +37,28 @@ Java_jdk_internal_misc_ScopedMemoryAccess_registerNatives(JNIEnv *env, jclass cl { } -static UDATA -closeScope0FrameWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState) -{ - if (JNI_FALSE == *(jboolean *)walkState->userData2) { - /* scope has been found */ - return J9_STACKWALK_STOP_ITERATING; - } - return J9_STACKWALK_KEEP_ITERATING; -} - -static void -closeScope0OSlotWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState, j9object_t *slot, const void *stackLocation) -{ - J9Method *method = walkState->method; - if (NULL != method) { - J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method); - if (NULL != romMethod && J9ROMMETHOD_HAS_EXTENDED_MODIFIERS(romMethod)) { - U_32 extraModifiers = getExtendedModifiersDataFromROMMethod(romMethod); - if (J9ROMMETHOD_HAS_SCOPED_ANNOTATION(extraModifiers)) { - if (*slot == J9_JNI_UNWRAP_REFERENCE(walkState->userData1)) { - *(jboolean *)walkState->userData2 = JNI_FALSE; - } - } - } - } -} - /** * For each thread, walk Java stack and look for the scope instance. Methods that can take and access a scope * instance are marked with the "@Scoped" extended modifier. If the scope instance is found in a method, that * method is accessing the memory segment associated with the scope and thus closing the scope will fail. */ +#if JAVA_SPEC_VERSION >= 22 +void JNICALL +Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject error) +#elif (JAVA_SPEC_VERSION >= 19) && (JAVA_SPEC_VERSION <= 21) /* JAVA_SPEC_VERSION >= 22 */ jboolean JNICALL -#if JAVA_SPEC_VERSION >= 19 Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope) -#else /* JAVA_SPEC_VERSION >= 19 */ +#else /* JAVA_SPEC_VERSION >= 22 */ +jboolean JNICALL Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject exception) -#endif /* JAVA_SPEC_VERSION >= 19 */ +#endif /* JAVA_SPEC_VERSION >= 22 */ { J9VMThread *currentThread = (J9VMThread *)env; J9JavaVM *vm = currentThread->javaVM; const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions; - jboolean scopeNotFound = JNI_TRUE; +#if JAVA_SPEC_VERSION <= 21 + jboolean scopeFound = JNI_FALSE; +#endif /* JAVA_SPEC_VERSION <= 21 */ vmFuncs->internalEnterVMFromJNI(currentThread); @@ -88,21 +67,29 @@ Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject insta } else { vmFuncs->acquireExclusiveVMAccess(currentThread); J9VMThread *walkThread = J9_LINKED_LIST_START_DO(vm->mainThread); + j9object_t closeScopeObj = J9_JNI_UNWRAP_REFERENCE(scope); +#if JAVA_SPEC_VERSION >= 22 + j9object_t errorObj = J9_JNI_UNWRAP_REFERENCE(error); +#endif /* JAVA_SPEC_VERSION >= 22 */ while (NULL != walkThread) { if (VM_VMHelpers::threadCanRunJavaCode(walkThread)) { - J9StackWalkState walkState; - walkState.walkThread = walkThread; - walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_ITERATE_O_SLOTS; - walkState.skipCount = 0; - walkState.userData1 = (void *)scope; - walkState.userData2 = (void *)&scopeNotFound; - walkState.frameWalkFunction = closeScope0FrameWalkFunction; - walkState.objectSlotWalkFunction = closeScope0OSlotWalkFunction; +#if JAVA_SPEC_VERSION >= 22 + /* Skip since an exception is already pending to be thrown.*/ + if (NULL != walkThread->scopedError) { + continue; + } +#endif /* JAVA_SPEC_VERSION >= 22 */ - vm->walkStackFrames(walkThread, &walkState); - if (JNI_FALSE == *(jboolean *)walkState.userData2) { - /* scope found */ + if (vmFuncs->hasMemoryScope(walkThread, closeScopeObj)) { + /* Scope found. */ +#if JAVA_SPEC_VERSION >= 22 + setHaltFlag(walkThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE); + walkThread->scopedError = errorObj; + walkThread->closeScopeObj = closeScopeObj; +#else /* JAVA_SPEC_VERSION >= 22 */ + scopeFound = JNI_TRUE; break; +#endif /* JAVA_SPEC_VERSION >= 22 */ } } @@ -112,7 +99,9 @@ Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject insta } vmFuncs->internalExitVMToJNI(currentThread); - return scopeNotFound; +#if JAVA_SPEC_VERSION <= 21 + return !scopeFound; +#endif /* JAVA_SPEC_VERSION <= 21 */ } #endif /* JAVA_SPEC_VERSION >= 16 */ diff --git a/runtime/oti/j9consts.h b/runtime/oti/j9consts.h index 8726297f66a..635e6c12ca3 100644 --- a/runtime/oti/j9consts.h +++ b/runtime/oti/j9consts.h @@ -203,7 +203,7 @@ extern "C" { #define J9_PUBLIC_FLAGS_THREAD_PARKED 0x20000 #define J9_PUBLIC_FLAGS_EXCLUSIVE_SET_NOT_SAFE 0x40000 #define J9_PUBLIC_FLAGS_THREAD_TIMED 0x80000 -#define J9_PUBLIC_FLAGS_UNUSED_0x100000 0x100000 +#define J9_PUBLIC_FLAGS_CLOSE_SCOPE 0x100000 #define J9_PUBLIC_FLAGS_HALT_THREAD_FOR_CHECKPOINT 0x200000 #define J9_PUBLIC_FLAGS_JNI_CRITICAL_REGION 0x400000 #define J9_PUBLIC_FLAGS_POP_FRAMES_INTERRUPT 0x800000 diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index cdd48847b81..453b57cb688 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -5090,6 +5090,7 @@ typedef struct J9InternalVMFunctions { float (JNICALL *native2InterpJavaUpcallF)(struct J9UpcallMetaData *data, void *argsListPointer); double (JNICALL *native2InterpJavaUpcallD)(struct J9UpcallMetaData *data, void *argsListPointer); U_8 * (JNICALL *native2InterpJavaUpcallStruct)(struct J9UpcallMetaData *data, void *argsListPointer); + BOOLEAN (*hasMemoryScope)(struct J9VMThread *walkThread, j9object_t scope); #endif /* JAVA_SPEC_VERSION >= 16 */ #if JAVA_SPEC_VERSION >= 19 void (*copyFieldsFromContinuation)(struct J9VMThread *currentThread, struct J9VMThread *vmThread, struct J9VMEntryLocalStorage *els, struct J9VMContinuation *continuation); @@ -5456,6 +5457,10 @@ typedef struct J9VMThread { #if JAVA_SPEC_VERSION >= 21 BOOLEAN isInCriticalDownCall; #endif /* JAVA_SPEC_VERSION >= 21 */ +#if JAVA_SPEC_VERSION >= 22 + j9object_t scopedError; + j9object_t closeScopeObj; +#endif /* JAVA_SPEC_VERSION >= 22 */ } J9VMThread; #define J9VMTHREAD_ALIGNMENT 0x100 diff --git a/runtime/oti/jclprots.h b/runtime/oti/jclprots.h index e5894689515..e48370e292e 100644 --- a/runtime/oti/jclprots.h +++ b/runtime/oti/jclprots.h @@ -1285,12 +1285,16 @@ Java_jdk_internal_foreign_abi_UpcallStubs_freeUpcallStub0(JNIEnv *env, jclass cl void JNICALL Java_jdk_internal_misc_ScopedMemoryAccess_registerNatives(JNIEnv *env, jclass clazz); +#if JAVA_SPEC_VERSION >= 22 +void JNICALL +Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject error); +#elif (JAVA_SPEC_VERSION >= 19) && (JAVA_SPEC_VERSION < 22) /* JAVA_SPEC_VERSION >= 22 */ jboolean JNICALL -#if JAVA_SPEC_VERSION >= 19 Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope); -#else /* JAVA_SPEC_VERSION >= 19 */ +#else /* JAVA_SPEC_VERSION >= 22 */ +jboolean JNICALL Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject exception); -#endif /* JAVA_SPEC_VERSION >= 19 */ +#endif /* JAVA_SPEC_VERSION >= 22 */ #endif /* JAVA_SPEC_VERSION >= 16 */ #if defined(J9VM_OPT_CRIU_SUPPORT) diff --git a/runtime/oti/vm_api.h b/runtime/oti/vm_api.h index f5eeea30650..68612327e18 100644 --- a/runtime/oti/vm_api.h +++ b/runtime/oti/vm_api.h @@ -5267,6 +5267,16 @@ native2InterpJavaUpcallD(J9UpcallMetaData *data, void *argsListPointer); U_8 * JNICALL native2InterpJavaUpcallStruct(J9UpcallMetaData *data, void *argsListPointer); +/** + * @brief Check if the memory's scope exists on the stack of the thread. + * + * @param[in] walkThread the J9VMThread to be walked + * @param[in] scope the object searched during the walk + * + * @return true if scope is found, false if not + */ +BOOLEAN +hasMemoryScope(J9VMThread *walkThread, j9object_t scope); #endif /* JAVA_SPEC_VERSION >= 16 */ #ifdef __cplusplus diff --git a/runtime/vm/AsyncMessageHandler.cpp b/runtime/vm/AsyncMessageHandler.cpp index 4f7e4f405cd..f886b57e7db 100644 --- a/runtime/vm/AsyncMessageHandler.cpp +++ b/runtime/vm/AsyncMessageHandler.cpp @@ -33,6 +33,74 @@ extern "C" { +#if JAVA_SPEC_VERSION >= 16 +/** + * Frame walk function, which is used with hasMemoryScope. + * + * @param[in] vmThread the J9VMThread + * @param[in] walkState the stack walk state + * + * @return J9_STACKWALK_STOP_ITERATING to stop iterating, and + * J9_STACKWALK_KEEP_ITERATING to continue iterating + */ +static UDATA +closeScope0FrameWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState) +{ + if (*(bool *)walkState->userData2) { + /* Scope has been found. */ + return J9_STACKWALK_STOP_ITERATING; + } + return J9_STACKWALK_KEEP_ITERATING; +} + +/** + * O-slot walk function, which is used with hasMemoryScope. + * + * @param[in] vmThread the J9VMThread + * @param[in] walkState the stack walk state + * @param[in] slot the O-slot pointer + * @param[in] stackLocation the stack location + */ +static void +closeScope0OSlotWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState, j9object_t *slot, const void *stackLocation) +{ + J9Method *method = walkState->method; + if (NULL != method) { + J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method); + if (NULL != romMethod && J9ROMMETHOD_HAS_EXTENDED_MODIFIERS(romMethod)) { + U_32 extraModifiers = getExtendedModifiersDataFromROMMethod(romMethod); + if (J9ROMMETHOD_HAS_SCOPED_ANNOTATION(extraModifiers)) { + if (*slot == walkState->userData1) { + *(bool *)walkState->userData2 = true; + } + } + } + } +} + +BOOLEAN +hasMemoryScope(J9VMThread *walkThread, j9object_t scope) +{ + bool scopeFound = false; + + if (NULL != scope) { + J9StackWalkState walkState; + + walkState.walkThread = walkThread; + walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_ITERATE_O_SLOTS; + walkState.skipCount = 0; + walkState.userData1 = (void *)scope; + walkState.userData2 = (void *)&scopeFound; + walkState.frameWalkFunction = closeScope0FrameWalkFunction; + walkState.objectSlotWalkFunction = closeScope0OSlotWalkFunction; + + walkThread->javaVM->walkStackFrames(walkThread, &walkState); + } + + return scopeFound; +} +#endif /* JAVA_SPEC_VERSION >= 16 */ + void clearAsyncEventFlags(J9VMThread *vmThread, UDATA flags) { @@ -72,6 +140,27 @@ javaCheckAsyncMessages(J9VMThread *currentThread, UDATA throwExceptions) result = J9_CHECK_ASYNC_POP_FRAMES; break; } +#if JAVA_SPEC_VERSION >= 22 + /* Check for a close scope request. */ + if (J9_ARE_ANY_BITS_SET(publicFlags, J9_PUBLIC_FLAGS_CLOSE_SCOPE)) { + if (hasMemoryScope(currentThread, currentThread->closeScopeObj)) { + if (throwExceptions) { + currentThread->currentException = currentThread->scopedError; + currentThread->scopedError = NULL; + currentThread->closeScopeObj = NULL; + clearEventFlag(currentThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE); + result = J9_CHECK_ASYNC_THROW_EXCEPTION; + } else { + VM_VMHelpers::indicateAsyncMessagePending(currentThread); + } + } else { + currentThread->scopedError = NULL; + currentThread->closeScopeObj = NULL; + clearEventFlag(currentThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE); + } + break; + } +#endif /* JAVA_SPEC_VERSION >= 22 */ /* Check for a thread halt request */ if (J9_ARE_ANY_BITS_SET(publicFlags, J9_PUBLIC_FLAGS_RELEASE_ACCESS_REQUIRED_MASK)) { Assert_VM_false(J9_ARE_ANY_BITS_SET(publicFlags, J9_PUBLIC_FLAGS_NOT_AT_SAFE_POINT)); diff --git a/runtime/vm/intfunc.c b/runtime/vm/intfunc.c index 9c4f850ee99..8404e22595f 100644 --- a/runtime/vm/intfunc.c +++ b/runtime/vm/intfunc.c @@ -438,6 +438,7 @@ J9InternalVMFunctions J9InternalFunctions = { native2InterpJavaUpcallF, native2InterpJavaUpcallD, native2InterpJavaUpcallStruct, + hasMemoryScope, #endif /* JAVA_SPEC_VERSION >= 16 */ #if JAVA_SPEC_VERSION >= 19 copyFieldsFromContinuation, From 0de98105c0e89689134fb0fe0beab60315e36c0e Mon Sep 17 00:00:00 2001 From: Babneet Singh Date: Mon, 29 Apr 2024 15:17:14 -0400 Subject: [PATCH 2/2] ScopedMemoryAccess closeScope0 synchronization There are gaps where async exceptions are not processed in time (e.g. JIT compiled code in a loop). Threads will wait in closeScope0 until J9VMThread->scopedError (async exception) is transferred to J9VMThread->currentException. The wait prevents a MemorySession to be closed until no more operations are being performed on it. Related: #13211 Signed-off-by: Babneet Singh --- .../jdk_internal_misc_ScopedMemoryAccess.cpp | 17 +++++++++++++++++ runtime/oti/j9nonbuilder.h | 4 ++++ runtime/vm/AsyncMessageHandler.cpp | 17 +++++++++++++++++ runtime/vm/jvminit.c | 7 +++++++ runtime/vm/vmthinit.c | 4 ++++ 5 files changed, 49 insertions(+) diff --git a/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp b/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp index e61a595e393..4eac6a65891 100644 --- a/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp +++ b/runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp @@ -86,6 +86,8 @@ Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject insta setHaltFlag(walkThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE); walkThread->scopedError = errorObj; walkThread->closeScopeObj = closeScopeObj; + /* Atomic add is not needed since exclusive VM access has been acquired. */ + vm->closeScopeNotifyCount += 1; #else /* JAVA_SPEC_VERSION >= 22 */ scopeFound = JNI_TRUE; break; @@ -99,6 +101,21 @@ Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject insta } vmFuncs->internalExitVMToJNI(currentThread); + +#if JAVA_SPEC_VERSION >= 22 + /* There are gaps where async exceptions are not processed in time + * (e.g. JIT compiled code in a loop). Wait until J9VMThread->scopedError + * (async exception) is transferred to J9VMThread->currentException. The + * wait prevents a MemorySession to be closed until no more operations are + * being performed on it. + */ + omrthread_monitor_enter(vm->closeScopeMutex); + while (0 != vm->closeScopeNotifyCount) { + omrthread_monitor_wait(vm->closeScopeMutex); + } + omrthread_monitor_exit(vm->closeScopeMutex); +#endif /* JAVA_SPEC_VERSION >= 22 */ + #if JAVA_SPEC_VERSION <= 21 return !scopeFound; #endif /* JAVA_SPEC_VERSION <= 21 */ diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index 453b57cb688..75418d924d5 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -6049,6 +6049,10 @@ typedef struct J9JavaVM { /* Pool for allocating J9MemberNameListNode. */ struct J9Pool *memberNameListNodePool; #endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */ +#if JAVA_SPEC_VERSION >= 22 + omrthread_monitor_t closeScopeMutex; + UDATA closeScopeNotifyCount; +#endif /* JAVA_SPEC_VERSION >= 22 */ } J9JavaVM; #define J9VM_PHASE_STARTUP 1 diff --git a/runtime/vm/AsyncMessageHandler.cpp b/runtime/vm/AsyncMessageHandler.cpp index f886b57e7db..b45b54a2d89 100644 --- a/runtime/vm/AsyncMessageHandler.cpp +++ b/runtime/vm/AsyncMessageHandler.cpp @@ -143,6 +143,7 @@ javaCheckAsyncMessages(J9VMThread *currentThread, UDATA throwExceptions) #if JAVA_SPEC_VERSION >= 22 /* Check for a close scope request. */ if (J9_ARE_ANY_BITS_SET(publicFlags, J9_PUBLIC_FLAGS_CLOSE_SCOPE)) { + bool notifyThreads = false; if (hasMemoryScope(currentThread, currentThread->closeScopeObj)) { if (throwExceptions) { currentThread->currentException = currentThread->scopedError; @@ -150,6 +151,7 @@ javaCheckAsyncMessages(J9VMThread *currentThread, UDATA throwExceptions) currentThread->closeScopeObj = NULL; clearEventFlag(currentThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE); result = J9_CHECK_ASYNC_THROW_EXCEPTION; + notifyThreads = true; } else { VM_VMHelpers::indicateAsyncMessagePending(currentThread); } @@ -157,6 +159,21 @@ javaCheckAsyncMessages(J9VMThread *currentThread, UDATA throwExceptions) currentThread->scopedError = NULL; currentThread->closeScopeObj = NULL; clearEventFlag(currentThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE); + notifyThreads = true; + } + if (notifyThreads) { + J9JavaVM *vm = currentThread->javaVM; + /* Notify all threads that are waiting in ScopedMemoryAccess closeScope0 + * to continue since the MemorySession(s) will no longer be used and it + * is safe to close them. + */ + omrthread_monitor_enter(vm->closeScopeMutex); + Assert_VM_true(vm->closeScopeNotifyCount > 0); + vm->closeScopeNotifyCount -= 1; + if (0 == vm->closeScopeNotifyCount) { + omrthread_monitor_notify_all(vm->closeScopeMutex); + } + omrthread_monitor_exit(vm->closeScopeMutex); } break; } diff --git a/runtime/vm/jvminit.c b/runtime/vm/jvminit.c index 93ef0467763..540cfb1aed4 100644 --- a/runtime/vm/jvminit.c +++ b/runtime/vm/jvminit.c @@ -1025,6 +1025,13 @@ freeJavaVM(J9JavaVM * vm) } #endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ +#if JAVA_SPEC_VERSION >= 22 + if (NULL != vm->closeScopeMutex) { + omrthread_monitor_destroy(vm->closeScopeMutex); + vm->closeScopeMutex = NULL; + } +#endif /* JAVA_SPEC_VERSION >= 22 */ + j9mem_free_memory(vm); if (NULL != tmpLib->self_handle) { diff --git a/runtime/vm/vmthinit.c b/runtime/vm/vmthinit.c index 1ff64e2b4b5..e7ea6fe7db3 100644 --- a/runtime/vm/vmthinit.c +++ b/runtime/vm/vmthinit.c @@ -99,6 +99,10 @@ UDATA initializeVMThreading(J9JavaVM *vm) omrthread_monitor_init_with_name(&vm->delayedLockingOperationsMutex, 0, "Delayed locking operations mutex") || #endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ +#if JAVA_SPEC_VERSION >= 22 + omrthread_monitor_init_with_name(&vm->closeScopeMutex, 0, "ScopedMemoryAccess closeScope0 mutex") || +#endif /* JAVA_SPEC_VERSION >= 22 */ + initializeMonitorTable(vm) ) {