1 /* 2 * Copyright (c) 2003, 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 <string.h> 25 #include "jvmti.h" 26 #include "agent_common.h" 27 #include "jni_tools.h" 28 #include "jvmti_tools.h" 29 30 extern "C" { 31 32 /* ============================================================================= */ 33 34 /* constant names */ 35 #define DEBUGEE_CLASS_NAME "nsk/jvmti/scenarios/sampling/SP05/sp05t003" 36 #define THREAD_CLASS_NAME "nsk/jvmti/scenarios/sampling/SP05/sp05t003Thread" 37 #define THREADS_FIELD_NAME "threads" 38 #define THREADS_FIELD_SIG "[L" THREAD_CLASS_NAME ";" 39 40 /* constants */ 41 #define TIMEOUT_DELTA 1000 42 43 /* scaffold objects */ 44 static JNIEnv* jni = NULL; 45 static jvmtiEnv *jvmti = NULL; 46 static jlong timeout = 0; 47 48 /* number of tested threads and events */ 49 #define THREADS_COUNT 2 50 #define EVENTS_COUNT 2 51 #define MAX_STACK_DEPTH 64 52 53 /* tested events */ 54 static jvmtiEvent eventsList[EVENTS_COUNT] = { 55 JVMTI_EVENT_THREAD_START, 56 JVMTI_EVENT_THREAD_END 57 }; 58 59 /* tested threads names */ 60 static const char* threadsName[THREADS_COUNT] = { 61 "threadRunningJava", 62 "threadRunningNative" 63 }; 64 65 /* references to tested threads */ 66 static jthread threadsList[THREADS_COUNT]; 67 68 /* events conunts */ 69 static volatile int eventsStart = 0; 70 static volatile int eventsEnd = 0; 71 72 /* ============================================================================= */ 73 74 /* testcase(s) */ 75 static int prepare(); 76 static int checkThreads(const char* kind); 77 static int resumeThreads(const char* kind); 78 static int clean(); 79 80 /* ============================================================================= */ 81 82 /** Agent algorithm. */ 83 static void JNICALL 84 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 85 jni = agentJNI; 86 87 /* wait for initial sync */ 88 if (!nsk_jvmti_waitForSync(timeout)) 89 return; 90 91 /* testcase(s) */ 92 { 93 /* obtain threads list */ 94 if (!prepare()) { 95 nsk_jvmti_setFailStatus(); 96 return; 97 } 98 99 /* testcase #1: suspend and check threads on THREAD_START event */ 100 { 101 eventsStart = 0; 102 if (!NSK_JVMTI_VERIFY( 103 NSK_CPP_STUB4(SetEventNotificationMode, jvmti, JVMTI_ENABLE, 104 JVMTI_EVENT_THREAD_START, NULL))) { 105 nsk_jvmti_setFailStatus(); 106 return; 107 } 108 109 NSK_DISPLAY0("Let threads to start\n"); 110 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 111 return; 112 113 NSK_DISPLAY0("Wait for THREAD_START events\n"); 114 { 115 int i; 116 117 for (i = 0; i * TIMEOUT_DELTA < timeout; i++) { 118 if (eventsStart >= THREADS_COUNT) 119 break; 120 nsk_jvmti_sleep(TIMEOUT_DELTA); 121 } 122 } 123 124 if (!NSK_JVMTI_VERIFY( 125 NSK_CPP_STUB4(SetEventNotificationMode, jvmti, JVMTI_DISABLE, 126 JVMTI_EVENT_THREAD_START, NULL))) { 127 nsk_jvmti_setFailStatus(); 128 } 129 130 /* check if all threads suspended on THREAD_START events */ 131 if (eventsStart != THREADS_COUNT) { 132 NSK_COMPLAIN2("Unexpected number of THREAD_START events:\n" 133 "# received: %d\n" 134 "# expected: %d\n", 135 eventsStart, THREADS_COUNT); 136 } 137 138 NSK_DISPLAY0("Testcase #1: check threads on THREAD_START\n"); 139 if (!NSK_VERIFY(checkThreads("starting"))) 140 return; 141 142 NSK_DISPLAY0("Resume all threads\n"); 143 if (!NSK_VERIFY(resumeThreads("starting"))) 144 return; 145 146 NSK_DISPLAY0("Wait for threads to run\n"); 147 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 148 return; 149 } 150 151 /* testcase #2: suspend and check threads on THREAD_END event */ 152 { 153 eventsEnd = 0; 154 if (!NSK_JVMTI_VERIFY( 155 NSK_CPP_STUB4(SetEventNotificationMode, jvmti, JVMTI_ENABLE, 156 JVMTI_EVENT_THREAD_END, NULL))) { 157 nsk_jvmti_setFailStatus(); 158 return; 159 } 160 161 NSK_DISPLAY0("Let threads to finish\n"); 162 if (!NSK_VERIFY(nsk_jvmti_resumeSync())) 163 return; 164 165 NSK_DISPLAY0("Wait for THREAD_END events\n"); 166 { 167 int i; 168 169 for (i = 0; i * TIMEOUT_DELTA < timeout; i++) { 170 if (eventsEnd >= THREADS_COUNT) 171 break; 172 nsk_jvmti_sleep(TIMEOUT_DELTA); 173 } 174 } 175 176 if (!NSK_JVMTI_VERIFY( 177 NSK_CPP_STUB4(SetEventNotificationMode, jvmti, JVMTI_DISABLE, 178 JVMTI_EVENT_THREAD_END, NULL))) { 179 nsk_jvmti_setFailStatus(); 180 } 181 182 /* check ia all threads suspended on THREAD_END event */ 183 if (eventsEnd != THREADS_COUNT) { 184 NSK_COMPLAIN2("Unexpected number of THREAD_END events:\n" 185 "# received: %d\n" 186 "# expected: %d\n", 187 eventsEnd, THREADS_COUNT); 188 } 189 190 NSK_DISPLAY0("Testcase #2: check threads on THREAD_END\n"); 191 if (!NSK_VERIFY(checkThreads("finishing"))) 192 return; 193 194 NSK_DISPLAY0("Resume all threads\n"); 195 if (!NSK_VERIFY(resumeThreads("finishing"))) 196 return; 197 198 NSK_DISPLAY0("Wait for threads to finish\n"); 199 if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) 200 return; 201 } 202 203 /* clean threads references */ 204 if (!clean()) { 205 nsk_jvmti_setFailStatus(); 206 return; 207 } 208 } 209 210 /* resume debugee after last sync */ 211 if (!nsk_jvmti_resumeSync()) 212 return; 213 } 214 215 /* ============================================================================= */ 216 217 /** 218 * Resume all threads in given state. 219 */ 220 static int resumeThreads(const char* kind) { 221 int i; 222 223 for (i = 0; i < THREADS_COUNT; i++) { 224 if (!NSK_JVMTI_VERIFY( 225 NSK_CPP_STUB2(ResumeThread, jvmti, threadsList[i]))) { 226 nsk_jvmti_setFailStatus(); 227 } 228 } 229 return NSK_TRUE; 230 } 231 232 /** 233 * Prepare data: 234 * - get threads array from static field 235 * - get each thread from array 236 * - make global refs 237 */ 238 static int prepare() { 239 jclass debugeeClass = NULL; 240 jfieldID threadsFieldID = NULL; 241 jobjectArray threadsArray = NULL; 242 jsize threadsArrayLength = 0; 243 jsize i; 244 245 /* find debugee class */ 246 if (!NSK_JNI_VERIFY(jni, (debugeeClass = 247 NSK_CPP_STUB2(FindClass, jni, DEBUGEE_CLASS_NAME)) != NULL)) 248 return NSK_FALSE; 249 250 /* find static field with threads array */ 251 if (!NSK_JNI_VERIFY(jni, (threadsFieldID = 252 NSK_CPP_STUB4(GetStaticFieldID, jni, debugeeClass, 253 THREADS_FIELD_NAME, THREADS_FIELD_SIG)) != NULL)) 254 return NSK_FALSE; 255 256 /* get threads array from static field */ 257 if (!NSK_JNI_VERIFY(jni, (threadsArray = (jobjectArray) 258 NSK_CPP_STUB3(GetStaticObjectField, jni, debugeeClass, threadsFieldID)) != NULL)) 259 return NSK_FALSE; 260 261 /* check array length */ 262 if (!NSK_JNI_VERIFY(jni, (threadsArrayLength = 263 NSK_CPP_STUB2(GetArrayLength, jni, threadsArray)) == THREADS_COUNT)) 264 return NSK_FALSE; 265 266 /* get each thread from array */ 267 for (i = 0; i < THREADS_COUNT; i++) { 268 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 269 NSK_CPP_STUB3(GetObjectArrayElement, jni, threadsArray, i)) != NULL)) 270 return NSK_FALSE; 271 } 272 273 /* make global references to threads */ 274 for (i = 0; i < THREADS_COUNT; i++) { 275 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = (jthread) 276 NSK_CPP_STUB2(NewGlobalRef, jni, threadsList[i])) != NULL)) 277 return NSK_FALSE; 278 } 279 280 return NSK_TRUE; 281 } 282 283 /** 284 * Check thread's stack on event. 285 * 286 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 287 */ 288 static int checkThread(jthread thread, int i, const char* kind) { 289 jint framesCount = 0; 290 jint stackDepth = 0; 291 jvmtiFrameInfo stackFrames[MAX_STACK_DEPTH]; 292 293 NSK_DISPLAY3(" thread #%d (%s): %p\n", i, threadsName[i], (void*)thread); 294 295 /* get frames count */ 296 if (!NSK_JVMTI_VERIFY( 297 NSK_CPP_STUB3(GetFrameCount, jvmti, thread, &framesCount))) { 298 nsk_jvmti_setFailStatus(); 299 return NSK_TRUE; 300 } 301 NSK_DISPLAY1(" frames count: %d\n", (int)framesCount); 302 303 /* get stack frames */ 304 if (!NSK_JVMTI_VERIFY( 305 NSK_CPP_STUB6(GetStackTrace, jvmti, thread, 0, MAX_STACK_DEPTH, 306 stackFrames, &stackDepth))) { 307 nsk_jvmti_setFailStatus(); 308 return NSK_TRUE; 309 } 310 NSK_DISPLAY1(" stack depth: %d\n", (int)stackDepth); 311 312 /* check against emptyness */ 313 if (framesCount != 0) { 314 NSK_COMPLAIN5("Unexpected GetFramesCount() for %s thread #%d (%s):\n" 315 "# got frames: %d\n" 316 "# expected: %d\n", 317 kind, i, threadsName[i], 318 framesCount, 0); 319 nsk_jvmti_setFailStatus(); 320 } 321 if (stackDepth != 0) { 322 NSK_COMPLAIN5("Unexpected GetStackTrace() for %s thread #%d (%s):\n" 323 "# got frames: %d\n" 324 "# expected: %d\n", 325 kind, i, threadsName[i], 326 stackDepth, 0); 327 nsk_jvmti_setFailStatus(); 328 } 329 330 /* test may continue */ 331 return NSK_TRUE; 332 } 333 334 /** 335 * Testcase: check each thread's stack on event. 336 * 337 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 338 */ 339 static int checkThreads(const char* kind) { 340 int i; 341 342 for (i = 0; i < THREADS_COUNT; i++) { 343 if (!checkThread(threadsList[i], i, kind)) 344 return NSK_FALSE; 345 } 346 return NSK_TRUE; 347 } 348 349 /** 350 * Clean data: 351 * - dispose global references to tested threads 352 */ 353 static int clean() { 354 int i; 355 356 /* dispose global references to threads */ 357 for (i = 0; i < THREADS_COUNT; i++) { 358 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, threadsList[i])); 359 } 360 361 return NSK_TRUE; 362 } 363 364 /* ============================================================================= */ 365 366 /** 367 * THREAD_START callback: 368 * - check thread's stack on THREAD_START 369 */ 370 JNIEXPORT void JNICALL 371 callbackThreadStart(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 372 int i; 373 374 /* check if thread is not NULL */ 375 if (!NSK_VERIFY(thread != NULL)) { 376 nsk_jvmti_setFailStatus(); 377 return; 378 } 379 380 /* check if event is for tested thread */ 381 for (i = 0; i < THREADS_COUNT; i++) { 382 if (NSK_CPP_STUB3(IsSameObject, jni, threadsList[i], thread)) { 383 NSK_DISPLAY0("SUCCESS: expected THREAD_START event\n"); 384 385 /* suspend thread */ 386 NSK_DISPLAY3(" suspend starting thread #%d (%s): %p\n", 387 i, threadsName[i], (void*)thread); 388 389 if (!NSK_JVMTI_VERIFY( 390 NSK_CPP_STUB2(SuspendThread, jvmti, thread))) { 391 nsk_jvmti_setFailStatus(); 392 return; 393 } 394 eventsStart++; 395 396 break; 397 } 398 } 399 } 400 401 /** 402 * THREAD_END callback: 403 * - check thread's stack on THREAD_END 404 */ 405 JNIEXPORT void JNICALL 406 callbackThreadEnd(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 407 int i; 408 409 /* check if thread is not NULL */ 410 if (!NSK_VERIFY(thread != NULL)) { 411 nsk_jvmti_setFailStatus(); 412 return; 413 } 414 415 /* check if event is for tested thread */ 416 for (i = 0; i < THREADS_COUNT; i++) { 417 if (NSK_CPP_STUB3(IsSameObject, jni, threadsList[i], thread)) { 418 NSK_DISPLAY0("SUCCESS: expected THREAD_END event\n"); 419 420 /* suspend thread */ 421 NSK_DISPLAY3(" suspend finishing thread #%d (%s): %p\n", 422 i, threadsName[i], (void*)thread); 423 424 if (!NSK_JVMTI_VERIFY( 425 NSK_CPP_STUB2(SuspendThread, jvmti, thread))) { 426 nsk_jvmti_setFailStatus(); 427 return; 428 } 429 eventsEnd++; 430 431 break; 432 } 433 } 434 } 435 436 /* ============================================================================= */ 437 438 static volatile int testedThreadRunning = NSK_FALSE; 439 static volatile int testedThreadShouldFinish = NSK_FALSE; 440 441 /** Native running method in tested thread. */ 442 JNIEXPORT void JNICALL 443 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t003ThreadRunningNative_run(JNIEnv* jni, 444 jobject obj) { 445 volatile int i = 0, n = 1000; 446 447 /* run in a loop */ 448 testedThreadRunning = NSK_TRUE; 449 while (!testedThreadShouldFinish) { 450 if (n <= 0) 451 n = 1000; 452 if (i >= n) 453 i = 0; 454 i++; 455 } 456 testedThreadRunning = NSK_FALSE; 457 } 458 459 /** Wait for native method is running. */ 460 JNIEXPORT jboolean JNICALL 461 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t003ThreadRunningNative_checkStarted(JNIEnv* jni, 462 jobject obj) { 463 while (!testedThreadRunning) { 464 nsk_jvmti_sleep(1000); 465 } 466 return testedThreadRunning ? JNI_TRUE : JNI_FALSE; 467 } 468 469 /** Let native method to finish. */ 470 JNIEXPORT void JNICALL 471 Java_nsk_jvmti_scenarios_sampling_SP05_sp05t003ThreadRunningNative_letFinish(JNIEnv* jni, 472 jobject obj) { 473 testedThreadShouldFinish = NSK_TRUE; 474 } 475 476 /* ============================================================================= */ 477 478 /** Agent library initialization. */ 479 #ifdef STATIC_BUILD 480 JNIEXPORT jint JNICALL Agent_OnLoad_sp05t003(JavaVM *jvm, char *options, void *reserved) { 481 return Agent_Initialize(jvm, options, reserved); 482 } 483 JNIEXPORT jint JNICALL Agent_OnAttach_sp05t003(JavaVM *jvm, char *options, void *reserved) { 484 return Agent_Initialize(jvm, options, reserved); 485 } 486 JNIEXPORT jint JNI_OnLoad_sp05t003(JavaVM *jvm, char *options, void *reserved) { 487 return JNI_VERSION_1_8; 488 } 489 #endif 490 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 491 /* init framework and parse options */ 492 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 493 return JNI_ERR; 494 495 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 496 497 /* create JVMTI environment */ 498 if (!NSK_VERIFY((jvmti = 499 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 500 return JNI_ERR; 501 502 /* add capabilities for suspending thread */ 503 { 504 jvmtiCapabilities suspendCaps; 505 memset(&suspendCaps, 0, sizeof(suspendCaps)); 506 suspendCaps.can_suspend = 1; 507 if (!NSK_JVMTI_VERIFY( 508 NSK_CPP_STUB2(AddCapabilities, jvmti, &suspendCaps))) 509 return JNI_ERR; 510 } 511 512 /* set events callbacks */ 513 { 514 jvmtiEventCallbacks eventCallbacks; 515 memset(&eventCallbacks, 0, sizeof(eventCallbacks)); 516 eventCallbacks.ThreadStart = callbackThreadStart; 517 eventCallbacks.ThreadEnd = callbackThreadEnd; 518 if (!NSK_JVMTI_VERIFY( 519 NSK_CPP_STUB3(SetEventCallbacks, jvmti, 520 &eventCallbacks, sizeof(eventCallbacks)))) 521 return JNI_ERR; 522 } 523 524 /* register agent proc and arg */ 525 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 526 return JNI_ERR; 527 528 return JNI_OK; 529 } 530 531 /* ============================================================================= */ 532 533 }