1 /*
2 * Copyright (c) 2004, 2018, Oracle and/or its affiliates. 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include "jvmti.h"
27 #include "agent_common.h"
28 #include "JVMTITools.h"
29
30 extern "C" {
31
32
33 #define PASSED 0
34 #define STATUS_FAILED 2
35 #define WAIT_START 100
36
37 static jvmtiEnv *jvmti = NULL;
38 static jvmtiCapabilities caps;
39 static jvmtiEventCallbacks callbacks;
40 static jrawMonitorID access_lock, wait_lock;
41 static jint result = PASSED;
42 static jboolean printdump = JNI_FALSE;
43 static jthread thr_ptr = NULL;
44 static jint wait_time = 0;
45 static jint state[] = {
46 JVMTI_THREAD_STATE_RUNNABLE,
47 JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
48 JVMTI_THREAD_STATE_IN_OBJECT_WAIT
49 };
50
printStateFlags(jint flags)51 void printStateFlags(jint flags) {
52 if (flags & JVMTI_THREAD_STATE_SUSPENDED)
53 printf(" JVMTI_THREAD_STATE_SUSPENDED");
54 if (flags & JVMTI_THREAD_STATE_INTERRUPTED)
55 printf(" JVMTI_THREAD_STATE_INTERRUPTED");
56 if (flags & JVMTI_THREAD_STATE_IN_NATIVE)
57 printf(" JVMTI_THREAD_STATE_IN_NATIVE");
58 printf(" (0x%0x)\n", flags);
59 }
60
VMInit(jvmtiEnv * jvmti_env,JNIEnv * env,jthread thr)61 void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) {
62 jvmtiError err;
63
64 err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
65 JVMTI_EVENT_THREAD_START, NULL);
66 if (err != JVMTI_ERROR_NONE) {
67 printf("Failed to enable THREAD_START event: %s (%d)\n",
68 TranslateError(err), err);
69 result = STATUS_FAILED;
70 }
71 }
72
73 void JNICALL
ThreadStart(jvmtiEnv * jvmti_env,JNIEnv * env,jthread thread)74 ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) {
75 jvmtiThreadInfo thrInfo;
76 jvmtiError err;
77
78 err = jvmti_env->RawMonitorEnter(access_lock);
79 if (err != JVMTI_ERROR_NONE) {
80 printf("(RawMonitorEnter) unexpected error: %s (%d)\n",
81 TranslateError(err), err);
82 result = STATUS_FAILED;
83 }
84
85 err = jvmti_env->GetThreadInfo(thread, &thrInfo);
86 if (err != JVMTI_ERROR_NONE) {
87 printf("(GetThreadInfo) unexpected error: %s (%d)\n",
88 TranslateError(err), err);
89 result = STATUS_FAILED;
90 }
91 if (thrInfo.name != NULL && strcmp(thrInfo.name, "thr1") == 0) {
92 thr_ptr = env->NewGlobalRef(thread);
93 if (printdump == JNI_TRUE) {
94 printf(">>> ThreadStart: \"%s\", 0x%p\n", thrInfo.name, thr_ptr);
95 }
96 }
97
98 err = jvmti_env->RawMonitorExit(access_lock);
99 if (err != JVMTI_ERROR_NONE) {
100 printf("(RawMonitorExit) unexpected error: %s (%d)\n",
101 TranslateError(err), err);
102 result = STATUS_FAILED;
103 }
104 }
105
106 #ifdef STATIC_BUILD
Agent_OnLoad_thrstat002(JavaVM * jvm,char * options,void * reserved)107 JNIEXPORT jint JNICALL Agent_OnLoad_thrstat002(JavaVM *jvm, char *options, void *reserved) {
108 return Agent_Initialize(jvm, options, reserved);
109 }
Agent_OnAttach_thrstat002(JavaVM * jvm,char * options,void * reserved)110 JNIEXPORT jint JNICALL Agent_OnAttach_thrstat002(JavaVM *jvm, char *options, void *reserved) {
111 return Agent_Initialize(jvm, options, reserved);
112 }
JNI_OnLoad_thrstat002(JavaVM * jvm,char * options,void * reserved)113 JNIEXPORT jint JNI_OnLoad_thrstat002(JavaVM *jvm, char *options, void *reserved) {
114 return JNI_VERSION_1_8;
115 }
116 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)117 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
118 jint res;
119 jvmtiError err;
120
121 if (options != NULL && strcmp(options, "printdump") == 0) {
122 printdump = JNI_TRUE;
123 }
124
125 res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
126 if (res != JNI_OK || jvmti == NULL) {
127 printf("Wrong result of a valid call to GetEnv !\n");
128 return JNI_ERR;
129 }
130
131 err = jvmti->GetPotentialCapabilities(&caps);
132 if (err != JVMTI_ERROR_NONE) {
133 printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",
134 TranslateError(err), err);
135 return JNI_ERR;
136 }
137
138 err = jvmti->AddCapabilities(&caps);
139 if (err != JVMTI_ERROR_NONE) {
140 printf("(AddCapabilities) unexpected error: %s (%d)\n",
141 TranslateError(err), err);
142 return JNI_ERR;
143 }
144
145 err = jvmti->GetCapabilities(&caps);
146 if (err != JVMTI_ERROR_NONE) {
147 printf("(GetCapabilities) unexpected error: %s (%d)\n",
148 TranslateError(err), err);
149 return JNI_ERR;
150 }
151
152 if (!caps.can_suspend) {
153 printf("Warning: suspend/resume is not implemented\n");
154 }
155
156 err = jvmti->CreateRawMonitor("_access_lock", &access_lock);
157 if (err != JVMTI_ERROR_NONE) {
158 printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
159 TranslateError(err), err);
160 return JNI_ERR;
161 }
162
163 err = jvmti->CreateRawMonitor("_wait_lock", &wait_lock);
164 if (err != JVMTI_ERROR_NONE) {
165 printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
166 TranslateError(err), err);
167 return JNI_ERR;
168 }
169
170 callbacks.VMInit = &VMInit;
171 callbacks.ThreadStart = &ThreadStart;
172 err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
173 if (err != JVMTI_ERROR_NONE) {
174 printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
175 TranslateError(err), err);
176 return JNI_ERR;
177 }
178
179 err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
180 JVMTI_EVENT_VM_INIT, NULL);
181 if (err != JVMTI_ERROR_NONE) {
182 printf("Failed to enable VM_INIT event: %s (%d)\n",
183 TranslateError(err), err);
184 result = STATUS_FAILED;
185 }
186
187 return JNI_OK;
188 }
189
190 JNIEXPORT void JNICALL
Java_nsk_jvmti_GetThreadState_thrstat002_init(JNIEnv * env,jclass cls,jint waitTime)191 Java_nsk_jvmti_GetThreadState_thrstat002_init(JNIEnv *env, jclass cls,
192 jint waitTime) {
193 wait_time = waitTime * 60000;
194 }
195
wait_for(jint millis)196 void wait_for(jint millis) {
197 jvmtiError err;
198
199 err = jvmti->RawMonitorEnter(wait_lock);
200 if (err != JVMTI_ERROR_NONE) {
201 printf("(RawMonitorEnter#check) unexpected error: %s (%d)\n",
202 TranslateError(err), err);
203 result = STATUS_FAILED;
204 }
205 err = jvmti->RawMonitorWait(wait_lock, (jlong)millis);
206 if (err != JVMTI_ERROR_NONE) {
207 printf("(RawMonitorWait#check) unexpected error: %s (%d)\n",
208 TranslateError(err), err);
209 result = STATUS_FAILED;
210 }
211 err = jvmti->RawMonitorExit(wait_lock);
212 if (err != JVMTI_ERROR_NONE) {
213 printf("(RawMonitorExit#check) unexpected error: %s (%d)\n",
214 TranslateError(err), err);
215 result = STATUS_FAILED;
216 }
217 }
218
219 JNIEXPORT void JNICALL
Java_nsk_jvmti_GetThreadState_thrstat002_checkStatus(JNIEnv * env,jclass cls,jint statInd,jboolean suspended)220 Java_nsk_jvmti_GetThreadState_thrstat002_checkStatus(JNIEnv *env, jclass cls,
221 jint statInd, jboolean suspended) {
222 jint thrState;
223 jint suspState = -1;
224 jint right_stat = (suspended ? JVMTI_THREAD_STATE_SUSPENDED : 0);
225 jvmtiError right_ans = (suspended ? JVMTI_ERROR_THREAD_SUSPENDED : JVMTI_ERROR_NONE);
226 const char *suspStr = (suspended ? ", suspended" : "");
227 jvmtiError err;
228 jint millis;
229 jboolean timeout_is_reached;
230 unsigned int waited_millis;
231
232 if (jvmti == NULL) {
233 printf("JVMTI client was not properly loaded!\n");
234 result = STATUS_FAILED;
235 return;
236 }
237
238 if (thr_ptr == NULL) {
239 printf("Missing thread \"thr1\" start event\n");
240 result = STATUS_FAILED;
241 return;
242 }
243
244 if (!caps.can_suspend) {
245 return;
246 }
247
248 printf("START checkStatus for \"thr1\" (0x%p%s), check state: %s\n",
249 thr_ptr, suspStr, TranslateState(state[statInd]));
250
251 timeout_is_reached = JNI_TRUE;
252 for (millis = WAIT_START, waited_millis=0; millis < wait_time; millis <<= 1) {
253 err = jvmti->GetThreadState(thr_ptr, &thrState);
254 if (err != JVMTI_ERROR_NONE) {
255 printf("(GetThreadState#%d) unexpected error: %s (%d)\n",
256 statInd, TranslateError(err), err);
257 result = STATUS_FAILED;
258 timeout_is_reached = JNI_FALSE;
259 break;
260 }
261 suspState = thrState & JVMTI_THREAD_STATE_SUSPENDED;
262 if (suspended || (thrState & JVMTI_THREAD_STATE_RUNNABLE) == 0 ||
263 (state[statInd] == JVMTI_THREAD_STATE_RUNNABLE)) {
264 timeout_is_reached = JNI_FALSE;
265 break;
266 }
267
268 waited_millis += millis;
269 wait_for(millis);
270 }
271
272 if (printdump == JNI_TRUE) {
273 printf(">>> thread \"thr1\" (0x%p) state: %s (%d)\n",
274 thr_ptr, TranslateState(thrState), thrState);
275 printf(">>>\tflags:");
276 printStateFlags(suspState);
277 }
278
279 if (timeout_is_reached == JNI_TRUE) {
280 printf("Error: timeout (%d secs) has been reached\n", waited_millis/1000);
281 }
282 if ((thrState & state[statInd]) == 0) {
283 printf("Wrong thread \"thr1\" (0x%p%s) state:\n", thr_ptr, suspStr);
284 printf(" expected: %s (%d)\n",
285 TranslateState(state[statInd]), state[statInd]);
286 printf(" actual: %s (%d)\n",
287 TranslateState(thrState), thrState);
288 result = STATUS_FAILED;
289 }
290 if (suspState != right_stat) {
291 printf("Wrong thread \"thr1\" (0x%p%s) state flags:\n",
292 thr_ptr, suspStr);
293 printf(" expected:");
294 printStateFlags(right_stat);
295 printf(" actual:");
296 printStateFlags(suspState);
297 result = STATUS_FAILED;
298 }
299
300 err = jvmti->SuspendThread(thr_ptr);
301 if (err != right_ans) {
302 printf("Wrong result of SuspendThread() for \"thr1\" (0x%p%s):\n",
303 thr_ptr, suspStr);
304 printf(" expected: %s (%d), actual: %s (%d)\n",
305 TranslateError(right_ans), right_ans, TranslateError(err), err);
306 result = STATUS_FAILED;
307 }
308
309 if (!suspended) {
310 // wait till thread is not suspended
311 timeout_is_reached = JNI_TRUE;
312 for (millis = WAIT_START, waited_millis=0; millis < wait_time; millis <<= 1) {
313 waited_millis += millis;
314 wait_for(millis);
315 err = jvmti->GetThreadState(thr_ptr, &thrState);
316 if (err != JVMTI_ERROR_NONE) {
317 printf("(GetThreadState#%d,after) unexpected error: %s (%d)\n",
318 statInd, TranslateError(err), err);
319 timeout_is_reached = JNI_FALSE;
320 result = STATUS_FAILED;
321 break;
322 }
323 suspState = thrState & JVMTI_THREAD_STATE_SUSPENDED;
324 if (suspState) {
325 timeout_is_reached = JNI_FALSE;
326 break;
327 }
328 }
329
330 if (timeout_is_reached == JNI_TRUE) {
331 printf("Error: timeout (%d secs) has been reached\n", waited_millis/1000);
332 }
333 if ((thrState & state[statInd]) == 0) {
334 printf("Wrong thread \"thr1\" (0x%p) state after SuspendThread:\n",
335 thr_ptr);
336 printf(" expected: %s (%d)\n",
337 TranslateState(state[statInd]), state[statInd]);
338 printf(" actual: %s (%d)\n",
339 TranslateState(thrState), thrState);
340 result = STATUS_FAILED;
341 }
342 if (suspState != JVMTI_THREAD_STATE_SUSPENDED) {
343 printf("Wrong thread \"thr1\" (0x%p) state flags", thr_ptr);
344 printf(" after SuspendThread:\n");
345 printf(" expected:");
346 printStateFlags(JVMTI_THREAD_STATE_SUSPENDED);
347 printf(" actual:");
348 printStateFlags(suspState);
349 result = STATUS_FAILED;
350 }
351 err = jvmti->ResumeThread(thr_ptr);
352 if (err != JVMTI_ERROR_NONE) {
353 printf("(ResumeThread#%d) unexpected error: %s (%d)\n",
354 statInd, TranslateError(err), err);
355 result = STATUS_FAILED;
356 }
357 }
358 }
359
360 JNIEXPORT jint JNICALL
Java_nsk_jvmti_GetThreadState_thrstat002_getRes(JNIEnv * env,jclass cls)361 Java_nsk_jvmti_GetThreadState_thrstat002_getRes(JNIEnv *env, jclass cls) {
362 return result;
363 }
364
365 }
366