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(jvmti->GetAllThreads(&allThreadsCount, &allThreadsList))) 159 return NSK_FALSE; 160 161 if (!NSK_VERIFY(allThreadsCount > 0 && allThreadsList != NULL)) 162 return NSK_FALSE; 163 164 /* find tested threads */ 165 for (i = 0; i < allThreadsCount; i++) { 166 jvmtiThreadInfo threadInfo; 167 168 if (!NSK_VERIFY(allThreadsList[i] != NULL)) 169 return NSK_FALSE; 170 171 /* get thread name (info) */ 172 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(allThreadsList[i], &threadInfo))) 173 return NSK_FALSE; 174 175 /* find by name */ 176 if (threadInfo.name != NULL) { 177 int j; 178 179 for (j = 0; j < THREADS_COUNT; j++) { 180 if (strcmp(threadInfo.name, threadsName[j]) == 0) { 181 threadsList[j] = allThreadsList[i]; 182 NSK_DISPLAY3(" thread #%d (%s): %p\n", 183 j, threadInfo.name, (void*)threadsList[j]); 184 } 185 } 186 } 187 } 188 189 /* deallocate all threads list */ 190 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)allThreadsList))) 191 return NSK_FALSE; 192 193 /* check if all tested threads found */ 194 found = 0; 195 for (i = 0; i < THREADS_COUNT; i++) { 196 if (threadsList[i] == NULL) { 197 NSK_COMPLAIN2("Not found tested thread #%d (%s)\n", i, threadsName[i]); 198 } else { 199 found++; 200 } 201 } 202 203 if (found < THREADS_COUNT) 204 return NSK_FALSE; 205 206 /* make global refs */ 207 for (i = 0; i < THREADS_COUNT; i++) { 208 if (!NSK_JNI_VERIFY(jni, (threadsList[i] = jni->NewGlobalRef(threadsList[i])) != NULL)) 209 return NSK_FALSE; 210 } 211 212 return NSK_TRUE; 213 } 214 215 /** 216 * Suspend or resume tested threads. 217 */ 218 static int suspendThreadsIndividually(int suspend) { 219 int i; 220 221 for (i = 0; i < THREADS_COUNT; i++) { 222 if (suspend) { 223 NSK_DISPLAY2(" suspend thread #%d (%s)\n", i, threadsName[i]); 224 if (!NSK_JVMTI_VERIFY(jvmti->SuspendThread(threadsList[i]))) 225 nsk_jvmti_setFailStatus(); 226 } else { 227 NSK_DISPLAY2(" resume thread #%d (%s)\n", i, threadsName[i]); 228 if (!NSK_JVMTI_VERIFY(jvmti->ResumeThread(threadsList[i]))) 229 nsk_jvmti_setFailStatus(); 230 } 231 } 232 return NSK_TRUE; 233 } 234 235 /** 236 * Testcase: check tested threads 237 * - get thread state 238 * - wait for WAITIME if state is not expected 239 * - check if thread state is as expected 240 * 241 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 242 */ 243 static int checkThreads(int suspended, const char* kind, jlong timeout) { 244 int i; 245 246 /* check each thread */ 247 for (i = 0; i < THREADS_COUNT; i++) { 248 jthread thread = threadsList[i]; 249 jint state = JVMTI_THREAD_STATE_NOT_STARTED; 250 jlong t = 0; 251 252 NSK_DISPLAY2(" thread #%d (%s):\n", i, threadsName[i]); 253 254 /* wait for WAITTIME for thread to reach expected state */ 255 do { 256 /* get thread state */ 257 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadState(threadsList[i], &state))) { 258 nsk_jvmti_setFailStatus(); 259 return NSK_TRUE; 260 } 261 262 /* break if state is NOT_STARTED as expected */ 263 if (threadsState[i] == JVMTI_THREAD_STATE_NOT_STARTED 264 && state == threadsState[i]) 265 break; 266 267 /* break if state is as expected */ 268 if ((state & threadsState[i]) != 0) 269 break; 270 271 /* wait for one second */ 272 nsk_jvmti_sleep(1000); 273 t += 1000; 274 275 } while (t < timeout); 276 277 /* display thread state */ 278 NSK_DISPLAY2(" state = %s (%d)\n", 279 TranslateState(state), (int)state); 280 281 /* check thread state */ 282 if ((state & threadsState[i]) == 0) { 283 if (state == JVMTI_THREAD_STATE_NOT_STARTED) { 284 NSK_DISPLAY1("WARNING: state of thread #%d is NOT_STARTED\n", kind); 285 } else { 286 NSK_COMPLAIN7("Unexpected state of %s thread #%d (%s):\n" 287 "# got state: %s (%d)\n" 288 "# expected: %s (%d)\n", 289 kind, i, threadsName[i], 290 TranslateState(state), (int)state, 291 TranslateState(threadsState[i]), (int)threadsState[i]); 292 nsk_jvmti_setFailStatus(); 293 } 294 } 295 296 /* check SUSPENDED state flag */ 297 if (suspended) { 298 if (!(state & JVMTI_THREAD_STATE_SUSPENDED)) { 299 NSK_COMPLAIN5("No SUSPENDED state flag for %s thread #%d (%s):\n" 300 "# got flags: %s (%d)\n", 301 kind, i, threadsName[i], 302 TranslateState(state), (int)state); 303 nsk_jvmti_setFailStatus(); 304 } 305 } else { 306 if (state & JVMTI_THREAD_STATE_SUSPENDED) { 307 NSK_COMPLAIN5("Unexpected SUSPENDED state flag for %s thread #%d (%s):\n" 308 "# got flags: %s (%d)\n", 309 kind, i, threadsName[i], 310 TranslateState(state), (int)state); 311 nsk_jvmti_setFailStatus(); 312 } 313 } 314 315 /* check INTERRUPTED state flag */ 316 if (interruptedThreadIndex == i) { 317 if (!(state & JVMTI_THREAD_STATE_INTERRUPTED)) { 318 NSK_COMPLAIN5("No INTERRUPTED state flag for %s thread #%d (%s):\n" 319 "# got flags: %s (%d)\n", 320 kind, i, threadsName[i], 321 TranslateState(state), (int)state); 322 nsk_jvmti_setFailStatus(); 323 } 324 } else { 325 if (state & JVMTI_THREAD_STATE_INTERRUPTED) { 326 NSK_COMPLAIN5("Unexpected INTERRUPTED state flag for %s thread #%d (%s):\n" 327 "# got flags: %s (%d)\n", 328 kind, threadsName[i], i, 329 TranslateState(state), (int)state); 330 nsk_jvmti_setFailStatus(); 331 } 332 } 333 334 /* check NATIVE state flag */ 335 if (nativeThreadIndex == i) { 336 if (!(state & JVMTI_THREAD_STATE_IN_NATIVE)) { 337 NSK_COMPLAIN5("No NATIVE state flag for %s thread #%d (%s):\n" 338 "# got flags: %s (%d)\n", 339 kind, i, threadsName[i], 340 TranslateState(state), (int)state); 341 nsk_jvmti_setFailStatus(); 342 } 343 } else { 344 if (state & JVMTI_THREAD_STATE_IN_NATIVE) { 345 NSK_COMPLAIN5("Unexpected NATIVE state flag for %s thread #%d (%s):\n" 346 "# got flags: %s (%d)\n", 347 kind, i, threadsName[i], 348 TranslateState(state), (int)state); 349 nsk_jvmti_setFailStatus(); 350 } 351 } 352 } 353 354 /* test may continue */ 355 return NSK_TRUE; 356 } 357 358 /** 359 * Clean data: 360 * - dispose global references to tested threads 361 */ 362 static int clean() { 363 int i; 364 365 /* dispose global references to threads */ 366 for (i = 0; i < THREADS_COUNT; i++) { 367 NSK_TRACE(jni->DeleteGlobalRef(threadsList[i])); 368 } 369 370 return NSK_TRUE; 371 } 372 373 /* ============================================================================= */ 374 375 static volatile int testedThreadRunning = NSK_FALSE; 376 static volatile int testedThreadShouldFinish = NSK_FALSE; 377 378 /** Native running method in tested thread. */ 379 JNIEXPORT void JNICALL 380 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t002ThreadRunningNative_nativeMethod(JNIEnv* jni, 381 jobject obj) { 382 volatile int i = 0, n = 1000; 383 384 /* run in a loop */ 385 testedThreadRunning = NSK_TRUE; 386 while (!testedThreadShouldFinish) { 387 if (n <= 0) 388 n = 1000; 389 if (i >= n) 390 i = 0; 391 i++; 392 } 393 testedThreadRunning = NSK_FALSE; 394 } 395 396 /** Wait for native method is running. */ 397 JNIEXPORT jboolean JNICALL 398 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t002ThreadRunningNative_checkReady(JNIEnv* jni, 399 jobject obj) { 400 while (!testedThreadRunning) { 401 nsk_jvmti_sleep(1000); 402 } 403 return testedThreadRunning ? JNI_TRUE : JNI_FALSE; 404 } 405 406 /** Let native method to finish. */ 407 JNIEXPORT void JNICALL 408 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t002ThreadRunningNative_letFinish(JNIEnv* jni, 409 jobject obj) { 410 testedThreadShouldFinish = NSK_TRUE; 411 } 412 413 /* ============================================================================= */ 414 415 /** Agent library initialization. */ 416 #ifdef STATIC_BUILD 417 JNIEXPORT jint JNICALL Agent_OnLoad_sp01t002(JavaVM *jvm, char *options, void *reserved) { 418 return Agent_Initialize(jvm, options, reserved); 419 } 420 JNIEXPORT jint JNICALL Agent_OnAttach_sp01t002(JavaVM *jvm, char *options, void *reserved) { 421 return Agent_Initialize(jvm, options, reserved); 422 } 423 JNIEXPORT jint JNI_OnLoad_sp01t002(JavaVM *jvm, char *options, void *reserved) { 424 return JNI_VERSION_1_8; 425 } 426 #endif 427 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 428 429 /* init framework and parse options */ 430 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 431 return JNI_ERR; 432 433 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 434 435 /* create JVMTI environment */ 436 if (!NSK_VERIFY((jvmti = 437 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 438 return JNI_ERR; 439 440 /* add specific capabilities for suspending thread */ 441 { 442 jvmtiCapabilities suspendCaps; 443 memset(&suspendCaps, 0, sizeof(suspendCaps)); 444 suspendCaps.can_suspend = 1; 445 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&suspendCaps))) 446 return JNI_ERR; 447 } 448 449 /* register agent proc and arg */ 450 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 451 return JNI_ERR; 452 453 return JNI_OK; 454 } 455 456 /* ============================================================================= */ 457 458 }