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 jlong timeout = 0; 36 37 /* constant names */ 38 #define THREAD_NAME "TestedThread" 39 #define N_LATE_CALLS 10000 40 41 /* ============================================================================= */ 42 43 /** Agent algorithm. */ 44 static void JNICALL 45 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 46 47 /* Original agentProc test block starts here: */ 48 NSK_DISPLAY0("Wait for thread to start\n"); 49 // SP2.1-n - notify agent is waiting and wait 50 // SP3.1-w - wait to start test 51 if (!nsk_jvmti_waitForSync(timeout)) 52 return; 53 54 /* perform testing */ 55 { 56 jthread testedThread = NULL; 57 int late_count; 58 59 NSK_DISPLAY1("Find thread: %s\n", THREAD_NAME); 60 if (!NSK_VERIFY((testedThread = 61 nsk_jvmti_threadByName(THREAD_NAME)) != NULL)) 62 return; 63 NSK_DISPLAY1(" ... found thread: %p\n", (void*)testedThread); 64 65 NSK_DISPLAY1("Suspend thread: %p\n", (void*)testedThread); 66 if (!NSK_JVMTI_VERIFY( 67 NSK_CPP_STUB2(SuspendThread, jvmti, testedThread))) { 68 nsk_jvmti_setFailStatus(); 69 return; 70 } 71 72 NSK_DISPLAY0("Let thread to run and finish\n"); 73 // SP5.1-n - notify suspend done 74 if (!nsk_jvmti_resumeSync()) 75 return; 76 77 NSK_DISPLAY1("Get state vector for thread: %p\n", (void*)testedThread); 78 { 79 jint state = 0; 80 81 if (!NSK_JVMTI_VERIFY( 82 NSK_CPP_STUB3(GetThreadState, jvmti, testedThread, &state))) { 83 nsk_jvmti_setFailStatus(); 84 } 85 NSK_DISPLAY2(" ... got state vector: %s (%d)\n", 86 TranslateState(state), (int)state); 87 88 if ((state & JVMTI_THREAD_STATE_SUSPENDED) == 0) { 89 NSK_COMPLAIN2("SuspendThread() does not turn on flag SUSPENDED:\n" 90 "# state: %s (%d)\n", 91 TranslateState(state), (int)state); 92 nsk_jvmti_setFailStatus(); 93 } 94 } 95 96 NSK_DISPLAY1("Resume thread: %p\n", (void*)testedThread); 97 if (!NSK_JVMTI_VERIFY( 98 NSK_CPP_STUB2(ResumeThread, jvmti, testedThread))) { 99 nsk_jvmti_setFailStatus(); 100 } 101 /* Original agentProc test block ends here. */ 102 103 /* 104 * Using printf() instead of NSK_DISPLAY1() in this loop 105 * in order to slow down the rate of SuspendThread() calls. 106 */ 107 for (late_count = 0; late_count < N_LATE_CALLS; late_count++) { 108 jvmtiError l_err; 109 printf("INFO: Late suspend thread: %p\n", (void*)testedThread); 110 l_err = NSK_CPP_STUB2(SuspendThread, jvmti, testedThread); 111 if (l_err != JVMTI_ERROR_NONE) { 112 printf("INFO: Late suspend thread err: %d\n", l_err); 113 // testedThread has exited so we're done with late calls 114 break; 115 } 116 117 // Only resume a thread if suspend worked. Using NSK_DISPLAY1() 118 // here because we want ResumeThread() to be faster. 119 NSK_DISPLAY1("INFO: Late resume thread: %p\n", (void*)testedThread); 120 if (!NSK_JVMTI_VERIFY( 121 NSK_CPP_STUB2(ResumeThread, jvmti, testedThread))) { 122 nsk_jvmti_setFailStatus(); 123 } 124 } 125 126 printf("INFO: made %d late calls to JVM/TI SuspendThread()\n", 127 late_count); 128 printf("INFO: N_LATE_CALLS==%d value is %slarge enough to cause a " 129 "SuspendThread() call after thread exit.\n", N_LATE_CALLS, 130 (late_count == N_LATE_CALLS) ? "NOT " : ""); 131 132 /* Second part of original agentProc test block starts here: */ 133 NSK_DISPLAY0("Wait for thread to finish\n"); 134 // SP4.1-n - notify agent is waiting and wait 135 // SP6.1-w - wait to end test 136 if (!nsk_jvmti_waitForSync(timeout)) 137 return; 138 139 NSK_DISPLAY0("Delete thread reference\n"); 140 NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, testedThread)); 141 } 142 143 NSK_DISPLAY0("Let debugee to finish\n"); 144 // SP7.1-n - notify agent end 145 if (!nsk_jvmti_resumeSync()) 146 return; 147 /* Second part of original agentProc test block ends here. */ 148 } 149 150 /* ============================================================================= */ 151 152 /** Agent library initialization. */ 153 #ifdef STATIC_BUILD 154 JNIEXPORT jint JNICALL Agent_OnLoad_suspendthrd003(JavaVM *jvm, char *options, void *reserved) { 155 return Agent_Initialize(jvm, options, reserved); 156 } 157 JNIEXPORT jint JNICALL Agent_OnAttach_suspendthrd003(JavaVM *jvm, char *options, void *reserved) { 158 return Agent_Initialize(jvm, options, reserved); 159 } 160 JNIEXPORT jint JNI_OnLoad_suspendthrd003(JavaVM *jvm, char *options, void *reserved) { 161 return JNI_VERSION_1_8; 162 } 163 #endif 164 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 165 jvmtiEnv* jvmti = NULL; 166 167 /* init framework and parse options */ 168 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 169 return JNI_ERR; 170 171 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 172 173 /* create JVMTI environment */ 174 if (!NSK_VERIFY((jvmti = 175 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 176 return JNI_ERR; 177 178 /* add specific capabilities for suspending thread */ 179 { 180 jvmtiCapabilities suspendCaps; 181 memset(&suspendCaps, 0, sizeof(suspendCaps)); 182 suspendCaps.can_suspend = 1; 183 if (!NSK_JVMTI_VERIFY( 184 NSK_CPP_STUB2(AddCapabilities, jvmti, &suspendCaps))) 185 return JNI_ERR; 186 } 187 188 /* register agent proc and arg */ 189 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 190 return JNI_ERR; 191 192 return JNI_OK; 193 } 194 195 /* ============================================================================= */ 196 197 }