Path: blob/master/runtime/gc_glue_java/JNICriticalRegion.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "j9.h"2324#include "JNICriticalRegion.hpp"2526/**27* Re-acquire VM and/or JNI critical access as specified by the accessMask.28* This will block if another thread holds exclusive VM access.29*30* This function is intended for use with releaseAccess.31*32* @param vmThread the J9VMThread requesting access33* @param accessMask the types of access that were held34*/35void36MM_JNICriticalRegion::reacquireAccess(J9VMThread* vmThread, UDATA accessMask)37{38#if defined(J9VM_INTERP_ATOMIC_FREE_JNI)39// Current thread must have entered the VM before acquiring exclusive40Assert_MM_false(vmThread->inNative);41#endif /* J9VM_INTERP_ATOMIC_FREE_JNI */42if (J9_ARE_ANY_BITS_SET(vmThread->publicFlags, J9_PUBLIC_FLAGS_DEBUG_VM_ACCESS)) {43Assert_MM_true(J9_VM_FUNCTION(vmThread, currentVMThread)(vmThread->javaVM) == vmThread);44}4546Assert_MM_true(0 != (accessMask & (J9_PUBLIC_FLAGS_VM_ACCESS | J9_PUBLIC_FLAGS_JNI_CRITICAL_ACCESS)));47Assert_MM_true(0 == (accessMask & ~(J9_PUBLIC_FLAGS_VM_ACCESS | J9_PUBLIC_FLAGS_JNI_CRITICAL_ACCESS)));48omrthread_monitor_enter(vmThread->publicFlagsMutex);49Assert_MM_true(0 == (vmThread->publicFlags & (J9_PUBLIC_FLAGS_VM_ACCESS | J9_PUBLIC_FLAGS_JNI_CRITICAL_ACCESS)));50while (vmThread->publicFlags & J9_PUBLIC_FLAGS_HALT_THREAD_EXCLUSIVE) {51omrthread_monitor_wait(vmThread->publicFlagsMutex);52}5354if (0 != (accessMask & J9_PUBLIC_FLAGS_VM_ACCESS)) {55TRIGGER_J9HOOK_VM_ACQUIREVMACCESS(vmThread->javaVM->hookInterface, vmThread);5657/* Now that the hook has been invoked, allow inline VM access */58if (0 != (vmThread->publicFlags & J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS)) {59clearEventFlag(vmThread, J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS);60}61}6263VM_VMAccess::setPublicFlags(vmThread, accessMask);64omrthread_monitor_exit(vmThread->publicFlagsMutex);65}6667/**68* Release VM and/or JNI critical access. Record what was held in accessMask.69* This will respond to any pending exclusive VM access request in progress.70*71* This function is intended for use with reacquireAccess.72*73* @param vmThread the J9VMThread requesting access74* @param accessMask the types of access to re-acquire75*/76void77MM_JNICriticalRegion::releaseAccess(J9VMThread* vmThread, UDATA* accessMask)78{79#if defined(J9VM_INTERP_ATOMIC_FREE_JNI)80// Current thread must have entered the VM before acquiring exclusive81Assert_MM_false(vmThread->inNative);82#endif /* J9VM_INTERP_ATOMIC_FREE_JNI */83if (J9_ARE_ANY_BITS_SET(vmThread->publicFlags, J9_PUBLIC_FLAGS_DEBUG_VM_ACCESS)) {84Assert_MM_true(J9_VM_FUNCTION(vmThread, currentVMThread)(vmThread->javaVM) == vmThread);85}8687omrthread_monitor_enter(vmThread->publicFlagsMutex);88Assert_MM_true(0 != (vmThread->publicFlags & (J9_PUBLIC_FLAGS_VM_ACCESS | J9_PUBLIC_FLAGS_JNI_CRITICAL_ACCESS)));89UDATA currentAccess = vmThread->publicFlags & (J9_PUBLIC_FLAGS_VM_ACCESS | J9_PUBLIC_FLAGS_JNI_CRITICAL_ACCESS);90Assert_MM_true(0 != currentAccess);91VM_VMAccess::clearPublicFlags(vmThread, currentAccess);9293if (0 != (currentAccess & J9_PUBLIC_FLAGS_VM_ACCESS)) {94TRIGGER_J9HOOK_VM_RELEASEVMACCESS(vmThread->javaVM->hookInterface, vmThread);9596/* Now that the hook has been invoked, allow inline VM access */97if (0 != (vmThread->publicFlags & J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS)) {98clearEventFlag(vmThread, J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS);99}100}101102if(0 != (vmThread->publicFlags & J9_PUBLIC_FLAGS_HALT_THREAD_EXCLUSIVE)) {103J9JavaVM* vm = vmThread->javaVM;104PORT_ACCESS_FROM_JAVAVM(vm);105UDATA shouldRespond = FALSE;106107omrthread_monitor_enter(vm->exclusiveAccessMutex);108109U_64 timeNow = VM_VMAccess::updateExclusiveVMAccessStats(vmThread, vm, PORTLIB);110111if(0 != (currentAccess & J9_PUBLIC_FLAGS_VM_ACCESS)) {112if (!J9_ARE_ANY_BITS_SET(vmThread->publicFlags, J9_PUBLIC_FLAGS_NOT_COUNTED_BY_EXCLUSIVE)) {113--vm->exclusiveAccessResponseCount;114if(0 == vm->exclusiveAccessResponseCount) {115shouldRespond = TRUE;116}117}118}119if(0 != (currentAccess & J9_PUBLIC_FLAGS_JNI_CRITICAL_ACCESS)) {120--vm->jniCriticalResponseCount;121if(0 == vm->jniCriticalResponseCount) {122shouldRespond = TRUE;123}124}125if(shouldRespond) {126VM_VMAccess::respondToExclusiveRequest(vmThread, vm, PORTLIB, timeNow, J9_EXCLUSIVE_SLOW_REASON_JNICRITICAL);127}128omrthread_monitor_exit(vm->exclusiveAccessMutex);129}130131*accessMask = currentAccess;132omrthread_monitor_exit(vmThread->publicFlagsMutex);133}134135136