Path: blob/master/src/java.instrument/share/native/libinstrument/Reentrancy.c
41149 views
/*1* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* Copyright 2003 Wily Technology, Inc.27*/2829#include <jni.h>30#include <jvmti.h>3132#include "JPLISAssert.h"33#include "Reentrancy.h"34#include "JPLISAgent.h"3536/*37* This module provides some utility functions to support the "same thread" re-entrancy management.38* Uses JVMTI TLS to store a single bit per thread.39* Non-zero means the thread is already inside; zero means the thread is not inside.40*/4142/*43* Local prototypes44*/4546/* Wrapper around set that does the set then re-fetches to make sure it worked.47* Degenerates to a simple set when assertions are disabled.48* This routine is only here because of a bug in the JVMTI where set to 0 fails.49*/50jvmtiError51confirmingTLSSet( jvmtiEnv * jvmtienv,52jthread thread,53const void * newValue);5455/* Confirmation routine only; used to assure that the TLS slot holds the value we expect it to. */56void57assertTLSValue( jvmtiEnv * jvmtienv,58jthread thread,59const void * expected);606162#define JPLIS_CURRENTLY_INSIDE_TOKEN ((void *) 0x7EFFC0BB)63#define JPLIS_CURRENTLY_OUTSIDE_TOKEN ((void *) 0)646566jvmtiError67confirmingTLSSet( jvmtiEnv * jvmtienv,68jthread thread,69const void * newValue) {70jvmtiError error;7172error = (*jvmtienv)->SetThreadLocalStorage(73jvmtienv,74thread,75newValue);76check_phase_ret_blob(error, error);7778#if JPLISASSERT_ENABLEASSERTIONS79assertTLSValue( jvmtienv,80thread,81newValue);82#endif8384return error;85}8687void88assertTLSValue( jvmtiEnv * jvmtienv,89jthread thread,90const void * expected) {91jvmtiError error;92void * test = (void *) 0x99999999ULL;9394/* now check if we do a fetch we get what we wrote */95error = (*jvmtienv)->GetThreadLocalStorage(96jvmtienv,97thread,98&test);99check_phase_ret(error);100jplis_assert(error == JVMTI_ERROR_NONE);101jplis_assert(test == expected);102}103104jboolean105tryToAcquireReentrancyToken( jvmtiEnv * jvmtienv,106jthread thread) {107jboolean result = JNI_FALSE;108jvmtiError error = JVMTI_ERROR_NONE;109void * storedValue = NULL;110111error = (*jvmtienv)->GetThreadLocalStorage(112jvmtienv,113thread,114&storedValue);115check_phase_ret_false(error);116jplis_assert(error == JVMTI_ERROR_NONE);117if ( error == JVMTI_ERROR_NONE ) {118/* if this thread is already inside, just return false and short-circuit */119if ( storedValue == JPLIS_CURRENTLY_INSIDE_TOKEN ) {120result = JNI_FALSE;121}122else {123/* stuff in the sentinel and return true */124#if JPLISASSERT_ENABLEASSERTIONS125assertTLSValue( jvmtienv,126thread,127JPLIS_CURRENTLY_OUTSIDE_TOKEN);128#endif129error = confirmingTLSSet ( jvmtienv,130thread,131JPLIS_CURRENTLY_INSIDE_TOKEN);132check_phase_ret_false(error);133jplis_assert(error == JVMTI_ERROR_NONE);134if ( error != JVMTI_ERROR_NONE ) {135result = JNI_FALSE;136}137else {138result = JNI_TRUE;139}140}141}142return result;143}144145146void147releaseReentrancyToken( jvmtiEnv * jvmtienv,148jthread thread) {149jvmtiError error = JVMTI_ERROR_NONE;150151/* assert we hold the token */152#if JPLISASSERT_ENABLEASSERTIONS153assertTLSValue( jvmtienv,154thread,155JPLIS_CURRENTLY_INSIDE_TOKEN);156#endif157158error = confirmingTLSSet( jvmtienv,159thread,160JPLIS_CURRENTLY_OUTSIDE_TOKEN);161check_phase_ret(error);162jplis_assert(error == JVMTI_ERROR_NONE);163164}165166167