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