1 /* 2 * Copyright (c) 2004, 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 <stdlib.h> 25 #include <string.h> 26 #include "jni_tools.h" 27 #include "agent_common.h" 28 #include "jvmti_tools.h" 29 30 extern "C" { 31 32 /* ========================================================================== */ 33 34 static const jlong EXPECTED_TIMEOUT = 1; 35 /* 36 * The expected timeout accuracy was already increased from 100000 to 300000. 37 * Please, do not increase it anymore if the test still fails with the message: 38 * "(waitedTime - waitTime) >= (EXPECTED_TIMEOUT * 1000000) - EXPECTED_TIMEOUT_ACCURACY_NS" 39 */ 40 static const jlong EXPECTED_TIMEOUT_ACCURACY_NS = 300000; 41 42 static const jlong EXPECTED_ACCURACY = 10; 43 44 /* scaffold objects */ 45 static jlong timeout = 0; 46 47 /* test objects */ 48 static jthread thread = NULL; 49 static jobject object_M = NULL; 50 static volatile int waitEventsCount = 0; 51 static volatile int waitedEventsCount = 0; 52 static jlong waitTime = 0; 53 static jlong waitThreadCpuTime = 0; 54 static jlong waitedTime = 0; 55 static jlong waitedThreadCpuTime = 0; 56 57 /* ========================================================================== */ 58 59 void JNICALL 60 MonitorWait(jvmtiEnv *jvmti, JNIEnv* jni, 61 jthread thr, jobject obj, jlong tout) { 62 char buffer[32]; 63 64 if (!NSK_VERIFY(thr != NULL)) { 65 nsk_jvmti_setFailStatus(); 66 return; 67 } 68 69 if (!NSK_VERIFY(obj != NULL)) { 70 nsk_jvmti_setFailStatus(); 71 return; 72 } 73 74 /* check if event is for tested thread and object */ 75 if (jni->IsSameObject(thread, thr) && 76 jni->IsSameObject(object_M, obj)) { 77 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadCpuTime(thr, &waitThreadCpuTime))) { 78 nsk_jvmti_setFailStatus(); 79 } 80 if (!NSK_JVMTI_VERIFY(jvmti->GetTime(&waitTime))) { 81 nsk_jvmti_setFailStatus(); 82 } 83 waitEventsCount++; 84 NSK_DISPLAY0("MonitorWait event:\n"); 85 NSK_DISPLAY3("\tthread: %p, object: %p, timeout: %s\n", 86 thr, obj, jlong_to_string(tout, buffer)); 87 NSK_DISPLAY1("\ttime: %s\n", 88 jlong_to_string(waitTime, buffer)); 89 NSK_DISPLAY1("\tthread CPU time: %s\n", 90 jlong_to_string(waitThreadCpuTime, buffer)); 91 92 if (!NSK_VERIFY(tout == EXPECTED_TIMEOUT)) { 93 nsk_jvmti_setFailStatus(); 94 } 95 } 96 } 97 98 void JNICALL 99 MonitorWaited(jvmtiEnv *jvmti, JNIEnv* jni, 100 jthread thr, jobject obj, jboolean timed_out) { 101 char buffer[32]; 102 103 if (!NSK_VERIFY(thr != NULL)) { 104 nsk_jvmti_setFailStatus(); 105 return; 106 } 107 108 if (!NSK_VERIFY(obj != NULL)) { 109 nsk_jvmti_setFailStatus(); 110 return; 111 } 112 113 /* check if event is for tested thread and object */ 114 if (jni->IsSameObject(thread, thr) && 115 jni->IsSameObject(object_M, obj)) { 116 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadCpuTime(thr, &waitedThreadCpuTime))) { 117 nsk_jvmti_setFailStatus(); 118 } 119 if (!NSK_JVMTI_VERIFY(jvmti->GetTime(&waitedTime))) { 120 nsk_jvmti_setFailStatus(); 121 } 122 waitedEventsCount++; 123 NSK_DISPLAY0("MonitorWaited event:\n"); 124 NSK_DISPLAY3("\tthread: %p, object: %p, timed_out: %s\n", 125 thr, obj, (timed_out==JNI_TRUE) ? "true" : "false"); 126 NSK_DISPLAY1("\tGetTime: %s\n", 127 jlong_to_string(waitedTime, buffer)); 128 NSK_DISPLAY1("\tthread CPU time: %s\n", 129 jlong_to_string(waitedThreadCpuTime, buffer)); 130 } 131 } 132 133 /* ========================================================================== */ 134 135 static int prepare(jvmtiEnv* jvmti, JNIEnv* jni) { 136 const char* THREAD_NAME = "Debuggee Thread"; 137 const char* FIELD_SIG = "Ljava/lang/Object;"; 138 jvmtiThreadInfo info; 139 jthread *threads = NULL; 140 jint threads_count = 0; 141 jfieldID field = NULL; 142 jclass klass = NULL; 143 int i; 144 145 NSK_DISPLAY0("Prepare: find tested thread\n"); 146 147 /* get all live threads */ 148 if (!NSK_JVMTI_VERIFY(jvmti->GetAllThreads(&threads_count, &threads))) 149 return NSK_FALSE; 150 151 if (!NSK_VERIFY(threads_count > 0 && threads != NULL)) 152 return NSK_FALSE; 153 154 /* find tested thread */ 155 for (i = 0; i < threads_count; i++) { 156 if (!NSK_VERIFY(threads[i] != NULL)) 157 return NSK_FALSE; 158 159 /* get thread information */ 160 if (!NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(threads[i], &info))) 161 return NSK_FALSE; 162 163 NSK_DISPLAY3(" thread #%d (%s): %p\n", i, info.name, threads[i]); 164 165 /* find by name */ 166 if (info.name != NULL && (strcmp(info.name, THREAD_NAME) == 0)) { 167 thread = threads[i]; 168 } 169 170 if (info.name != NULL) { 171 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)info.name))) 172 return NSK_FALSE; 173 } 174 } 175 176 /* deallocate threads list */ 177 if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threads))) 178 return NSK_FALSE; 179 180 if (thread == NULL) { 181 NSK_COMPLAIN0("Debuggee thread not found"); 182 return NSK_FALSE; 183 } 184 185 /* make thread accessable for a long time */ 186 if (!NSK_JNI_VERIFY(jni, (thread = jni->NewGlobalRef(thread)) != NULL)) 187 return NSK_FALSE; 188 189 /* get tested thread class */ 190 if (!NSK_JNI_VERIFY(jni, (klass = jni->GetObjectClass(thread)) != NULL)) 191 return NSK_FALSE; 192 193 /* get tested thread field 'M' */ 194 if (!NSK_JNI_VERIFY(jni, (field = jni->GetFieldID(klass, "M", FIELD_SIG)) != NULL)) 195 return NSK_FALSE; 196 197 if (!NSK_JNI_VERIFY(jni, (object_M = jni->GetObjectField(thread, field)) != NULL)) 198 return NSK_FALSE; 199 200 /* make object accessable for a long time */ 201 if (!NSK_JNI_VERIFY(jni, (object_M = jni->NewGlobalRef(object_M)) != NULL)) 202 return NSK_FALSE; 203 204 /* enable MonitorWait event */ 205 if (!NSK_JVMTI_VERIFY( 206 jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAIT, NULL))) 207 return NSK_FALSE; 208 209 /* enable MonitorWaited event */ 210 if (!NSK_JVMTI_VERIFY( 211 jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAITED, NULL))) 212 return NSK_FALSE; 213 214 return NSK_TRUE; 215 } 216 217 static int clean(jvmtiEnv* jvmti, JNIEnv* jni) { 218 219 /* disable MonitorWait event */ 220 if (!NSK_JVMTI_VERIFY( 221 jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_MONITOR_WAIT, NULL))) 222 nsk_jvmti_setFailStatus(); 223 224 /* disable MonitorWaited event */ 225 if (!NSK_JVMTI_VERIFY( 226 jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_MONITOR_WAITED, NULL))) 227 nsk_jvmti_setFailStatus(); 228 229 return NSK_TRUE; 230 } 231 232 /* ========================================================================== */ 233 234 /* agent algorithm */ 235 static void JNICALL 236 agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { 237 char buffer[32]; 238 239 /* wait for initial sync */ 240 if (!nsk_jvmti_waitForSync(timeout)) 241 return; 242 243 if (!prepare(jvmti, jni)) { 244 nsk_jvmti_setFailStatus(); 245 return; 246 } 247 248 /* resume debugee to catch MonitorContendedEntered events */ 249 if (!(NSK_VERIFY(nsk_jvmti_resumeSync()) && 250 NSK_VERIFY(nsk_jvmti_waitForSync(timeout)))) 251 return; 252 253 NSK_DISPLAY1("Number of MonitorWait events: %d\n", waitEventsCount); 254 if (!(NSK_VERIFY(waitEventsCount == 1))) { 255 nsk_jvmti_setFailStatus(); 256 } 257 258 NSK_DISPLAY1("Number of MonitorWaited events: %d\n", waitedEventsCount); 259 if (!(NSK_VERIFY(waitedEventsCount == 1))) { 260 nsk_jvmti_setFailStatus(); 261 } 262 263 NSK_DISPLAY1("Time frame between the events: %s ns\n", 264 jlong_to_string(waitedTime - waitTime, buffer)); 265 if (!(NSK_VERIFY((waitedTime - waitTime) >= (EXPECTED_TIMEOUT * 1000000) - EXPECTED_TIMEOUT_ACCURACY_NS))) { 266 #if (defined(WIN32) || defined(_WIN32)) 267 /* Do not fail on Windows as spurious wakeups are expected. The JDK-6313903 was closed as "Won't Fix". */ 268 #else 269 nsk_jvmti_setFailStatus(); 270 #endif 271 printf("waitedTime: %" LL "d, waitTime: %" LL "d, waitedTime - waitTime: %" LL "d\n", 272 waitedTime, waitTime, waitedTime - waitTime); 273 } 274 275 NSK_DISPLAY1("Thread CPU time between the events: %s ns\n", 276 jlong_to_string(waitedThreadCpuTime - waitThreadCpuTime, buffer)); 277 if (!(NSK_VERIFY((waitedThreadCpuTime - waitThreadCpuTime) 278 < (EXPECTED_ACCURACY * 1000000)))) { 279 nsk_jvmti_setFailStatus(); 280 printf("waitedThreadCpuTime: %" LL "d, waitThreadCpuTime: %" LL "d, waitedThreadCpuTime - waitThreadCpuTime: %" LL "d\n", 281 waitedThreadCpuTime, waitThreadCpuTime, waitedThreadCpuTime - waitThreadCpuTime); 282 } 283 284 if (!clean(jvmti, jni)) { 285 nsk_jvmti_setFailStatus(); 286 return; 287 } 288 289 /* resume debugee after last sync */ 290 if (!nsk_jvmti_resumeSync()) 291 return; 292 } 293 294 /* ========================================================================== */ 295 296 /* agent library initialization */ 297 #ifdef STATIC_BUILD 298 JNIEXPORT jint JNICALL Agent_OnLoad_tc05t001(JavaVM *jvm, char *options, void *reserved) { 299 return Agent_Initialize(jvm, options, reserved); 300 } 301 JNIEXPORT jint JNICALL Agent_OnAttach_tc05t001(JavaVM *jvm, char *options, void *reserved) { 302 return Agent_Initialize(jvm, options, reserved); 303 } 304 JNIEXPORT jint JNI_OnLoad_tc05t001(JavaVM *jvm, char *options, void *reserved) { 305 return JNI_VERSION_1_8; 306 } 307 #endif 308 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { 309 jvmtiEnv* jvmti = NULL; 310 jvmtiCapabilities caps; 311 jvmtiEventCallbacks callbacks; 312 313 /* init framework and parse options */ 314 if (!NSK_VERIFY(nsk_jvmti_parseOptions(options))) 315 return JNI_ERR; 316 317 timeout = nsk_jvmti_getWaitTime() * 60000; 318 NSK_DISPLAY1("Timeout: %d msc\n", (int)timeout); 319 320 /* create JVMTI environment */ 321 if (!NSK_VERIFY((jvmti = 322 nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL)) 323 return JNI_ERR; 324 325 /* add capabilities */ 326 memset(&caps, 0, sizeof(caps)); 327 caps.can_generate_monitor_events = 1; 328 caps.can_get_thread_cpu_time = 1; 329 if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps))) 330 return JNI_ERR; 331 332 memset(&callbacks, 0, sizeof(callbacks)); 333 callbacks.MonitorWait = &MonitorWait; 334 callbacks.MonitorWaited = &MonitorWaited; 335 if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)))) 336 return JNI_ERR; 337 338 /* register agent proc and arg */ 339 if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) 340 return JNI_ERR; 341 342 return JNI_OK; 343 } 344 345 /* ========================================================================== */ 346 347 }