1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <pthread.h> 18 19 #include <cstdio> 20 #include <iostream> 21 #include <vector> 22 23 #include "android-base/logging.h" 24 #include "jni.h" 25 #include "jvmti.h" 26 27 #include "scoped_local_ref.h" 28 #include "scoped_primitive_array.h" 29 30 // Test infrastructure 31 #include "jvmti_helper.h" 32 #include "test_env.h" 33 34 namespace art { 35 namespace Test1934SignalThreads { 36 37 struct NativeMonitor { 38 jrawMonitorID continue_monitor; 39 bool should_continue; 40 jrawMonitorID start_monitor; 41 bool should_start; 42 }; 43 44 extern "C" JNIEXPORT jlong JNICALL Java_art_Test1934_allocNativeMonitor(JNIEnv* env, jclass) { 45 NativeMonitor* mon; 46 if (JvmtiErrorToException(env, 47 jvmti_env, 48 jvmti_env->Allocate(sizeof(NativeMonitor), 49 reinterpret_cast<unsigned char**>(&mon)))) { 50 return -1L; 51 } 52 if (JvmtiErrorToException(env, 53 jvmti_env, 54 jvmti_env->CreateRawMonitor("test-1934 start", 55 &mon->start_monitor))) { 56 return -1L; 57 } 58 if (JvmtiErrorToException(env, 59 jvmti_env, 60 jvmti_env->CreateRawMonitor("test-1934 continue", 61 &mon->continue_monitor))) { 62 return -1L; 63 } 64 mon->should_continue = false; 65 mon->should_start = false; 66 return static_cast<jlong>(reinterpret_cast<intptr_t>(mon)); 67 } 68 69 extern "C" JNIEXPORT void Java_art_Test1934_nativeWaitForOtherThread(JNIEnv* env, 70 jclass, 71 jlong id) { 72 NativeMonitor* mon = reinterpret_cast<NativeMonitor*>(static_cast<intptr_t>(id)); 73 // Start 74 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(mon->start_monitor))) { 75 return; 76 } 77 mon->should_start = true; 78 if (JvmtiErrorToException(env, 79 jvmti_env, 80 jvmti_env->RawMonitorNotifyAll(mon->start_monitor))) { 81 JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(mon->start_monitor)); 82 return; 83 } 84 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(mon->start_monitor))) { 85 return; 86 } 87 88 // Finish 89 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(mon->continue_monitor))) { 90 return; 91 } 92 while (!mon->should_continue) { 93 if (JvmtiErrorToException(env, 94 jvmti_env, 95 jvmti_env->RawMonitorWait(mon->continue_monitor, -1L))) { 96 JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(mon->continue_monitor)); 97 return; 98 } 99 } 100 JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(mon->continue_monitor)); 101 } 102 103 extern "C" JNIEXPORT void Java_art_Test1934_nativeDoInterleaved(JNIEnv* env, 104 jclass, 105 jlong id, 106 jobject closure) { 107 NativeMonitor* mon = reinterpret_cast<NativeMonitor*>(static_cast<intptr_t>(id)); 108 // Wait for start. 109 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(mon->start_monitor))) { 110 return; 111 } 112 while (!mon->should_start) { 113 if (JvmtiErrorToException(env, 114 jvmti_env, 115 jvmti_env->RawMonitorWait(mon->start_monitor, -1L))) { 116 return; 117 } 118 } 119 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(mon->start_monitor))) { 120 return; 121 } 122 123 // Call closure. 124 ScopedLocalRef<jclass> runnable_klass(env, env->FindClass("java/lang/Runnable")); 125 if (env->ExceptionCheck()) { 126 return; 127 } 128 jmethodID doRun = env->GetMethodID(runnable_klass.get(), "run", "()V"); 129 if (env->ExceptionCheck()) { 130 return; 131 } 132 env->CallVoidMethod(closure, doRun); 133 134 // Tell other thread to finish. 135 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(mon->continue_monitor))) { 136 return; 137 } 138 mon->should_continue = true; 139 if (JvmtiErrorToException(env, 140 jvmti_env, 141 jvmti_env->RawMonitorNotifyAll(mon->continue_monitor))) { 142 JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(mon->continue_monitor)); 143 return; 144 } 145 JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(mon->continue_monitor)); 146 } 147 148 extern "C" JNIEXPORT void Java_art_Test1934_destroyNativeMonitor(JNIEnv*, jclass, jlong id) { 149 NativeMonitor* mon = reinterpret_cast<NativeMonitor*>(static_cast<intptr_t>(id)); 150 jvmti_env->DestroyRawMonitor(mon->start_monitor); 151 jvmti_env->DestroyRawMonitor(mon->continue_monitor); 152 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(mon)); 153 } 154 155 } // namespace Test1934SignalThreads 156 } // namespace art 157 158