Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/SuspendWithObjectMonitorWait/SuspendWithObjectMonitorWait.java
41153 views
1
/*
2
* Copyright (c) 2001, 2021, 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
* @test
26
* @bug 4413752 8262881
27
* @summary Test SuspendThread with ObjectMonitor wait.
28
* @requires vm.jvmti
29
* @library /test/lib
30
* @compile SuspendWithObjectMonitorWait.java
31
* @run main/othervm/native -agentlib:SuspendWithObjectMonitorWait SuspendWithObjectMonitorWait
32
*/
33
34
import java.io.PrintStream;
35
36
//
37
// main waiter resumer
38
// ================= ================== ===================
39
// launch waiter
40
// <launch returns> waiter running
41
// launch resumer enter threadLock
42
// <launch returns> threadLock.wait() resumer running
43
// enter threadLock : wait for notify
44
// threadLock.notify wait finishes :
45
// : reenter blocks :
46
// suspend waiter <suspended> :
47
// exit threadLock : :
48
// <ready to test> : :
49
// : : :
50
// notify resumer : wait finishes
51
// join resumer : enter threadLock
52
// : <resumed> resume waiter
53
// : : exit threadLock
54
// : reenter threadLock :
55
// <join returns> : resumer exits
56
// join waiter :
57
// <join returns> waiter exits
58
//
59
60
public class SuspendWithObjectMonitorWait {
61
private static final String AGENT_LIB = "SuspendWithObjectMonitorWait";
62
private static final int exit_delta = 95;
63
64
private static final int DEF_TIME_MAX = 60; // default max # secs to test
65
private static final int JOIN_MAX = 30; // max # secs to wait for join
66
67
public static final int TS_INIT = 1; // initial testState
68
public static final int TS_WAITER_RUNNING = 2; // waiter is running
69
public static final int TS_RESUMER_RUNNING = 3; // resumer is running
70
public static final int TS_READY_TO_NOTIFY = 4; // ready to notify threadLock
71
public static final int TS_CALL_SUSPEND = 5; // call suspend on contender
72
public static final int TS_READY_TO_RESUME = 6; // ready to resume waiter
73
public static final int TS_CALL_RESUME = 7; // call resume on waiter
74
public static final int TS_WAITER_DONE = 8; // waiter has run; done
75
76
public static Object barrierLaunch = new Object(); // controls thread launch
77
public static Object barrierResumer = new Object(); // controls resumer
78
public static Object threadLock = new Object(); // testing object
79
80
public static long count = 0;
81
public static boolean printDebug = false;
82
public volatile static int testState;
83
84
private static void log(String msg) { System.out.println(msg); }
85
86
native static int suspendThread(SuspendWithObjectMonitorWaitWorker thr);
87
native static int wait4ContendedEnter(SuspendWithObjectMonitorWaitWorker thr);
88
89
public static void main(String[] args) throws Exception {
90
try {
91
System.loadLibrary(AGENT_LIB);
92
log("Loaded library: " + AGENT_LIB);
93
} catch (UnsatisfiedLinkError ule) {
94
log("Failed to load library: " + AGENT_LIB);
95
log("java.library.path: " + System.getProperty("java.library.path"));
96
throw ule;
97
}
98
99
int timeMax = 0;
100
if (args.length == 0) {
101
timeMax = DEF_TIME_MAX;
102
} else {
103
int argIndex = 0;
104
int argsLeft = args.length;
105
if (args[0].equals("-p")) {
106
printDebug = true;
107
argIndex = 1;
108
argsLeft--;
109
}
110
if (argsLeft == 0) {
111
timeMax = DEF_TIME_MAX;
112
} else if (argsLeft == 1) {
113
try {
114
timeMax = Integer.parseUnsignedInt(args[argIndex]);
115
} catch (NumberFormatException nfe) {
116
System.err.println("'" + args[argIndex] +
117
"': invalid timeMax value.");
118
usage();
119
}
120
} else {
121
usage();
122
}
123
}
124
125
System.exit(run(timeMax, System.out) + exit_delta);
126
}
127
128
public static void logDebug(String mesg) {
129
if (printDebug) {
130
System.err.println(Thread.currentThread().getName() + ": " + mesg);
131
}
132
}
133
134
public static void usage() {
135
System.err.println("Usage: " + AGENT_LIB + " [-p][time_max]");
136
System.err.println("where:");
137
System.err.println(" -p ::= print debug info");
138
System.err.println(" time_max ::= max looping time in seconds");
139
System.err.println(" (default is " + DEF_TIME_MAX +
140
" seconds)");
141
System.exit(1);
142
}
143
144
public static int run(int timeMax, PrintStream out) {
145
return (new SuspendWithObjectMonitorWait()).doWork(timeMax, out);
146
}
147
148
public static void checkTestState(int exp) {
149
if (testState != exp) {
150
System.err.println("Failure at " + count + " loops.");
151
throw new InternalError("Unexpected test state value: "
152
+ "expected=" + exp + " actual=" + testState);
153
}
154
}
155
156
public int doWork(int timeMax, PrintStream out) {
157
SuspendWithObjectMonitorWaitWorker waiter; // waiter thread
158
SuspendWithObjectMonitorWaitWorker resumer; // resumer thread
159
160
System.out.println("About to execute for " + timeMax + " seconds.");
161
162
long start_time = System.currentTimeMillis();
163
while (System.currentTimeMillis() < start_time + (timeMax * 1000)) {
164
count++;
165
testState = TS_INIT; // starting the test loop
166
167
// launch the waiter thread
168
synchronized (barrierLaunch) {
169
waiter = new SuspendWithObjectMonitorWaitWorker("waiter");
170
waiter.start();
171
172
while (testState != TS_WAITER_RUNNING) {
173
try {
174
barrierLaunch.wait(0); // wait until it is running
175
} catch (InterruptedException ex) {
176
}
177
}
178
}
179
180
// launch the resumer thread
181
synchronized (barrierLaunch) {
182
resumer = new SuspendWithObjectMonitorWaitWorker("resumer", waiter);
183
resumer.start();
184
185
while (testState != TS_RESUMER_RUNNING) {
186
try {
187
barrierLaunch.wait(0); // wait until it is running
188
} catch (InterruptedException ex) {
189
}
190
}
191
}
192
193
checkTestState(TS_RESUMER_RUNNING);
194
195
// The waiter thread was synchronized on threadLock before it
196
// set TS_WAITER_RUNNING and notified barrierLaunch above so
197
// we cannot enter threadLock until the waiter thread calls
198
// threadLock.wait().
199
synchronized (threadLock) {
200
// notify waiter thread so it can try to reenter threadLock
201
testState = TS_READY_TO_NOTIFY;
202
threadLock.notify();
203
204
// wait for the waiter thread to block
205
logDebug("before contended enter wait");
206
int retCode = wait4ContendedEnter(waiter);
207
if (retCode != 0) {
208
throw new RuntimeException("error in JVMTI GetThreadState: "
209
+ "retCode=" + retCode);
210
}
211
logDebug("done contended enter wait");
212
213
checkTestState(TS_READY_TO_NOTIFY);
214
testState = TS_CALL_SUSPEND;
215
logDebug("before suspend thread");
216
retCode = suspendThread(waiter);
217
if (retCode != 0) {
218
throw new RuntimeException("error in JVMTI SuspendThread: "
219
+ "retCode=" + retCode);
220
}
221
logDebug("suspended thread");
222
}
223
224
//
225
// At this point, all of the child threads are running
226
// and we can get to meat of the test:
227
//
228
// - suspended threadLock waiter (trying to reenter)
229
// - a threadLock enter in the resumer thread
230
// - resumption of the waiter thread
231
// - a threadLock enter in the freshly resumed waiter thread
232
//
233
234
synchronized (barrierResumer) {
235
checkTestState(TS_CALL_SUSPEND);
236
237
// tell resumer thread to resume waiter thread
238
testState = TS_READY_TO_RESUME;
239
barrierResumer.notify();
240
241
// Can't call checkTestState() here because the
242
// resumer thread may have already resumed the
243
// waiter thread.
244
}
245
246
try {
247
resumer.join(JOIN_MAX * 1000);
248
if (resumer.isAlive()) {
249
System.err.println("Failure at " + count + " loops.");
250
throw new InternalError("resumer thread is stuck");
251
}
252
waiter.join(JOIN_MAX * 1000);
253
if (waiter.isAlive()) {
254
System.err.println("Failure at " + count + " loops.");
255
throw new InternalError("waiter thread is stuck");
256
}
257
} catch (InterruptedException ex) {
258
}
259
260
checkTestState(TS_WAITER_DONE);
261
}
262
263
System.out.println("Executed " + count + " loops in " + timeMax +
264
" seconds.");
265
266
return 0;
267
}
268
}
269
270
class SuspendWithObjectMonitorWaitWorker extends Thread {
271
private SuspendWithObjectMonitorWaitWorker target; // target for resume operation
272
273
public SuspendWithObjectMonitorWaitWorker(String name) {
274
super(name);
275
}
276
277
public SuspendWithObjectMonitorWaitWorker(String name, SuspendWithObjectMonitorWaitWorker target) {
278
super(name);
279
this.target = target;
280
}
281
282
native static int resumeThread(SuspendWithObjectMonitorWaitWorker thr);
283
284
public void run() {
285
SuspendWithObjectMonitorWait.logDebug("thread running");
286
287
//
288
// Launch the waiter thread:
289
// - grab the threadLock
290
// - threadLock.wait()
291
// - releases threadLock
292
//
293
if (getName().equals("waiter")) {
294
// grab threadLock before we tell main we are running
295
SuspendWithObjectMonitorWait.logDebug("before enter threadLock");
296
synchronized(SuspendWithObjectMonitorWait.threadLock) {
297
SuspendWithObjectMonitorWait.logDebug("enter threadLock");
298
299
SuspendWithObjectMonitorWait.checkTestState(SuspendWithObjectMonitorWait.TS_INIT);
300
301
synchronized(SuspendWithObjectMonitorWait.barrierLaunch) {
302
// tell main we are running
303
SuspendWithObjectMonitorWait.testState = SuspendWithObjectMonitorWait.TS_WAITER_RUNNING;
304
SuspendWithObjectMonitorWait.barrierLaunch.notify();
305
}
306
307
SuspendWithObjectMonitorWait.logDebug("before wait");
308
309
// TS_READY_TO_NOTIFY is set after the main thread has
310
// entered threadLock so a spurious wakeup can't get the
311
// waiter thread out of this threadLock.wait(0) call:
312
while (SuspendWithObjectMonitorWait.testState <= SuspendWithObjectMonitorWait.TS_READY_TO_NOTIFY) {
313
try {
314
SuspendWithObjectMonitorWait.threadLock.wait(0);
315
} catch (InterruptedException ex) {
316
}
317
}
318
319
SuspendWithObjectMonitorWait.logDebug("after wait");
320
321
SuspendWithObjectMonitorWait.checkTestState(SuspendWithObjectMonitorWait.TS_CALL_RESUME);
322
SuspendWithObjectMonitorWait.testState = SuspendWithObjectMonitorWait.TS_WAITER_DONE;
323
324
SuspendWithObjectMonitorWait.logDebug("exit threadLock");
325
}
326
}
327
//
328
// Launch the resumer thread:
329
// - tries to grab the threadLock (should not block!)
330
// - grabs threadLock
331
// - resumes the waiter thread
332
// - releases threadLock
333
//
334
else if (getName().equals("resumer")) {
335
synchronized(SuspendWithObjectMonitorWait.barrierResumer) {
336
synchronized(SuspendWithObjectMonitorWait.barrierLaunch) {
337
// tell main we are running
338
SuspendWithObjectMonitorWait.testState = SuspendWithObjectMonitorWait.TS_RESUMER_RUNNING;
339
SuspendWithObjectMonitorWait.barrierLaunch.notify();
340
}
341
SuspendWithObjectMonitorWait.logDebug("thread waiting");
342
while (SuspendWithObjectMonitorWait.testState != SuspendWithObjectMonitorWait.TS_READY_TO_RESUME) {
343
try {
344
// wait for main to tell us when to continue
345
SuspendWithObjectMonitorWait.barrierResumer.wait(0);
346
} catch (InterruptedException ex) {
347
}
348
}
349
}
350
351
SuspendWithObjectMonitorWait.logDebug("before enter threadLock");
352
synchronized(SuspendWithObjectMonitorWait.threadLock) {
353
SuspendWithObjectMonitorWait.logDebug("enter threadLock");
354
355
SuspendWithObjectMonitorWait.checkTestState(SuspendWithObjectMonitorWait.TS_READY_TO_RESUME);
356
SuspendWithObjectMonitorWait.testState = SuspendWithObjectMonitorWait.TS_CALL_RESUME;
357
358
// resume the waiter thread so waiter.join() can work
359
SuspendWithObjectMonitorWait.logDebug("before resume thread");
360
int retCode = resumeThread(target);
361
if (retCode != 0) {
362
throw new RuntimeException("error in JVMTI ResumeThread: " +
363
"retCode=" + retCode);
364
}
365
SuspendWithObjectMonitorWait.logDebug("resumed thread");
366
367
SuspendWithObjectMonitorWait.logDebug("exit threadLock");
368
}
369
}
370
}
371
}
372
373