Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(0.42) Prevent requesting exclusive, if already acquired #18629

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions runtime/jvmti/jvmtiClass.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,10 +1233,14 @@ redefineClassesCommon(jvmtiEnv* env,
/* Eliminate dark matter so that none will be encountered in prepareToFixMemberNames(). */
UDATA savedAllowUserHeapWalkFlag = vm->requiredDebugAttributes & J9VM_DEBUG_ATTRIBUTE_ALLOW_USER_HEAP_WALK;
vm->requiredDebugAttributes |= J9VM_DEBUG_ATTRIBUTE_ALLOW_USER_HEAP_WALK;
/* J9MMCONSTANT_EXPLICIT_GC_RASDUMP_COMPACT allows the GC to run while the current thread is holding
* exclusive VM access.
*/
vm->memoryManagerFunctions->j9gc_modron_global_collect_with_overrides(currentThread, J9MMCONSTANT_EXPLICIT_GC_RASDUMP_COMPACT);

/* This is to help with Metronome to avoid requesting Exclusive if we already have SafePoint, which may not look as Exclusive to the requester thread */
vm->alreadyHaveExclusive = TRUE;

vm->memoryManagerFunctions->j9gc_modron_global_collect_with_overrides(currentThread, J9MMCONSTANT_EXPLICIT_GC_EXCLUSIVE_VMACCESS_ALREADY_ACQUIRED);

vm->alreadyHaveExclusive = FALSE;

if (0 == savedAllowUserHeapWalkFlag) {
/* Clear the flag to restore its original value. */
vm->requiredDebugAttributes &= ~J9VM_DEBUG_ATTRIBUTE_ALLOW_USER_HEAP_WALK;
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -5911,6 +5911,7 @@ typedef struct J9JavaVM {
UDATA addModulesCount;
UDATA safePointState;
UDATA safePointResponseCount;
BOOLEAN alreadyHaveExclusive;
struct J9VMRuntimeStateListener vmRuntimeStateListener;
#if defined(J9VM_INTERP_ATOMIC_FREE_JNI_USES_FLUSH)
#if defined(J9UNIX) || defined(AIXPPC)
Expand Down
25 changes: 24 additions & 1 deletion runtime/vm/VMAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,11 @@ acquireExclusiveVMAccessFromExternalThread(J9JavaVM * vm)
UDATA vmResponsesExpected = 0;
UDATA jniResponsesExpected = 0;

/* If exclusive has already been acquired, nothing need be done here */
if (vm->alreadyHaveExclusive) {
return;
}

synchronizeRequestsFromExternalThread(vm, TRUE);

/* Post the halt request to all threads */
Expand Down Expand Up @@ -836,6 +841,12 @@ void
releaseExclusiveVMAccessFromExternalThread(J9JavaVM * vm)
{
J9VMThread * currentThread;

/* If exclusive has already been acquired, nothing need be done here */
if (vm->alreadyHaveExclusive) {
return;
}

Assert_VM_true(J9_XACCESS_EXCLUSIVE == vm->exclusiveAccessState);

/* Acquire these monitors in the same order as in allocateVMThread to prevent deadlock */
Expand Down Expand Up @@ -913,6 +924,11 @@ requestExclusiveVMAccessMetronomeTemp(J9JavaVM *vm, UDATA block, UDATA *vmRespon
UDATA jniResponsesExpected = 0;
*gcPriority = J9THREAD_PRIORITY_MAX;

/* If exclusive has already been acquired, nothing need be done here */
if (vm->alreadyHaveExclusive) {
return FALSE;
}

/* Check if another party is requesting X access already. */
if (FALSE == synchronizeRequestsFromExternalThread(vm, block)) {
/* Yes, there was another party requesting X access, but because we did not want to block,
Expand Down Expand Up @@ -1010,7 +1026,14 @@ waitForExclusiveVMAccessMetronome(J9VMThread * vmThread, UDATA responsesRequired
void
waitForExclusiveVMAccessMetronomeTemp(J9VMThread * vmThread, UDATA vmResponsesRequired, UDATA jniResponsesRequired)
{
waitForResponseFromExternalThread(vmThread->javaVM, vmResponsesRequired, jniResponsesRequired);
J9JavaVM *vm = vmThread->javaVM;

/* If exclusive has already been acquired, nothing need be done here */
if (vm->alreadyHaveExclusive) {
return;
}

waitForResponseFromExternalThread(vm, vmResponsesRequired, jniResponsesRequired);

VM_VMAccess::backOffFromSafePoint(vmThread);

Expand Down