1 /* 2 * Copyright (c) 2007, 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 /* 25 */ 26 27 #include <stdio.h> 28 #include <string.h> 29 #include "jvmti.h" 30 #include "agent_common.h" 31 32 #ifndef STANDALONE 33 #include "JVMTITools.h" 34 #endif 35 36 extern "C" { 37 38 39 #define THREAD_STATE_MASK ~(JVMTI_THREAD_STATE_SUSPENDED \ 40 | JVMTI_THREAD_STATE_INTERRUPTED \ 41 | JVMTI_THREAD_STATE_IN_NATIVE \ 42 | JVMTI_THREAD_STATE_VENDOR_1 \ 43 | JVMTI_THREAD_STATE_VENDOR_2 \ 44 | JVMTI_THREAD_STATE_VENDOR_3) 45 46 static int g_ThreadState[] = { 47 0, /* TS_NEW */ 48 JVMTI_THREAD_STATE_TERMINATED, /* TS_TERMINATED */ 49 JVMTI_THREAD_STATE_ALIVE 50 | JVMTI_THREAD_STATE_RUNNABLE, /* TS_RUN_RUNNING */ 51 JVMTI_THREAD_STATE_ALIVE 52 | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER, /* TS_RUN_BLOCKED */ 53 JVMTI_THREAD_STATE_ALIVE 54 | JVMTI_THREAD_STATE_IN_OBJECT_WAIT 55 | JVMTI_THREAD_STATE_WAITING 56 | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT, /* TS_RUN_WAIT_TIMED */ 57 JVMTI_THREAD_STATE_ALIVE 58 | JVMTI_THREAD_STATE_IN_OBJECT_WAIT 59 | JVMTI_THREAD_STATE_WAITING 60 | JVMTI_THREAD_STATE_WAITING_INDEFINITELY, /* TS_RUN_WAIT_INDEF */ 61 JVMTI_THREAD_STATE_ALIVE 62 | JVMTI_THREAD_STATE_PARKED 63 | JVMTI_THREAD_STATE_WAITING 64 | JVMTI_THREAD_STATE_WAITING_INDEFINITELY, /* TS_RUN_WAIT_PARKED_INDEF */ 65 JVMTI_THREAD_STATE_ALIVE 66 | JVMTI_THREAD_STATE_PARKED 67 | JVMTI_THREAD_STATE_WAITING 68 | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT, /* TS_RUN_WAIT_PARKED_TIMED */ 69 JVMTI_THREAD_STATE_ALIVE 70 | JVMTI_THREAD_STATE_SLEEPING 71 | JVMTI_THREAD_STATE_WAITING 72 | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT, /* TS_RUN_WAIT_SLEEPING */ 73 }; 74 75 static jvmtiEnv * g_ppJvmtiEnv = NULL; 76 static int g_waitTime = 1000; 77 jrawMonitorID g_waitMon; /* Monitor is used just for sleeping */ 78 79 void reportError(const char * szErr, jvmtiError res) { 80 #ifndef STANDALONE 81 printf("%s (%d: %s)\n", szErr, res, TranslateError(res)); 82 #else 83 printf("%s (%d)\n", szErr, res); 84 #endif 85 fflush(stdout); 86 } 87 88 #ifdef STATIC_BUILD 89 JNIEXPORT jint JNICALL Agent_OnLoad_thrstat005(JavaVM *jvm, char *options, void *reserved) { 90 return Agent_Initialize(jvm, options, reserved); 91 } 92 JNIEXPORT jint JNICALL Agent_OnAttach_thrstat005(JavaVM *jvm, char *options, void *reserved) { 93 return Agent_Initialize(jvm, options, reserved); 94 } 95 JNIEXPORT jint JNI_OnLoad_thrstat005(JavaVM *jvm, char *options, void *reserved) { 96 return JNI_VERSION_1_8; 97 } 98 #endif 99 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 100 jvmtiError error; 101 jint res; 102 103 res = jvm->GetEnv((void **) &g_ppJvmtiEnv, JVMTI_VERSION_1_1); 104 if ( res != JNI_OK || ! g_ppJvmtiEnv ) { 105 printf("Agent_OnLoad: Error: GetEnv returned error or NULL\n"); 106 return JNI_ERR; 107 } 108 109 error = g_ppJvmtiEnv->CreateRawMonitor("beast", &g_waitMon); 110 if ( error != JVMTI_ERROR_NONE ) { 111 reportError("Agent_OnLoad: error creating raw monitor", error); 112 return JNI_ERR; 113 } 114 115 return JNI_OK; 116 } 117 118 JNIEXPORT void JNICALL 119 Java_nsk_jvmti_GetThreadState_thrstat005_setWaitTime(JNIEnv * pEnv, jclass klass, jint waitTime) { 120 g_waitTime = waitTime; 121 } 122 123 JNIEXPORT jboolean JNICALL 124 Java_nsk_jvmti_GetThreadState_thrstat005_checkThreadState(JNIEnv * pEnv, jclass klass, jthread thread, jint stateIdx) { 125 126 jint thrState; 127 jint maskedThrState; 128 int waitTime = 10; 129 130 /* Repeat querying status until waitTime < g_waitTime */ 131 do { 132 jvmtiError res = g_ppJvmtiEnv->GetThreadState(thread, &thrState); 133 if (res != JVMTI_ERROR_NONE) { 134 reportError("GetThreadState: unexpected error", res); 135 return JNI_FALSE; 136 } 137 138 maskedThrState = thrState & THREAD_STATE_MASK; 139 printf("GetThreadState = %x. Masked: %x. Must be: %x\n", thrState, maskedThrState, g_ThreadState[stateIdx]); 140 fflush(stdout); 141 142 if ( maskedThrState == g_ThreadState[stateIdx] ) 143 return JNI_TRUE; 144 145 printf("checkThreadState: wait %d ms\n", waitTime); 146 fflush(stdout); 147 if ( (res = g_ppJvmtiEnv->RawMonitorEnter(g_waitMon)) != JVMTI_ERROR_NONE 148 || (res = g_ppJvmtiEnv->RawMonitorWait(g_waitMon, waitTime)) != JVMTI_ERROR_NONE 149 || (res = g_ppJvmtiEnv->RawMonitorExit(g_waitMon)) != JVMTI_ERROR_NONE ) { 150 reportError("GetThreadState: unexpected error", res); 151 return JNI_FALSE; 152 } 153 154 waitTime <<= 1; 155 156 } while ( waitTime < g_waitTime ); 157 158 return JNI_FALSE; 159 } 160 161 }