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 /* scaffold objects */ 35 static JNIEnv* jni = NULL; 36 static jvmtiEnv *jvmti = NULL; 37 static jlong timeout = 0; 38 39 /* number of tested threads */ 40 #define THREADS_COUNT 6 41 42 /* names of tested threads */ 43 static const char* threadsName[THREADS_COUNT] = { 44 "threadRunning", 45 "threadEntering", 46 "threadWaiting", 47 "threadSleeping", 48 "threadRunningInterrupted", 49 "threadRunningNative" 50 }; 51 52 /* expected states of tested threads */ 53 #define JVMTI_THREAD_STATE_NOT_STARTED 0 54 static jint threadsState[THREADS_COUNT] = { 55 JVMTI_THREAD_STATE_RUNNABLE, 56 JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER, 57 JVMTI_THREAD_STATE_IN_OBJECT_WAIT, 58 JVMTI_THREAD_STATE_SLEEPING, 59 JVMTI_THREAD_STATE_RUNNABLE, 60 JVMTI_THREAD_STATE_RUNNABLE 61 }; 62 63 /* references to tested threads */ 64 static jthread threadsList[THREADS_COUNT]; 65 66 /* indexes of known threads */ 67 static const int interruptedThreadIndex = THREADS_COUNT - 2; 68 static const int nativeThreadIndex = THREADS_COUNT - 1; 69 70 /* ============================================================================= */ 71 72 /* testcase(s) */ 73 static int prepare(); 74 static int checkThreads(int suspended, const char* kind, jlong timeout); 75 static int suspendThreadsIndividually(int suspend); 76 static int clean(); 77 78 /* ============================================================================= */ 79 80 /** Agent algorithm. */ 81 static void JNICALL 82 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { 83 jni = agentJNI; 84 85 /* wait for initial sync */ 86 if (!nsk_jvmti_waitForSync(timeout)) 87 return; 88 89 /* perform testcase(s) */ 90 { 91 /* prepare data: find threads */ 92 if (!prepare()) { 93 nsk_jvmti_setFailStatus(); 94 return; 95 } 96 97 /* testcase #1: check not suspended threads */ 98 NSK_DISPLAY0("Testcase #1: check state of not suspended threads\n"); 99 if (!checkThreads(NSK_FALSE, "not suspended", timeout)) 100 return; 101 102 /* suspend threads */ 103 NSK_DISPLAY0("Suspend each thread\n"); 104 if (!suspendThreadsIndividually(NSK_TRUE)) 105 return; 106 107 /* testcase #2: check suspended threads */ 108 NSK_DISPLAY0("Testcase #2: check state of suspended threads\n"); 109 if (!checkThreads(NSK_TRUE, "suspended", 0)) 110 return; 111 112 /* resume threads */ 113 NSK_DISPLAY0("Resume each thread\n"); 114 if (!suspendThreadsIndividually(NSK_FALSE)) 115 return; 116 117 /* testcase #3: check resumed threads */ 118 NSK_DISPLAY0("Testcase #3: check state of resumed threads\n"); 119 if (!checkThreads(NSK_FALSE, "resumed", 0)) 120 return; 121 122 /* clean date: delete threads references */ 123 if (!clean()) { 124 nsk_jvmti_setFailStatus(); 125 return; 126 } 127 } 128 129 /* resume debugee after last sync */ 130 if (!nsk_jvmti_resumeSync()) 131 return; 132 } 133 134 /* ============================================================================= */ 135 136 /** 137 * Prepare data: 138 * - clean threads list 139 * - get all live threads 140 * - get threads name 141 * - find tested threads 142 * - make global refs 143 */ 144 static int prepare() { 145 jthread *allThreadsList = NULL; 146 jint allThreadsCount = 0; 147 int found = 0; 148 int i; 149 150 NSK_DISPLAY1("Prepare: find tested threads: %d\n", THREADS_COUNT); 151 152 /* clean threads list */ 153 for (i = 0; i < THREADS_COUNT; i++) { 154 threadsList[i] = NULL; 155 } 156 157 /* get all live threads */ 158 if (!NSK_JVMTI_VERIFY( 159 NSK_CPP_STUB3(GetAllThreads, jvmti, &allThreadsCount, &allThreadsList))) 160 return NSK_FALSE; 161 162 if (!NSK_VERIFY(allThreadsCount > 0 && allThreadsList != NULL)) 163 return NSK_FALSE; 164 165 /* find tested threads */ 166 for (i = 0; i < allThreadsCount; i++) { 167 jvmtiThreadInfo threadInfo; 168 169 if (!NSK_VERIFY(allThreadsList[i] != NULL)) 170 return NSK_FALSE; 171 172 /* get thread name (info) */ 173 if (!NSK_JVMTI_VERIFY( 174 NSK_CPP_STUB3(GetThreadInfo, jvmti, allThreadsList[i], &threadInfo))) 175 return NSK_FALSE; 176 177 /* find by name */ 178 if (threadInfo.name != NULL) { 179 int j; 180 181 for (j = 0; j < THREADS_COUNT; j++) { 182 if (strcmp(threadInfo.name, threadsName[j]) == 0) { 183 threadsList[j] = allThreadsList[i]; 184 NSK_DISPLAY3(" thread #%d (%s): %p\n", 185 j, threadInfo.name, (void*)threadsList[j]); 186 } 187 } 188 } 189 } 190 191 /* deallocate all threads list */ 192 if (!NSK_JVMTI_VERIFY( 193 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)allThreadsList))) 194 return NSK_FALSE; 195 196 /* check if all tested threads found */ 197 found = 0; 198 for (i = 0; i < THREADS_COUNT; i++) { 199 if (threadsList[i] == NULL) { 200 NSK_COMPLAIN2("Not found tested thread #%d (%s)\n", i, threadsName[i]); 201 } else { 202 found++; 203 } 204 } 205 206 if (found < THREADS_COUNT) 207 return NSK_FALSE; 208 209 /* make global refs */ 210 for (i = 0; i < THREADS_COUNT; i++) { 211 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = 212 NSK_CPP_STUB2(NewGlobalRef, jni, threadsList[i])) != NULL)) 213 return NSK_FALSE; 214 } 215 216 return NSK_TRUE; 217 } 218 219 /** 220 * Suspend or resume tested threads. 221 */ 222 static int suspendThreadsIndividually(int suspend) { 223 int i; 224 225 for (i = 0; i < THREADS_COUNT; i++) { 226 if (suspend) { 227 NSK_DISPLAY2(" suspend thread #%d (%s)\n", i, threadsName[i]); 228 if (!NSK_JVMTI_VERIFY( 229 NSK_CPP_STUB2(SuspendThread, jvmti, threadsList[i]))) 230 nsk_jvmti_setFailStatus(); 231 } else { 232 NSK_DISPLAY2(" resume thread #%d (%s)\n", i, threadsName[i]); 233 if (!NSK_JVMTI_VERIFY( 234 NSK_CPP_STUB2(ResumeThread, jvmti, threadsList[i]))) 235 nsk_jvmti_setFailStatus(); 236 } 237 } 238 return NSK_TRUE; 239 } 240 241 /** 242 * Testcase: check tested threads 243 * - get thread state 244 * - wait for WAITIME if state is not expected 245 * - check if thread state is as expected 246 * 247 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 248 */ 249 static int checkThreads(int suspended, const char* kind, jlong timeout) { 250 int i; 251 252 /* check each thread */ 253 for (i = 0; i < THREADS_COUNT; i++) { 254 jthread thread = threadsList[i]; 255 jint state = JVMTI_THREAD_STATE_NOT_STARTED; 256 jlong t = 0; 257 258 NSK_DISPLAY2(" thread #%d (%s):\n", i, threadsName[i]); 259 260 /* wait for WAITTIME for thread to reach expected state */ 261 do { 262 /* get thread state */ 263 if (!NSK_JVMTI_VERIFY( 264 NSK_CPP_STUB3(GetThreadState, jvmti, threadsList[i], &state))) { 265 nsk_jvmti_setFailStatus(); 266 return NSK_TRUE; 267 } 268 269 /* break if state is NOT_STARTED as expected */ 270 if (threadsState[i] == JVMTI_THREAD_STATE_NOT_STARTED 271 && state == threadsState[i]) 272 break; 273 274 /* break if state is as expected */ 275 if ((state & threadsState[i]) != 0) 276 break; 277 278 /* wait for one second */ 279 nsk_jvmti_sleep(1000); 280 t += 1000; 281 282 } while (t < timeout); 283 284 /* display thread state */ 285 NSK_DISPLAY2(" state = %s (%d)\n", 286 TranslateState(state), (int)state); 287 288 /* check thread state */ 289 if ((state & threadsState[i]) == 0) { 290 if (state == JVMTI_THREAD_STATE_NOT_STARTED) { 291 NSK_DISPLAY1("WARNING: state of thread #%d is NOT_STARTED\n", kind); 292 } else { 293 NSK_COMPLAIN7("Unexpected state of %s thread #%d (%s):\n" 294 "# got state: %s (%d)\n" 295 "# expected: %s (%d)\n", 296 kind, i, threadsName[i], 297 TranslateState(state), (int)state, 298 TranslateState(threadsState[i]), (int)threadsState[i]); 299 nsk_jvmti_setFailStatus(); 300 } 301 } 302 303 /* check SUSPENDED state flag */ 304 if (suspended) { 305 if (!(state & JVMTI_THREAD_STATE_SUSPENDED)) { 306 NSK_COMPLAIN5("No SUSPENDED state flag for %s thread #%d (%s):\n" 307 "# got flags: %s (%d)\n", 308 kind, i, threadsName[i], 309 TranslateState(state), (int)state); 310 nsk_jvmti_setFailStatus(); 311 } 312 } else { 313 if (state & JVMTI_THREAD_STATE_SUSPENDED) { 314 NSK_COMPLAIN5("Unexpected SUSPENDED state flag for %s thread #%d (%s):\n" 315 "# got flags: %s (%d)\n", 316 kind, i, threadsName[i], 317 TranslateState(state), (int)state); 318 nsk_jvmti_setFailStatus(); 319 } 320 } 321 322 /* check INTERRUPTED state flag */ 323 if (interruptedThreadIndex == i) { 324 if (!(state & JVMTI_THREAD_STATE_INTERRUPTED)) { 325 NSK_COMPLAIN5("No INTERRUPTED state flag for %s thread #%d (%s):\n" 326 "# got flags: %s (%d)\n", 327 kind, i, threadsName[i], 328 TranslateState(state), (int)state); 329 nsk_jvmti_setFailStatus(); 330 } 331 } else { 332 if (state & JVMTI_THREAD_STATE_INTERRUPTED) { 333 NSK_COMPLAIN5("Unexpected INTERRUPTED state flag for %s thread #%d (%s):\n" 334 "# got flags: %s (%d)\n", 335 kind, threadsName[i], i, 336 TranslateState(state), (int)state); 337 nsk_jvmti_setFailStatus(); 338 } 339 } 340 341 /* check NATIVE state flag */ 342 if (nativeThreadIndex == i) { 343 if (!(state & JVMTI_THREAD_STATE_IN_NATIVE)) { 344 NSK_COMPLAIN5("No NATIVE state flag for %s thread #%d (%s):\n" 345 "# got flags: %s (%d)\n", 346 kind, i, threadsName[i], 347 TranslateState(state), (int)state); 348 nsk_jvmti_setFailStatus(); 349 } 350 } else { 351 if (state & JVMTI_THREAD_STATE_IN_NATIVE) { 352 NSK_COMPLAIN5("Unexpected NATIVE state flag for %s thread #%d (%s):\n" 353 "# got flags: %s (%d)\n", 354 kind, i, threadsName[i], 355 TranslateState(state), (int)state); 356 nsk_jvmti_setFailStatus(); 357 } 358 } 359 } 360 361 /* test may continue */ 362 return NSK_TRUE; 363 } 364 365 /** 366 * Clean data: 367 * - dispose global references to tested threads 368 */ 369 static int clean() { 370 int i; 371 372 /* dispose global references to threads */ 373 for (i = 0; i < THREADS_COUNT; i++) { 374 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, threadsList[i])); 375 } 376 377 return NSK_TRUE; 378 } 379 380 /* ============================================================================= */ 381 382 static volatile int testedThreadRunning = NSK_FALSE; 383 static volatile int testedThreadShouldFinish = NSK_FALSE; 384 385 /** Native running method in tested thread. */ 386 JNIEXPORT void JNICALL 387 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t002ThreadRunningNative_nativeMethod(JNIEnv* jni, 388 jobject obj) { 389 volatile int i = 0, n = 1000; 390 391 /* run in a loop */ 392 testedThreadRunning = NSK_TRUE; 393 while (!testedThreadShouldFinish) { 394 if (n <= 0) 395 n = 1000; 396 if (i >= n) 397 i = 0; 398 i++; 399 } 400 testedThreadRunning = NSK_FALSE; 401 } 402 403 /** Wait for native method is running. */ 404 JNIEXPORT jboolean JNICALL 405 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t002ThreadRunningNative_checkReady(JNIEnv* jni, 406 jobject obj) { 407 while (!testedThreadRunning) { 408 nsk_jvmti_sleep(1000); 409 } 410 return testedThreadRunning ? JNI_TRUE : JNI_FALSE; 411 } 412 413 /** Let native method to finish. */ 414 JNIEXPORT void JNICALL 415 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t002ThreadRunningNative_letFinish(JNIEnv* jni, 416 jobject obj) { 417 testedThreadShouldFinish = NSK_TRUE; 418 } 419 420 /* ============================================================================= */ 421 422 /** Agent library initialization. */ 423 #ifdef STATIC_BUILD 424 JNIEXPORT jint JNICALL Agent_OnLoad_sp01t002(JavaVM *jvm, char *options, void *reserved) { 425 return Agent_Initialize(jvm, options, reserved); 426 } 427 JNIEXPORT jint JNICALL Agent_OnAttach_sp01t002(JavaVM *jvm, char *options, void *reserved) { 428 return Agent_Initialize(jvm, options, reserved); 429 } 430 JNIEXPORT jint JNI_OnLoad_sp01t002(JavaVM *jvm, char *options, void *reserved) { 431 return JNI_VERSION_1_8; 432 } 433 #endif 434 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 435 436 /* init framework and parse options */ 437 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 438 return JNI_ERR; 439 440 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 441 442 /* create JVMTI environment */ 443 if (!NSK_VERIFY((jvmti = 444 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 445 return JNI_ERR; 446 447 /* add specific capabilities for suspending thread */ 448 { 449 jvmtiCapabilities suspendCaps; 450 memset(&suspendCaps, 0, sizeof(suspendCaps)); 451 suspendCaps.can_suspend = 1; 452 if (!NSK_JVMTI_VERIFY( 453 NSK_CPP_STUB2(AddCapabilities, jvmti, &suspendCaps))) 454 return JNI_ERR; 455 } 456 457 /* register agent proc and arg */ 458 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 459 return JNI_ERR; 460 461 return JNI_OK; 462 } 463 464 /* ============================================================================= */ 465 466 }