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 /* constan names */ 38 #define THREAD_NAME "TestedThread" 39 40 /* constants */ 41 #define STORAGE_DATA_SIZE 1024 42 #define STORAGE_DATA_CHAR 'X' 43 #define EVENTS_COUNT 2 44 45 /* events list */ 46 static jvmtiEvent eventsList[EVENTS_COUNT] = { 47 JVMTI_EVENT_THREAD_START, 48 JVMTI_EVENT_THREAD_END 49 }; 50 51 /* storage structure */ 52 typedef struct _StorageStructure { 53 char data[STORAGE_DATA_SIZE]; 54 } StorageStructure; 55 56 /* storage data */ 57 static StorageStructure storageData; 58 static StorageStructure* initialStorage = &storageData; 59 60 /* events counts */ 61 static int eventsStart = 0; 62 static int eventsEnd = 0; 63 64 /* ============================================================================= */ 65 66 /** Agent algorithm. */ 67 static void JNICALL 68 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 69 70 NSK_DISPLAY0("Wait for thread to create\n"); 71 if (!nsk_jvmti_waitForSync(timeout)) 72 return; 73 74 /* perform testing */ 75 { 76 memset(storageData.data, STORAGE_DATA_CHAR, STORAGE_DATA_SIZE); 77 78 eventsStart = 0; 79 eventsEnd = 0; 80 NSK_DISPLAY1("Enable events: %d events\n", EVENTS_COUNT); 81 if (!nsk_jvmti_enableEvents(JVMTI_ENABLE, EVENTS_COUNT, eventsList, NULL)) 82 return; 83 84 NSK_DISPLAY0("Let tested thread to run\n"); 85 if (!nsk_jvmti_resumeSync()) 86 return; 87 88 NSK_DISPLAY0("Wait for tested thread to finish\n"); 89 if (!nsk_jvmti_waitForSync(timeout)) 90 return; 91 92 NSK_DISPLAY1("Disable events: %d events\n", EVENTS_COUNT); 93 if (!nsk_jvmti_enableEvents(JVMTI_DISABLE, EVENTS_COUNT, eventsList, NULL)) 94 return; 95 96 NSK_DISPLAY1("Check if all expected events received for tested thread: %s\n", 97 THREAD_NAME); 98 if (eventsStart <= 0 || eventsStart != eventsEnd) { 99 NSK_COMPLAIN3("Unexpected number of events received for tedted thread:\n" 100 "# thread name: %s\n" 101 "# THREAD_START: %d events\n" 102 "# THREAD_END: %d events\n", 103 THREAD_NAME, 104 eventsStart, eventsEnd); 105 nsk_jvmti_setFailStatus(); 106 } 107 } 108 109 NSK_DISPLAY0("Let debugee to finish\n"); 110 if (!nsk_jvmti_resumeSync()) 111 return; 112 } 113 114 /* ============================================================================= */ 115 116 /** THREAD_START callback. */ 117 JNIEXPORT void JNICALL 118 callbackThreadStart(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 119 /* check if event is for tested thread */ 120 if (thread != NULL) { 121 jvmtiThreadInfo info; 122 123 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(thread, &info))) { 124 nsk_jvmti_setFailStatus(); 125 return; 126 } 127 128 if (info.name != NULL && strcmp(info.name, THREAD_NAME) == 0) { 129 NSK_DISPLAY2(" ... received THREAD_START event for tested thread: %p (%s)\n", 130 (void*)thread, info.name); 131 eventsStart++; 132 133 NSK_DISPLAY1("SetThreadLocalStorage() for current thread with pointer: %p\n", 134 (void*)initialStorage); 135 if (!NSK_JVMTI_VERIFY(jvmti->SetThreadLocalStorage(NULL, (void*)initialStorage))) { 136 nsk_jvmti_setFailStatus(); 137 return; 138 } 139 } 140 } 141 } 142 143 144 /** THREAD_END callback. */ 145 JNIEXPORT void JNICALL 146 callbackThreadEnd(jvmtiEnv* jvmti, JNIEnv* jni, jthread thread) { 147 /* check if event is for tested thread */ 148 if (thread != NULL) { 149 jvmtiThreadInfo info; 150 151 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(thread, &info))) { 152 nsk_jvmti_setFailStatus(); 153 return; 154 } 155 156 if (info.name != NULL && strcmp(info.name, THREAD_NAME) == 0) { 157 NSK_DISPLAY2(" ... received THREAD_END event for tested thread: %p (%s)\n", 158 (void*)thread, info.name); 159 eventsEnd++; 160 161 /* get storage data */ 162 { 163 StorageStructure* obtainedStorage = NULL; 164 165 NSK_DISPLAY0("GetThreadLocalStorage() for current thread\n"); 166 if (!NSK_JVMTI_VERIFY( 167 jvmti->GetThreadLocalStorage(NULL, (void**)&obtainedStorage))) { 168 nsk_jvmti_setFailStatus(); 169 return; 170 } 171 NSK_DISPLAY1(" ... got pointer: %p\n", (void*)obtainedStorage); 172 173 NSK_DISPLAY0("Check storage data obtained for current thread\n"); 174 if (obtainedStorage != initialStorage) { 175 NSK_COMPLAIN3("Wrong storage pointer returned for current thread:\n" 176 "# thread: %p\n" 177 "# got pointer: %p\n" 178 "# expected: %p\n", 179 (void*)thread, 180 (void*)obtainedStorage, (void*)initialStorage); 181 nsk_jvmti_setFailStatus(); 182 } else { 183 int changed = 0; 184 int i; 185 186 for (i = 0; i < STORAGE_DATA_SIZE; i++) { 187 if (obtainedStorage->data[i] != STORAGE_DATA_CHAR) { 188 changed++; 189 } 190 } 191 192 if (changed > 0) { 193 NSK_COMPLAIN3("Data changed in returned storage for current thread:\n" 194 "# thread: %p\n" 195 "# changed bytes: %d\n" 196 "# total bytes: %d\n", 197 (void*)thread, 198 changed, STORAGE_DATA_SIZE); 199 nsk_jvmti_setFailStatus(); 200 } 201 } 202 } 203 } 204 } 205 } 206 207 /* ============================================================================= */ 208 209 /** Agent library initialization. */ 210 #ifdef STATIC_BUILD 211 JNIEXPORT jint JNICALL Agent_OnLoad_setthrdstor003(JavaVM *jvm, char *options, void *reserved) { 212 return Agent_Initialize(jvm, options, reserved); 213 } 214 JNIEXPORT jint JNICALL Agent_OnAttach_setthrdstor003(JavaVM *jvm, char *options, void *reserved) { 215 return Agent_Initialize(jvm, options, reserved); 216 } 217 JNIEXPORT jint JNI_OnLoad_setthrdstor003(JavaVM *jvm, char *options, void *reserved) { 218 return JNI_VERSION_1_8; 219 } 220 #endif 221 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 222 jvmtiEnv* jvmti = NULL; 223 224 /* init framework and parse options */ 225 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 226 return JNI_ERR; 227 228 timeout = nsk_jvmti_getWaitTime() * 60 * 1000; 229 230 /* create JVMTI environment */ 231 if (!NSK_VERIFY((jvmti = 232 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 233 return JNI_ERR; 234 235 /* set callbacks for thread events */ 236 { 237 jvmtiEventCallbacks callbacks; 238 memset(&callbacks, 0, sizeof(callbacks)); 239 callbacks.ThreadStart = callbackThreadStart; 240 callbacks.ThreadEnd = callbackThreadEnd; 241 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)))) 242 return JNI_ERR; 243 } 244 245 /* register agent proc and arg */ 246 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 247 return JNI_ERR; 248 249 return JNI_OK; 250 } 251 252 /* ============================================================================= */ 253 254 }