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