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 statuses 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 suspendThreadsList(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 threads list\n"); 104 if (!suspendThreadsList(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 threads list\n"); 114 if (!suspendThreadsList(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 suspendThreadsList(int suspend) { 219 jvmtiError results[THREADS_COUNT]; 220 const char* kind = (suspend ? "suspending" : "resuming"); 221 int i; 222 223 /* suspend or resume threads list */ 224 if (suspend) { 225 if (!NSK_JVMTI_VERIFY(jvmti->SuspendThreadList(THREADS_COUNT, threadsList, results))) 226 nsk_jvmti_setFailStatus(); 227 } else { 228 if (!NSK_JVMTI_VERIFY(jvmti->ResumeThreadList(THREADS_COUNT, threadsList, results))) 229 nsk_jvmti_setFailStatus(); 230 } 231 232 /* check results */ 233 for (i = 0; i < THREADS_COUNT; i++) { 234 if (results[i] != JVMTI_ERROR_NONE) { 235 NSK_COMPLAIN5("Unexpected result of %s thread #%d (%s):\n" 236 "# got result: %s (%d)\n", 237 kind, i, threadsName[i], 238 TranslateError(results[i]), (int)results[i]); 239 nsk_jvmti_setFailStatus(); 240 } 241 } 242 243 return NSK_TRUE; 244 } 245 246 /** 247 * Testcase: check tested threads 248 * - get thread state and state flag 249 * - wait for WAITIME if state is not expected 250 * - check if thread state is as expected 251 * 252 * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break. 253 */ 254 static int checkThreads(int suspended, const char* kind, jlong timeout) { 255 int i; 256 257 /* check each thread */ 258 for (i = 0; i < THREADS_COUNT; i++) { 259 jthread thread = threadsList[i]; 260 jint state = JVMTI_THREAD_STATE_NOT_STARTED; 261 jlong t = 0; 262 263 NSK_DISPLAY2(" thread #%d (%s):\n", i, threadsName[i]); 264 265 /* wait for WAITTIME for thread to reach expected state */ 266 do { 267 /* get thread status */ 268 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadState(threadsList[i], &state))) { 269 nsk_jvmti_setFailStatus(); 270 return NSK_TRUE; 271 } 272 273 /* break if state is NOT_STARTED as expected */ 274 if (threadsState[i] == JVMTI_THREAD_STATE_NOT_STARTED 275 && state == threadsState[i]) 276 break; 277 278 /* break if state is as expected */ 279 if ((state & threadsState[i]) != 0) 280 break; 281 282 /* wait for one second */ 283 nsk_jvmti_sleep(1000); 284 t += 1000; 285 286 } while (t < timeout); 287 288 /* display thread status */ 289 NSK_DISPLAY2(" state = %s (%d)\n", 290 TranslateState(state), (int)state); 291 292 /* check thread status */ 293 if ((state & threadsState[i]) == 0) { 294 if (state == JVMTI_THREAD_STATE_NOT_STARTED) { 295 NSK_DISPLAY1("WARNING: status of thread #%d is UNKNOWN\n", kind); 296 } else { 297 NSK_COMPLAIN7("Unexpected status of %s thread #%d (%s):\n" 298 "# got status: %s (%d)\n" 299 "# expected: %s (%d)\n", 300 kind, i, threadsName[i], 301 TranslateState(state), (int)state, 302 TranslateState(threadsState[i]), (int)threadsState[i]); 303 nsk_jvmti_setFailStatus(); 304 } 305 } 306 307 /* check SUSPENDED state flag */ 308 if (suspended) { 309 if (!(state & JVMTI_THREAD_STATE_SUSPENDED)) { 310 NSK_COMPLAIN5("No SUSPENDED state flag for %s thread #%d (%s):\n" 311 "# got flags: %s (%d)\n", 312 kind, i, threadsName[i], 313 TranslateState(state), (int)state); 314 nsk_jvmti_setFailStatus(); 315 } 316 } else { 317 if (state & JVMTI_THREAD_STATE_SUSPENDED) { 318 NSK_COMPLAIN5("Unexpected SUSPENDED 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 } 325 326 /* check INTERRUPTED state flag */ 327 if (interruptedThreadIndex == i) { 328 if (!(state & JVMTI_THREAD_STATE_INTERRUPTED)) { 329 NSK_COMPLAIN5("No INTERRUPTED state flag for %s thread #%d (%s):\n" 330 "# got flags: %s (%d)\n", 331 kind, i, threadsName[i], 332 TranslateState(state), (int)state); 333 nsk_jvmti_setFailStatus(); 334 } 335 } else { 336 if (state & JVMTI_THREAD_STATE_INTERRUPTED) { 337 NSK_COMPLAIN5("Unexpected INTERRUPTED state flag for %s thread #%d (%s):\n" 338 "# got flags: %s (%d)\n", 339 kind, threadsName[i], i, 340 TranslateState(state), (int)state); 341 nsk_jvmti_setFailStatus(); 342 } 343 } 344 345 /* check NATIVE state flag */ 346 if (nativeThreadIndex == i) { 347 if (!(state & JVMTI_THREAD_STATE_IN_NATIVE)) { 348 NSK_COMPLAIN5("No NATIVE state flag for %s thread #%d (%s):\n" 349 "# got flags: %s (%d)\n", 350 kind, i, threadsName[i], 351 TranslateState(state), (int)state); 352 nsk_jvmti_setFailStatus(); 353 } 354 } else { 355 if (state & JVMTI_THREAD_STATE_IN_NATIVE) { 356 NSK_COMPLAIN5("Unexpected NATIVE state flag for %s thread #%d (%s):\n" 357 "# got flags: %s (%d)\n", 358 kind, i, threadsName[i], 359 TranslateState(state), (int)state); 360 nsk_jvmti_setFailStatus(); 361 } 362 } 363 } 364 365 /* test may continue */ 366 return NSK_TRUE; 367 } 368 369 /** 370 * Clean data: 371 * - dispose global references to tested threads 372 */ 373 static int clean() { 374 int i; 375 376 /* dispose global references to threads */ 377 for (i = 0; i < THREADS_COUNT; i++) { 378 NSK_TRACE(jni->DeleteGlobalRef(threadsList[i])); 379 } 380 381 return NSK_TRUE; 382 } 383 384 /* ============================================================================= */ 385 386 static volatile int testedThreadRunning = NSK_FALSE; 387 static volatile int testedThreadShouldFinish = NSK_FALSE; 388 389 /** Native running method in tested thread. */ 390 JNIEXPORT void JNICALL 391 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t003ThreadRunningNative_nativeMethod(JNIEnv* jni, 392 jobject obj) { 393 volatile int i = 0, n = 1000; 394 395 /* run in a loop */ 396 testedThreadRunning = NSK_TRUE; 397 while (!testedThreadShouldFinish) { 398 if (n <= 0) 399 n = 1000; 400 if (i >= n) 401 i = 0; 402 i++; 403 } 404 testedThreadRunning = NSK_FALSE; 405 } 406 407 /** Aait for native method is running. */ 408 JNIEXPORT jboolean JNICALL 409 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t003ThreadRunningNative_checkReady(JNIEnv* jni, 410 jobject obj) { 411 while (!testedThreadRunning) { 412 nsk_jvmti_sleep(1000); 413 } 414 return testedThreadRunning ? JNI_TRUE : JNI_FALSE; 415 } 416 417 /** Let native method to finish. */ 418 JNIEXPORT void JNICALL 419 Java_nsk_jvmti_scenarios_sampling_SP01_sp01t003ThreadRunningNative_letFinish(JNIEnv* jni, 420 jobject obj) { 421 testedThreadShouldFinish = NSK_TRUE; 422 } 423 424 /* ============================================================================= */ 425 426 /** Agent library initialization. */ 427 #ifdef STATIC_BUILD 428 JNIEXPORT jint JNICALL Agent_OnLoad_sp01t003(JavaVM *jvm, char *options, void *reserved) { 429 return Agent_Initialize(jvm, options, reserved); 430 } 431 JNIEXPORT jint JNICALL Agent_OnAttach_sp01t003(JavaVM *jvm, char *options, void *reserved) { 432 return Agent_Initialize(jvm, options, reserved); 433 } 434 JNIEXPORT jint JNI_OnLoad_sp01t003(JavaVM *jvm, char *options, void *reserved) { 435 return JNI_VERSION_1_8; 436 } 437 #endif 438 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 439 440 /* init framework and parse options */ 441 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 442 return JNI_ERR; 443 444 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 445 446 /* create JVMTI environment */ 447 if (!NSK_VERIFY((jvmti = 448 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 449 return JNI_ERR; 450 451 /* add specific capabilities for suspending thread */ 452 { 453 jvmtiCapabilities suspendCaps; 454 memset(&suspendCaps, 0, sizeof(suspendCaps)); 455 suspendCaps.can_suspend = 1; 456 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&suspendCaps))) 457 return JNI_ERR; 458 } 459 460 /* register agent proc and arg */ 461 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 462 return JNI_ERR; 463 464 return JNI_OK; 465 } 466 467 /* ============================================================================= */ 468 469 }