blob: dfb08c16219164143c1f7aee5a7d6b965f423369 [file] [log] [blame]
Alex Light54d39dc2017-09-25 17:00:16 -07001/*
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
34namespace art {
35namespace Test1934SignalThreads {
36
37struct NativeMonitor {
38 jrawMonitorID continue_monitor;
39 bool should_continue;
40 jrawMonitorID start_monitor;
41 bool should_start;
42};
43
44extern "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)))) {
Chih-Hung Hsieh457a0172018-12-10 13:08:27 -080050 return -1L;
Alex Light54d39dc2017-09-25 17:00:16 -070051 }
52 if (JvmtiErrorToException(env,
53 jvmti_env,
54 jvmti_env->CreateRawMonitor("test-1934 start",
55 &mon->start_monitor))) {
Chih-Hung Hsieh457a0172018-12-10 13:08:27 -080056 return -1L;
Alex Light54d39dc2017-09-25 17:00:16 -070057 }
58 if (JvmtiErrorToException(env,
59 jvmti_env,
60 jvmti_env->CreateRawMonitor("test-1934 continue",
61 &mon->continue_monitor))) {
Chih-Hung Hsieh457a0172018-12-10 13:08:27 -080062 return -1L;
Alex Light54d39dc2017-09-25 17:00:16 -070063 }
64 mon->should_continue = false;
65 mon->should_start = false;
66 return static_cast<jlong>(reinterpret_cast<intptr_t>(mon));
67}
68
69extern "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,
Chih-Hung Hsieh457a0172018-12-10 13:08:27 -080095 jvmti_env->RawMonitorWait(mon->continue_monitor, -1L))) {
Alex Light54d39dc2017-09-25 17:00:16 -070096 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
103extern "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,
Chih-Hung Hsieh457a0172018-12-10 13:08:27 -0800115 jvmti_env->RawMonitorWait(mon->start_monitor, -1L))) {
Alex Light54d39dc2017-09-25 17:00:16 -0700116 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
148extern "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