102 | thr_resume_lock.enter |
103 | thr_resume_lock.notify |
104 | thr_resume_lock.exit |
105 | | ... check next_thread state
106 | | thr_resume_lock.exit
107 | thr_start_lock.exit |
108 | thr_event_lock.exit
109
110
111 */
112
113 static void JNICALL
114 debug_agent(jvmtiEnv* jvmti, JNIEnv* jni, void *p) {
115 JNIEnv *env = jni;
116 jint thrStat;
117 jobject temp;
118
119 /* Notify VMInit callback as well as ThreadStart callback (if any)
120 * that agent thread has been started
121 */
122 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti, agent_start_lock))) {
123 result = STATUS_FAILED;
124 NSK_COMPLAIN0("[agent] failed to acquire agent_start_lock\n");
125 }
126
127 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorNotifyAll, jvmti, agent_start_lock))) {
128 result = STATUS_FAILED;
129 NSK_COMPLAIN0("[agent] failed to notify about agent_start_lock\n");
130 }
131
132 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti, agent_start_lock))) {
133 result = STATUS_FAILED;
134 NSK_COMPLAIN0("[agent] failed to release agent_start_lock\n");
135 }
136
137 NSK_DISPLAY0(">>> [agent] agent created\n");
138
139 debug_agent_started = JNI_TRUE;
140
141 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti, thr_start_lock))) {
142 result = STATUS_FAILED;
143 NSK_COMPLAIN0("[agent] failed to enter thr_start_lock\n");
144 }
145
146 while (terminate_debug_agent != JNI_TRUE) {
147
148 if (next_thread == NULL ) {
149 /* wait till new thread will be created and started */
150 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RawMonitorWait, jvmti, thr_start_lock, (jlong)0))) {
151 result = STATUS_FAILED;
152 NSK_COMPLAIN0("[agent] Failed while waiting thr_start_lock\n");
153 }
154 }
155
156 if (next_thread != NULL) {
157 /* hmm, why NewGlobalRef is called one more time???
158 * next_thread = NSK_CPP_STUB2(NewGlobalRef, env, next_thread);
159 */
160 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(SuspendThread, jvmti, next_thread))) {
161 result = STATUS_FAILED;
162 NSK_COMPLAIN1("[agent] Failed to suspend thread#%d\n", eventsCount);
163 }
164
165 NSK_DISPLAY2(">>> [agent] thread#%d %s suspended ...\n", eventsCount, inf.name);
166
167 /* these dummy calls provoke VM to hang */
168 temp = NSK_CPP_STUB2(NewGlobalRef, env, next_thread);
169 NSK_CPP_STUB2(DeleteGlobalRef, env, temp);
170
171 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(ResumeThread, jvmti, next_thread))) {
172 result = STATUS_FAILED;
173 NSK_COMPLAIN1("[agent] Failed to resume thread#%d\n", eventsCount);
174 }
175
176 NSK_DISPLAY2(">>> [agent] thread#%d %s resumed ...\n", eventsCount, inf.name);
177
178 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadState, jvmti, next_thread, &thrStat))) {
179 result = STATUS_FAILED;
180 NSK_COMPLAIN1("[agent] Failed to get thread state for thread#%d\n", eventsCount);
181 }
182
183 NSK_DISPLAY3(">>> [agent] %s threadState=%s (%x)\n",
184 inf.name, TranslateState(thrStat), thrStat);
185
186 if (thrStat & JVMTI_THREAD_STATE_SUSPENDED) {
187 NSK_COMPLAIN1("[agent] \"%s\" was not resumed\n", inf.name);
188 NSK_CPP_STUB2(FatalError, env, "[agent] could not recover");
189 }
190
191 NSK_CPP_STUB2(DeleteGlobalRef, env, next_thread);
192 next_thread = NULL;
193
194 /* Notify ThreadStart callback that thread has been resumed */
195 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti, thr_resume_lock))) {
196 NSK_COMPLAIN0("[agent] Failed to acquire thr_resume_lock\n");
197 result = STATUS_FAILED;
198 }
199
200 debug_agent_timed_out = JNI_FALSE;
201
202 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorNotify, jvmti, thr_resume_lock))) {
203 NSK_COMPLAIN0("[agent] Failed to notifing about thr_resume_lock\n");
204 result = STATUS_FAILED;
205 }
206
207 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti, thr_resume_lock))) {
208 NSK_COMPLAIN0("[agent] Failed to release thr_resume_lock\n");
209 result = STATUS_FAILED;
210 }
211 }
212 }
213
214 /*
215 * We don't call RawMonitorExit(thr_start_lock) in the loop so we don't
216 * lose any notify calls.
217 */
218 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti, thr_start_lock))) {
219 NSK_COMPLAIN0("[agent] Failed to release thr_start_lock\n");
220 result = STATUS_FAILED;
221 }
222
223 NSK_DISPLAY0(">>> [agent] done.\n");
224 }
225
226 void JNICALL ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) {
227 jint thrStat;
228 jvmtiPhase phase;
229
230 NSK_DISPLAY0(">>> [ThreadStart hook] start\n");
231
232 /* skip if thread is 'agent thread' */
233 if (NSK_CPP_STUB3(IsSameObject, env, agent_thread, thread) == JNI_TRUE) {
234 NSK_DISPLAY0(">>> [ThreadStart hook] skip agent thread\n");
235 NSK_DISPLAY0(">>> [ThreadStart hook] end\n");
236 return;
237 }
238
239 /* wait till agent thread is started
240 * (otherwise can fail while waiting on thr_resume_thread due to timeout)
241 */
242 if (debug_agent_started != JNI_TRUE) {
243 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti_env, agent_start_lock))) {
244 NSK_COMPLAIN0("[ThreadStart hook] Failed to acquire agent_start_lock\n");
245 result = STATUS_FAILED;
246 }
247
248 while (debug_agent_started != JNI_TRUE) {
249 NSK_DISPLAY1(">>> [ThreadStart hook] waiting %dms for agent thread to start\n", WAIT_TIME);
250
251 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RawMonitorWait,
252 jvmti_env, agent_start_lock, (jlong)WAIT_TIME))) {
253 NSK_COMPLAIN0("[ThreadStart hook] Failed to wait for agent_start_lock\n");
254 result = STATUS_FAILED;
255 }
256 }
257
258 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti_env, agent_start_lock))) {
259 NSK_COMPLAIN0("[ThreadStart hook] Failed to release agent_start_lock\n");
260 result = STATUS_FAILED;
261 }
262 }
263
264
265 /* get JVMTI phase */
266 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPhase, jvmti_env, &phase))) {
267 NSK_COMPLAIN0("[ThreadStart hook] Failed to get JVMTI phase\n");
268 result = STATUS_FAILED;
269 }
270
271 /* Acquire event lock,
272 * so only one StartThread callback could be proceeded at the time
273 */
274 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti_env, thr_event_lock))) {
275 NSK_COMPLAIN0("[ThreadStart hook] Failed to acquire thr_event_lock\n");
276 result = STATUS_FAILED;
277 }
278
279 {
280 /* Get thread name */
281 inf.name = (char*) "UNKNOWN";
282 if (phase == JVMTI_PHASE_LIVE) {
283 /* GetThreadInfo may only be called during the live phase */
284 if (!NSK_JVMTI_VERIFY(
285 NSK_CPP_STUB3(GetThreadInfo, jvmti_env, thread, &inf))) {
286 NSK_COMPLAIN1("[ThreadStart hook] Failed to get thread infor for thread#%d\n", eventsCount);
287 result = STATUS_FAILED;
288 }
289 }
290
291 NSK_DISPLAY2(">>> [ThreadStart hook] thread#%d: %s\n", eventsCount, inf.name);
292
293 /* Acquire thr_start_lock */
294 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti_env, thr_start_lock))) {
295 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to acquire thr_start_lock\n", eventsCount);
296 result = STATUS_FAILED;
297 }
298
299 /* Acquire thr_resume_lock before we release thr_start_lock to prevent
300 * debug agent from notifying us before we are ready.
301 */
302 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti_env, thr_resume_lock))) {
303 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to acquire thr_resume_lock\n", eventsCount);
304 result = STATUS_FAILED;
305 }
306
307 /* Store thread */
308 next_thread = NSK_CPP_STUB2(NewGlobalRef, env, thread);
309 debug_agent_timed_out = JNI_TRUE;
310
311 /* Notify agent thread about new started thread and let agent thread to work with it */
312 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorNotify, jvmti_env, thr_start_lock))) {
313 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to notify about thr_start_lock\n", eventsCount);
314 result = STATUS_FAILED;
315 }
316
317 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti_env, thr_start_lock))) {
318 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to release thr_start_lock\n", eventsCount);
319 result = STATUS_FAILED;
320 }
321
322 /* Wait till this started thread will be resumed by agent thread */
323 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RawMonitorWait,
324 jvmti_env, thr_resume_lock, (jlong)WAIT_TIME ))) {
325 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed while waiting for thr_resume_lock\n", eventsCount);
326 result = STATUS_FAILED;
327 }
328
329 if (debug_agent_timed_out == JNI_TRUE) {
330 NSK_COMPLAIN1("[ThreadStart hook] \"%s\": debug agent timed out\n", inf.name);
331 NSK_CPP_STUB2(FatalError, env, "[ThreadStart hook] could not recover");
332 }
333
334 /* Release thr_resume_lock lock */
335 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti_env, thr_resume_lock))) {
336 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to release thr_resume_lock\n", eventsCount);
337 result = STATUS_FAILED;
338 }
339
340 /* check that thread is not in SUSPENDED state */
341 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetThreadState, jvmti_env, thread, &thrStat))) {
342 NSK_COMPLAIN1("[ThreadStart hook] Failed to get thread state for thread#%d\n", eventsCount);
343 result = STATUS_FAILED;
344 }
345
346 NSK_DISPLAY2(">>> [ThreadStart hook] threadState=%s (%x)\n",
347 TranslateState(thrStat), thrStat);
348
349 if (thrStat & JVMTI_THREAD_STATE_SUSPENDED) {
350 NSK_COMPLAIN1("[ThreadStart hook] \"%s\" was self-suspended\n", inf.name);
351 NSK_CPP_STUB2(FatalError, env, "[ThreadStart hook] could not recover");
352 }
353
354 eventsCount++;
355 }
356
357 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti_env, thr_event_lock))) {
358 NSK_COMPLAIN0("[ThreadStart hook] Failed to release thr_event_lock\n");
359 result = STATUS_FAILED;
360 }
361
362 NSK_DISPLAY0(">>> [ThreadStart hook] end\n");
363 }
364
365 void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) {
366 jclass cls = NULL;
367 jmethodID mid = NULL;
368
369 NSK_DISPLAY0(">>> VMInit event: start\n");
370
371 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
372 jvmti_env, JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL))) {
373 NSK_COMPLAIN0("TEST FAILED: failed to enable JVMTI_EVENT_THREAD_START\n");
374 return;
375 }
376
377 /* Start agent thread */
378 if (!NSK_VERIFY((cls =
379 NSK_CPP_STUB2(FindClass, env, "java/lang/Thread")) != NULL)) {
380 result = STATUS_FAILED;
381 NSK_COMPLAIN0("TEST FAILED: Cannot start agent thread: FindClass() failed\n");
382 return;
383 }
384
385
386 if (!NSK_VERIFY((mid =
387 NSK_CPP_STUB4(GetMethodID, env, cls, "<init>", "()V")) != NULL)) {
388 result = STATUS_FAILED;
389 NSK_COMPLAIN0("TEST FAILED: Cannot start agent thread: GetMethodID() failed\n");
390 return;
391 }
392
393
394 if (!NSK_VERIFY((agent_thread =
395 NSK_CPP_STUB3(NewObject, env, cls, mid)) != NULL)) {
396 result = STATUS_FAILED;
397 NSK_COMPLAIN0("Cannot start agent thread: NewObject() failed\n");
398 return;
399 }
400
401 agent_thread = (jthread) NSK_CPP_STUB2(NewGlobalRef, env, agent_thread);
402 if (agent_thread == NULL) {
403 result = STATUS_FAILED;
404 NSK_COMPLAIN0("Cannot create global reference for agent_thread\n");
405 return;
406 }
407
408 /*
409 * Grab agent_start_lock before launching debug_agent to prevent
410 * debug_agent from notifying us before we are ready.
411 */
412
413 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter, jvmti_env, agent_start_lock))) {
414 result = STATUS_FAILED;
415 NSK_COMPLAIN0("TEST FAILED: failed to enter agent_start_lock\n");
416 }
417
418 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB5(RunAgentThread,
419 jvmti_env, agent_thread, debug_agent, NULL, JVMTI_THREAD_NORM_PRIORITY))) {
420 result = STATUS_FAILED;
421 NSK_COMPLAIN0("TEST FAILED: failed to create agent thread\n");
422 }
423
424 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RawMonitorWait, jvmti_env, agent_start_lock, (jlong)0))) {
425 result = STATUS_FAILED;
426 NSK_COMPLAIN0("TEST FAILED: failed to wait agent_start_lock\n");
427 }
428
429 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit, jvmti_env, agent_start_lock))) {
430 result = STATUS_FAILED;
431 NSK_COMPLAIN0("TEST FAILED: failed to exit agent_start_lock\n");
432 }
433
434 NSK_DISPLAY0(">>> VMInit event: end\n");
435 }
436
437 void JNICALL VMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) {
438 NSK_DISPLAY0(">>> VMDeath event\n");
439
440 terminate_debug_agent = JNI_TRUE;
441 }
442
443 #ifdef STATIC_BUILD
444 JNIEXPORT jint JNICALL Agent_OnLoad_threadstart002(JavaVM *jvm, char *options, void *reserved) {
445 return Agent_Initialize(jvm, options, reserved);
446 }
447 JNIEXPORT jint JNICALL Agent_OnAttach_threadstart002(JavaVM *jvm, char *options, void *reserved) {
448 return Agent_Initialize(jvm, options, reserved);
449 }
450 JNIEXPORT jint JNI_OnLoad_threadstart002(JavaVM *jvm, char *options, void *reserved) {
451 return JNI_VERSION_1_8;
452 }
453 #endif
454 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
455
456 /* init framework and parse options */
457 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
458 return JNI_ERR;
459
460 /* create JVMTI environment */
461 if (!NSK_VERIFY((jvmti =
462 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) {
463 NSK_COMPLAIN0("TEST FAILED: failed to create JVMTIEnv\n");
464 return JNI_ERR;
465 }
466
467 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetPotentialCapabilities, jvmti, &caps))) {
468 NSK_COMPLAIN0("TEST FAILED: failed to get potential capabilities\n");
469 return JNI_ERR;
470 }
471
472 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities, jvmti, &caps))) {
473 NSK_COMPLAIN0("TEST FAILED: failed to add capabilities during agent load\n");
474 return JNI_ERR;
475 }
476
477 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetCapabilities, jvmti, &caps))) {
478 NSK_COMPLAIN0("TEST FAILED: failed to get capabilities\n");
479 return JNI_ERR;
480 }
481
482 if (!caps.can_suspend) {
483 NSK_DISPLAY0("WARNING: suspend/resume is not implemented\n");
484 }
485
486 /* create raw monitors */
487 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(CreateRawMonitor, jvmti, "_agent_start_lock", &agent_start_lock))) {
488 NSK_COMPLAIN0("TEST FAILED: failed to create agent_start_lock\n");
489 return JNI_ERR;
490 }
491
492 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(CreateRawMonitor, jvmti, "_thr_event_lock", &thr_event_lock))) {
493 NSK_COMPLAIN0("TEST FAILED: failed to create thr_event_lock\n");
494 return JNI_ERR;
495 }
496
497 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(CreateRawMonitor, jvmti, "_thr_start_lock", &thr_start_lock))) {
498 NSK_COMPLAIN0("TEST FAILED: failed to create thr_start_lock\n");
499 return JNI_ERR;
500 }
501
502 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(CreateRawMonitor, jvmti, "_thr_resume_lock", &thr_resume_lock))) {
503 NSK_COMPLAIN0("TEST FAILED: failed to create thr_resume_lock\n");
504 return JNI_ERR;
505 }
506
507 callbacks.VMInit = &VMInit;
508 callbacks.VMDeath = &VMDeath;
509 callbacks.ThreadStart = &ThreadStart;
510
511 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks, jvmti, &callbacks, sizeof(callbacks)))) {
512 NSK_COMPLAIN0("TEST FAILED: failed to set event callbacks\n");
513 return JNI_ERR;
514 }
515
516 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
517 jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL))) {
518 NSK_COMPLAIN0("TEST FAILED: failed to enable JVMTI_EVENT_VM_INIT\n");
519 return JNI_ERR;
520 }
521
522 if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
523 jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL))) {
524 NSK_COMPLAIN0("TEST FAILED: failed to enable JVMTI_EVENT_VM_DEATH\n");
525 return JNI_ERR;
526 }
527
528 return JNI_OK;
529 }
530
531 JNIEXPORT jint JNICALL
532 Java_nsk_jvmti_ThreadStart_threadstart002_check(JNIEnv *env, jclass cls) {
533 if (eventsCount == 0) {
534 NSK_COMPLAIN0("None of thread start events!\n");
535 result = STATUS_FAILED;
536 }
537
538 NSK_DISPLAY1(">>> total of thread start events: %d\n", eventsCount);
539
540 return result;
541 }
542
543 }
|
102 | thr_resume_lock.enter |
103 | thr_resume_lock.notify |
104 | thr_resume_lock.exit |
105 | | ... check next_thread state
106 | | thr_resume_lock.exit
107 | thr_start_lock.exit |
108 | thr_event_lock.exit
109
110
111 */
112
113 static void JNICALL
114 debug_agent(jvmtiEnv* jvmti, JNIEnv* jni, void *p) {
115 JNIEnv *env = jni;
116 jint thrStat;
117 jobject temp;
118
119 /* Notify VMInit callback as well as ThreadStart callback (if any)
120 * that agent thread has been started
121 */
122 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(agent_start_lock))) {
123 result = STATUS_FAILED;
124 NSK_COMPLAIN0("[agent] failed to acquire agent_start_lock\n");
125 }
126
127 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorNotifyAll(agent_start_lock))) {
128 result = STATUS_FAILED;
129 NSK_COMPLAIN0("[agent] failed to notify about agent_start_lock\n");
130 }
131
132 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(agent_start_lock))) {
133 result = STATUS_FAILED;
134 NSK_COMPLAIN0("[agent] failed to release agent_start_lock\n");
135 }
136
137 NSK_DISPLAY0(">>> [agent] agent created\n");
138
139 debug_agent_started = JNI_TRUE;
140
141 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(thr_start_lock))) {
142 result = STATUS_FAILED;
143 NSK_COMPLAIN0("[agent] failed to enter thr_start_lock\n");
144 }
145
146 while (terminate_debug_agent != JNI_TRUE) {
147
148 if (next_thread == NULL ) {
149 /* wait till new thread will be created and started */
150 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorWait(thr_start_lock, (jlong)0))) {
151 result = STATUS_FAILED;
152 NSK_COMPLAIN0("[agent] Failed while waiting thr_start_lock\n");
153 }
154 }
155
156 if (next_thread != NULL) {
157 /* hmm, why NewGlobalRef is called one more time???
158 * next_thread = env->NewGlobalRef(next_thread);
159 */
160 if (!NSK_JVMTI_VERIFY(jvmti->SuspendThread(next_thread))) {
161 result = STATUS_FAILED;
162 NSK_COMPLAIN1("[agent] Failed to suspend thread#%d\n", eventsCount);
163 }
164
165 NSK_DISPLAY2(">>> [agent] thread#%d %s suspended ...\n", eventsCount, inf.name);
166
167 /* these dummy calls provoke VM to hang */
168 temp = env->NewGlobalRef(next_thread);
169 env->DeleteGlobalRef(temp);
170
171 if (!NSK_JVMTI_VERIFY(jvmti->ResumeThread(next_thread))) {
172 result = STATUS_FAILED;
173 NSK_COMPLAIN1("[agent] Failed to resume thread#%d\n", eventsCount);
174 }
175
176 NSK_DISPLAY2(">>> [agent] thread#%d %s resumed ...\n", eventsCount, inf.name);
177
178 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadState(next_thread, &thrStat))) {
179 result = STATUS_FAILED;
180 NSK_COMPLAIN1("[agent] Failed to get thread state for thread#%d\n", eventsCount);
181 }
182
183 NSK_DISPLAY3(">>> [agent] %s threadState=%s (%x)\n",
184 inf.name, TranslateState(thrStat), thrStat);
185
186 if (thrStat & JVMTI_THREAD_STATE_SUSPENDED) {
187 NSK_COMPLAIN1("[agent] \"%s\" was not resumed\n", inf.name);
188 env->FatalError("[agent] could not recover");
189 }
190
191 env->DeleteGlobalRef(next_thread);
192 next_thread = NULL;
193
194 /* Notify ThreadStart callback that thread has been resumed */
195 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorEnter(thr_resume_lock))) {
196 NSK_COMPLAIN0("[agent] Failed to acquire thr_resume_lock\n");
197 result = STATUS_FAILED;
198 }
199
200 debug_agent_timed_out = JNI_FALSE;
201
202 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorNotify(thr_resume_lock))) {
203 NSK_COMPLAIN0("[agent] Failed to notifing about thr_resume_lock\n");
204 result = STATUS_FAILED;
205 }
206
207 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(thr_resume_lock))) {
208 NSK_COMPLAIN0("[agent] Failed to release thr_resume_lock\n");
209 result = STATUS_FAILED;
210 }
211 }
212 }
213
214 /*
215 * We don't call RawMonitorExit(thr_start_lock) in the loop so we don't
216 * lose any notify calls.
217 */
218 if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(thr_start_lock))) {
219 NSK_COMPLAIN0("[agent] Failed to release thr_start_lock\n");
220 result = STATUS_FAILED;
221 }
222
223 NSK_DISPLAY0(">>> [agent] done.\n");
224 }
225
226 void JNICALL ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) {
227 jint thrStat;
228 jvmtiPhase phase;
229
230 NSK_DISPLAY0(">>> [ThreadStart hook] start\n");
231
232 /* skip if thread is 'agent thread' */
233 if (env->IsSameObject(agent_thread, thread) == JNI_TRUE) {
234 NSK_DISPLAY0(">>> [ThreadStart hook] skip agent thread\n");
235 NSK_DISPLAY0(">>> [ThreadStart hook] end\n");
236 return;
237 }
238
239 /* wait till agent thread is started
240 * (otherwise can fail while waiting on thr_resume_thread due to timeout)
241 */
242 if (debug_agent_started != JNI_TRUE) {
243 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorEnter(agent_start_lock))) {
244 NSK_COMPLAIN0("[ThreadStart hook] Failed to acquire agent_start_lock\n");
245 result = STATUS_FAILED;
246 }
247
248 while (debug_agent_started != JNI_TRUE) {
249 NSK_DISPLAY1(">>> [ThreadStart hook] waiting %dms for agent thread to start\n", WAIT_TIME);
250
251 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorWait(agent_start_lock, (jlong)WAIT_TIME))) {
252 NSK_COMPLAIN0("[ThreadStart hook] Failed to wait for agent_start_lock\n");
253 result = STATUS_FAILED;
254 }
255 }
256
257 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(agent_start_lock))) {
258 NSK_COMPLAIN0("[ThreadStart hook] Failed to release agent_start_lock\n");
259 result = STATUS_FAILED;
260 }
261 }
262
263
264 /* get JVMTI phase */
265 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
266 NSK_COMPLAIN0("[ThreadStart hook] Failed to get JVMTI phase\n");
267 result = STATUS_FAILED;
268 }
269
270 /* Acquire event lock,
271 * so only one StartThread callback could be proceeded at the time
272 */
273 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorEnter(thr_event_lock))) {
274 NSK_COMPLAIN0("[ThreadStart hook] Failed to acquire thr_event_lock\n");
275 result = STATUS_FAILED;
276 }
277
278 {
279 /* Get thread name */
280 inf.name = (char*) "UNKNOWN";
281 if (phase == JVMTI_PHASE_LIVE) {
282 /* GetThreadInfo may only be called during the live phase */
283 if (!NSK_JVMTI_VERIFY(jvmti_env->GetThreadInfo(thread, &inf))) {
284 NSK_COMPLAIN1("[ThreadStart hook] Failed to get thread infor for thread#%d\n", eventsCount);
285 result = STATUS_FAILED;
286 }
287 }
288
289 NSK_DISPLAY2(">>> [ThreadStart hook] thread#%d: %s\n", eventsCount, inf.name);
290
291 /* Acquire thr_start_lock */
292 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorEnter(thr_start_lock))) {
293 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to acquire thr_start_lock\n", eventsCount);
294 result = STATUS_FAILED;
295 }
296
297 /* Acquire thr_resume_lock before we release thr_start_lock to prevent
298 * debug agent from notifying us before we are ready.
299 */
300 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorEnter(thr_resume_lock))) {
301 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to acquire thr_resume_lock\n", eventsCount);
302 result = STATUS_FAILED;
303 }
304
305 /* Store thread */
306 next_thread = env->NewGlobalRef(thread);
307 debug_agent_timed_out = JNI_TRUE;
308
309 /* Notify agent thread about new started thread and let agent thread to work with it */
310 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorNotify(thr_start_lock))) {
311 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to notify about thr_start_lock\n", eventsCount);
312 result = STATUS_FAILED;
313 }
314
315 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(thr_start_lock))) {
316 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to release thr_start_lock\n", eventsCount);
317 result = STATUS_FAILED;
318 }
319
320 /* Wait till this started thread will be resumed by agent thread */
321 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorWait(thr_resume_lock, (jlong)WAIT_TIME ))) {
322 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed while waiting for thr_resume_lock\n", eventsCount);
323 result = STATUS_FAILED;
324 }
325
326 if (debug_agent_timed_out == JNI_TRUE) {
327 NSK_COMPLAIN1("[ThreadStart hook] \"%s\": debug agent timed out\n", inf.name);
328 env->FatalError("[ThreadStart hook] could not recover");
329 }
330
331 /* Release thr_resume_lock lock */
332 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(thr_resume_lock))) {
333 NSK_COMPLAIN1("[ThreadStart hook] thread#%d failed to release thr_resume_lock\n", eventsCount);
334 result = STATUS_FAILED;
335 }
336
337 /* check that thread is not in SUSPENDED state */
338 if (!NSK_JVMTI_VERIFY(jvmti_env->GetThreadState(thread, &thrStat))) {
339 NSK_COMPLAIN1("[ThreadStart hook] Failed to get thread state for thread#%d\n", eventsCount);
340 result = STATUS_FAILED;
341 }
342
343 NSK_DISPLAY2(">>> [ThreadStart hook] threadState=%s (%x)\n",
344 TranslateState(thrStat), thrStat);
345
346 if (thrStat & JVMTI_THREAD_STATE_SUSPENDED) {
347 NSK_COMPLAIN1("[ThreadStart hook] \"%s\" was self-suspended\n", inf.name);
348 env->FatalError("[ThreadStart hook] could not recover");
349 }
350
351 eventsCount++;
352 }
353
354 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(thr_event_lock))) {
355 NSK_COMPLAIN0("[ThreadStart hook] Failed to release thr_event_lock\n");
356 result = STATUS_FAILED;
357 }
358
359 NSK_DISPLAY0(">>> [ThreadStart hook] end\n");
360 }
361
362 void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) {
363 jclass cls = NULL;
364 jmethodID mid = NULL;
365
366 NSK_DISPLAY0(">>> VMInit event: start\n");
367
368 if (!NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL))) {
369 NSK_COMPLAIN0("TEST FAILED: failed to enable JVMTI_EVENT_THREAD_START\n");
370 return;
371 }
372
373 /* Start agent thread */
374 if (!NSK_VERIFY((cls = env->FindClass("java/lang/Thread")) != NULL)) {
375 result = STATUS_FAILED;
376 NSK_COMPLAIN0("TEST FAILED: Cannot start agent thread: FindClass() failed\n");
377 return;
378 }
379
380
381 if (!NSK_VERIFY((mid = env->GetMethodID(cls, "<init>", "()V")) != NULL)) {
382 result = STATUS_FAILED;
383 NSK_COMPLAIN0("TEST FAILED: Cannot start agent thread: GetMethodID() failed\n");
384 return;
385 }
386
387
388 if (!NSK_VERIFY((agent_thread = env->NewObject(cls, mid)) != NULL)) {
389 result = STATUS_FAILED;
390 NSK_COMPLAIN0("Cannot start agent thread: NewObject() failed\n");
391 return;
392 }
393
394 agent_thread = (jthread) env->NewGlobalRef(agent_thread);
395 if (agent_thread == NULL) {
396 result = STATUS_FAILED;
397 NSK_COMPLAIN0("Cannot create global reference for agent_thread\n");
398 return;
399 }
400
401 /*
402 * Grab agent_start_lock before launching debug_agent to prevent
403 * debug_agent from notifying us before we are ready.
404 */
405
406 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorEnter(agent_start_lock))) {
407 result = STATUS_FAILED;
408 NSK_COMPLAIN0("TEST FAILED: failed to enter agent_start_lock\n");
409 }
410
411 if (!NSK_JVMTI_VERIFY(jvmti_env->RunAgentThread(agent_thread, debug_agent, NULL, JVMTI_THREAD_NORM_PRIORITY))) {
412 result = STATUS_FAILED;
413 NSK_COMPLAIN0("TEST FAILED: failed to create agent thread\n");
414 }
415
416 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorWait(agent_start_lock, (jlong)0))) {
417 result = STATUS_FAILED;
418 NSK_COMPLAIN0("TEST FAILED: failed to wait agent_start_lock\n");
419 }
420
421 if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(agent_start_lock))) {
422 result = STATUS_FAILED;
423 NSK_COMPLAIN0("TEST FAILED: failed to exit agent_start_lock\n");
424 }
425
426 NSK_DISPLAY0(">>> VMInit event: end\n");
427 }
428
429 void JNICALL VMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) {
430 NSK_DISPLAY0(">>> VMDeath event\n");
431
432 terminate_debug_agent = JNI_TRUE;
433 }
434
435 #ifdef STATIC_BUILD
436 JNIEXPORT jint JNICALL Agent_OnLoad_threadstart002(JavaVM *jvm, char *options, void *reserved) {
437 return Agent_Initialize(jvm, options, reserved);
438 }
439 JNIEXPORT jint JNICALL Agent_OnAttach_threadstart002(JavaVM *jvm, char *options, void *reserved) {
440 return Agent_Initialize(jvm, options, reserved);
441 }
442 JNIEXPORT jint JNI_OnLoad_threadstart002(JavaVM *jvm, char *options, void *reserved) {
443 return JNI_VERSION_1_8;
444 }
445 #endif
446 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
447
448 /* init framework and parse options */
449 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
450 return JNI_ERR;
451
452 /* create JVMTI environment */
453 if (!NSK_VERIFY((jvmti =
454 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) {
455 NSK_COMPLAIN0("TEST FAILED: failed to create JVMTIEnv\n");
456 return JNI_ERR;
457 }
458
459 if (!NSK_JVMTI_VERIFY(jvmti->GetPotentialCapabilities(&caps))) {
460 NSK_COMPLAIN0("TEST FAILED: failed to get potential capabilities\n");
461 return JNI_ERR;
462 }
463
464 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) {
465 NSK_COMPLAIN0("TEST FAILED: failed to add capabilities during agent load\n");
466 return JNI_ERR;
467 }
468
469 if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps))) {
470 NSK_COMPLAIN0("TEST FAILED: failed to get capabilities\n");
471 return JNI_ERR;
472 }
473
474 if (!caps.can_suspend) {
475 NSK_DISPLAY0("WARNING: suspend/resume is not implemented\n");
476 }
477
478 /* create raw monitors */
479 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_agent_start_lock", &agent_start_lock))) {
480 NSK_COMPLAIN0("TEST FAILED: failed to create agent_start_lock\n");
481 return JNI_ERR;
482 }
483
484 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_thr_event_lock", &thr_event_lock))) {
485 NSK_COMPLAIN0("TEST FAILED: failed to create thr_event_lock\n");
486 return JNI_ERR;
487 }
488
489 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_thr_start_lock", &thr_start_lock))) {
490 NSK_COMPLAIN0("TEST FAILED: failed to create thr_start_lock\n");
491 return JNI_ERR;
492 }
493
494 if (!NSK_JVMTI_VERIFY(jvmti->CreateRawMonitor("_thr_resume_lock", &thr_resume_lock))) {
495 NSK_COMPLAIN0("TEST FAILED: failed to create thr_resume_lock\n");
496 return JNI_ERR;
497 }
498
499 callbacks.VMInit = &VMInit;
500 callbacks.VMDeath = &VMDeath;
501 callbacks.ThreadStart = &ThreadStart;
502
503 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)))) {
504 NSK_COMPLAIN0("TEST FAILED: failed to set event callbacks\n");
505 return JNI_ERR;
506 }
507
508 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL))) {
509 NSK_COMPLAIN0("TEST FAILED: failed to enable JVMTI_EVENT_VM_INIT\n");
510 return JNI_ERR;
511 }
512
513 if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL))) {
514 NSK_COMPLAIN0("TEST FAILED: failed to enable JVMTI_EVENT_VM_DEATH\n");
515 return JNI_ERR;
516 }
517
518 return JNI_OK;
519 }
520
521 JNIEXPORT jint JNICALL
522 Java_nsk_jvmti_ThreadStart_threadstart002_check(JNIEnv *env, jclass cls) {
523 if (eventsCount == 0) {
524 NSK_COMPLAIN0("None of thread start events!\n");
525 result = STATUS_FAILED;
526 }
527
528 NSK_DISPLAY1(">>> total of thread start events: %d\n", eventsCount);
529
530 return result;
531 }
532
533 }
|