blob: e5f9c62a73ee3e24ed61bbadf12c0640618ce1eb [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26/*
27 * Copyright 2003 Wily Technology, Inc.
28 */
29
30#include <jni.h>
31#include <jvmti.h>
32
33#include "JPLISAssert.h"
34#include "Reentrancy.h"
35#include "JPLISAgent.h"
36
37/*
38 * This module provides some utility functions to support the "same thread" re-entrancy management.
39 * Uses JVMTI TLS to store a single bit per thread.
40 * Non-zero means the thread is already inside; zero means the thread is not inside.
41 */
42
43/*
44 * Local prototypes
45 */
46
47/* Wrapper around set that does the set then re-fetches to make sure it worked.
48 * Degenerates to a simple set when assertions are disabled.
49 * This routine is only here because of a bug in the JVMTI where set to 0 fails.
50 */
51jvmtiError
52confirmingTLSSet( jvmtiEnv * jvmtienv,
53 jthread thread,
54 const void * newValue);
55
56/* Confirmation routine only; used to assure that the TLS slot holds the value we expect it to. */
57void
58assertTLSValue( jvmtiEnv * jvmtienv,
59 jthread thread,
60 const void * expected);
61
62
63#define JPLIS_CURRENTLY_INSIDE_TOKEN ((void *) 0x7EFFC0BB)
64#define JPLIS_CURRENTLY_OUTSIDE_TOKEN ((void *) 0)
65
66
67jvmtiError
68confirmingTLSSet( jvmtiEnv * jvmtienv,
69 jthread thread,
70 const void * newValue) {
71 jvmtiError error;
72
73 error = (*jvmtienv)->SetThreadLocalStorage(
74 jvmtienv,
75 thread,
76 newValue);
77
78#if JPLISASSERT_ENABLEASSERTIONS
79 assertTLSValue( jvmtienv,
80 thread,
81 newValue);
82#endif
83
84 return error;
85}
86
87void
88assertTLSValue( jvmtiEnv * jvmtienv,
89 jthread thread,
90 const void * expected) {
91 jvmtiError error;
92 void * test = (void *) 0x99999999;
93
94 /* now check if we do a fetch we get what we wrote */
95 error = (*jvmtienv)->GetThreadLocalStorage(
96 jvmtienv,
97 thread,
98 &test);
99 jplis_assert(error == JVMTI_ERROR_NONE);
100 jplis_assert(test == expected);
101}
102
103jboolean
104tryToAcquireReentrancyToken( jvmtiEnv * jvmtienv,
105 jthread thread) {
106 jboolean result = JNI_FALSE;
107 jvmtiError error = JVMTI_ERROR_NONE;
108 void * storedValue = NULL;
109
110 error = (*jvmtienv)->GetThreadLocalStorage(
111 jvmtienv,
112 thread,
113 &storedValue);
114 jplis_assert(error == JVMTI_ERROR_NONE);
115 if ( error == JVMTI_ERROR_NONE ) {
116 /* if this thread is already inside, just return false and short-circuit */
117 if ( storedValue == JPLIS_CURRENTLY_INSIDE_TOKEN ) {
118 result = JNI_FALSE;
119 }
120 else {
121 /* stuff in the sentinel and return true */
122#if JPLISASSERT_ENABLEASSERTIONS
123 assertTLSValue( jvmtienv,
124 thread,
125 JPLIS_CURRENTLY_OUTSIDE_TOKEN);
126#endif
127 error = confirmingTLSSet ( jvmtienv,
128 thread,
129 JPLIS_CURRENTLY_INSIDE_TOKEN);
130 jplis_assert(error == JVMTI_ERROR_NONE);
131 if ( error != JVMTI_ERROR_NONE ) {
132 result = JNI_FALSE;
133 }
134 else {
135 result = JNI_TRUE;
136 }
137 }
138 }
139 return result;
140}
141
142
143void
144releaseReentrancyToken( jvmtiEnv * jvmtienv,
145 jthread thread) {
146 jvmtiError error = JVMTI_ERROR_NONE;
147
148/* assert we hold the token */
149#if JPLISASSERT_ENABLEASSERTIONS
150 assertTLSValue( jvmtienv,
151 thread,
152 JPLIS_CURRENTLY_INSIDE_TOKEN);
153#endif
154
155 error = confirmingTLSSet( jvmtienv,
156 thread,
157 JPLIS_CURRENTLY_OUTSIDE_TOKEN);
158 jplis_assert(error == JVMTI_ERROR_NONE);
159
160}