Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/monitoring/ThreadInfo/GetLockOwnerName/GetLockOwnerName.java
41161 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 8167108 8265153
27
* @summary The test checks that ThreadInfo.getLockOwnerName() returns a
28
* non-null string for a blocked thread and then makes repeated calls
29
* to getThreadInfo() and ThreadInfo.getLockOwnerName() until the thread
30
* has exited.
31
* @requires vm.jvmti
32
* @run main/othervm/native -agentlib:GetLockOwnerName GetLockOwnerName
33
*/
34
35
import java.io.PrintStream;
36
import java.lang.management.ManagementFactory;
37
import java.lang.management.ThreadInfo;
38
import java.lang.management.ThreadMXBean;
39
40
//
41
// main blocker contender releaser
42
// ================= ================ =================== ================
43
// launch blocker
44
// <launch returns> blocker running
45
// launch contender enter threadLock
46
// <launch returns> wait for notify contender running
47
// launch releaser : block on threadLock
48
// <launch returns> : : releaser running
49
// wait for : : wait for notify
50
// contended enter : : :
51
// <ready to test> : : :
52
// getThreadInfo : : :
53
// verify contender : : :
54
// lock owner name : : :
55
// is "blocker" : : :
56
// notify releaser : : :
57
// loop until thread : : wait finishes
58
// is NULL : : notify blocker
59
// get thread info wait finishes : releaser exits
60
// get lock owner exit threadLock : :
61
// name blocker exits enter threadLock :
62
// join releaser : exit threadLock <exit finishes>
63
// <join returns> : contender exits
64
// join blocker <exit finishes> :
65
// <join returns> :
66
// join contender <exit finishes>
67
// <join returns>
68
//
69
70
public class GetLockOwnerName {
71
private static final String AGENT_LIB = "GetLockOwnerName";
72
73
private static final int DEF_TIME_MAX = 60; // default max # secs to test
74
private static final int JOIN_MAX = 30; // max # secs to wait for join
75
76
public static final int TS_INIT = 1; // initial testState
77
public static final int TS_BLOCKER_RUNNING = 2; // blocker is running
78
public static final int TS_CONTENDER_RUNNING = 3; // contender is running
79
public static final int TS_RELEASER_RUNNING = 4; // releaser is running
80
public static final int TS_CONTENDER_BLOCKED = 5; // contender is blocked
81
public static final int TS_READY_TO_RELEASE = 6; // ready to release the blocker
82
public static final int TS_DONE_BLOCKING = 7; // done blocking threadLock
83
public static final int TS_CONTENDER_DONE = 8; // contender has run; done
84
85
public static Object barrierLaunch = new Object(); // controls thread launch
86
public static Object barrierBlocker = new Object(); // controls blocker
87
public static Object barrierReleaser = new Object(); // controls releaser
88
public static Object threadLock = new Object(); // testing object
89
90
public static long count = 0;
91
public static boolean printDebug = false;
92
public volatile static int testState;
93
94
private static void log(String msg) { System.out.println(msg); }
95
96
native static int wait4ContendedEnter(GetLockOwnerNameWorker thr);
97
98
public static void main(String[] args) throws Exception {
99
try {
100
System.loadLibrary(AGENT_LIB);
101
log("Loaded library: " + AGENT_LIB);
102
} catch (UnsatisfiedLinkError ule) {
103
log("Failed to load library: " + AGENT_LIB);
104
log("java.library.path: " + System.getProperty("java.library.path"));
105
throw ule;
106
}
107
108
int timeMax = 0;
109
if (args.length == 0) {
110
timeMax = DEF_TIME_MAX;
111
} else {
112
int argIndex = 0;
113
int argsLeft = args.length;
114
if (args[0].equals("-p")) {
115
printDebug = true;
116
argIndex = 1;
117
argsLeft--;
118
}
119
if (argsLeft == 0) {
120
timeMax = DEF_TIME_MAX;
121
} else if (argsLeft == 1) {
122
try {
123
timeMax = Integer.parseUnsignedInt(args[argIndex]);
124
} catch (NumberFormatException nfe) {
125
System.err.println("'" + args[argIndex] +
126
"': invalid timeMax value.");
127
usage();
128
}
129
} else {
130
usage();
131
}
132
}
133
134
int retCode = run(timeMax, System.out);
135
if (retCode != 0) {
136
throw new RuntimeException("Test failed with retCode=" + retCode);
137
}
138
}
139
140
public static void logDebug(String mesg) {
141
if (printDebug) {
142
System.err.println(Thread.currentThread().getName() + ": " + mesg);
143
}
144
}
145
146
public static void usage() {
147
System.err.println("Usage: " + AGENT_LIB + " [-p][time_max]");
148
System.err.println("where:");
149
System.err.println(" -p print debug info");
150
System.err.println(" time_max max looping time in seconds");
151
System.err.println(" (default is " + DEF_TIME_MAX +
152
" seconds)");
153
System.exit(1);
154
}
155
156
public static int run(int timeMax, PrintStream out) {
157
return (new GetLockOwnerName()).doWork(timeMax, out);
158
}
159
160
public static void checkTestState(int exp) {
161
if (testState != exp) {
162
System.err.println("Failure at " + count + " loops.");
163
throw new InternalError("Unexpected test state value: "
164
+ "expected=" + exp + " actual=" + testState);
165
}
166
}
167
168
public int doWork(int timeMax, PrintStream out) {
169
ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
170
171
GetLockOwnerNameWorker blocker; // blocker thread
172
GetLockOwnerNameWorker contender; // contender thread
173
GetLockOwnerNameWorker releaser; // releaser thread
174
175
System.out.println("About to execute for " + timeMax + " seconds.");
176
177
long start_time = System.currentTimeMillis();
178
while (System.currentTimeMillis() < start_time + (timeMax * 1000)) {
179
count++;
180
testState = TS_INIT; // starting the test loop
181
182
// launch the blocker thread
183
synchronized (barrierLaunch) {
184
blocker = new GetLockOwnerNameWorker("blocker");
185
blocker.start();
186
187
while (testState != TS_BLOCKER_RUNNING) {
188
try {
189
barrierLaunch.wait(); // wait until it is running
190
} catch (InterruptedException ex) {
191
}
192
}
193
}
194
195
// launch the contender thread
196
synchronized (barrierLaunch) {
197
contender = new GetLockOwnerNameWorker("contender");
198
contender.start();
199
200
while (testState != TS_CONTENDER_RUNNING) {
201
try {
202
barrierLaunch.wait(); // wait until it is running
203
} catch (InterruptedException ex) {
204
}
205
}
206
}
207
208
// launch the releaser thread
209
synchronized (barrierLaunch) {
210
releaser = new GetLockOwnerNameWorker("releaser");
211
releaser.start();
212
213
while (testState != TS_RELEASER_RUNNING) {
214
try {
215
barrierLaunch.wait(); // wait until it is running
216
} catch (InterruptedException ex) {
217
}
218
}
219
}
220
221
// wait for the contender thread to block
222
logDebug("before contended enter wait");
223
int retCode = wait4ContendedEnter(contender);
224
if (retCode != 0) {
225
throw new RuntimeException("error in JVMTI GetThreadState " +
226
"or GetCurrentContendedMonitor " +
227
"retCode=" + retCode);
228
}
229
testState = TS_CONTENDER_BLOCKED;
230
logDebug("done contended enter wait");
231
232
//
233
// At this point, all of the child threads are running
234
// and we can get to meat of the test:
235
//
236
// - query the contender thread and verify that it is blocked
237
// by the blocker thread
238
// - tell the releaser thread to release the blocker thread
239
// - continue to query the contender thread until it exits
240
//
241
long id = 0;
242
ThreadInfo info = null;
243
int lateCount = 0;
244
245
checkTestState(TS_CONTENDER_BLOCKED);
246
247
id = contender.getId();
248
info = mbean.getThreadInfo(id, 0);
249
String name = info.getLockOwnerName();
250
251
if (name == null) {
252
out.println("Failure at " + count + " loops.");
253
throw new RuntimeException("ThreadInfo.GetLockOwnerName() "
254
+ "returned null name for "
255
+ "contender.");
256
} else if (!name.equals("blocker")) {
257
out.println("Failure at " + count + " loops.");
258
throw new RuntimeException("name='" + name + "': name "
259
+ "should be blocker.");
260
} else {
261
logDebug("ThreadInfo.GetLockOwnerName() returned blocker.");
262
}
263
264
synchronized (barrierReleaser) {
265
// tell releaser thread to release the blocker thread
266
testState = TS_READY_TO_RELEASE;
267
barrierReleaser.notify();
268
}
269
270
while (true) {
271
// maxDepth == 0 requires no safepoint so alternate.
272
int maxDepth = ((count % 1) == 1) ? Integer.MAX_VALUE : 0;
273
info = mbean.getThreadInfo(id, maxDepth);
274
if (info == null) {
275
// the contender has exited
276
break;
277
}
278
name = info.getLockOwnerName();
279
// We can't verify that name == null here because contender
280
// might be slow leaving the threadLock monitor.
281
lateCount++;
282
}
283
logDebug("made " + lateCount + " late calls to getThreadInfo() " +
284
"and info.getLockOwnerName().");
285
286
try {
287
releaser.join(JOIN_MAX * 1000);
288
if (releaser.isAlive()) {
289
System.err.println("Failure at " + count + " loops.");
290
throw new InternalError("releaser thread is stuck");
291
}
292
blocker.join(JOIN_MAX * 1000);
293
if (blocker.isAlive()) {
294
System.err.println("Failure at " + count + " loops.");
295
throw new InternalError("blocker thread is stuck");
296
}
297
contender.join(JOIN_MAX * 1000);
298
if (contender.isAlive()) {
299
System.err.println("Failure at " + count + " loops.");
300
throw new InternalError("contender thread is stuck");
301
}
302
} catch (InterruptedException ex) {
303
}
304
305
checkTestState(TS_CONTENDER_DONE);
306
}
307
308
System.out.println("Executed " + count + " loops in " + timeMax +
309
" seconds.");
310
311
return 0;
312
}
313
}
314
315
class GetLockOwnerNameWorker extends Thread {
316
public GetLockOwnerNameWorker(String name) {
317
super(name);
318
}
319
320
public void run() {
321
GetLockOwnerName.logDebug("thread running");
322
323
//
324
// The blocker thread:
325
// - grabs threadLock
326
// - holds threadLock until we tell it let go
327
// - releases threadLock
328
//
329
if (getName().equals("blocker")) {
330
// grab threadLock before we tell main we are running
331
GetLockOwnerName.logDebug("before enter threadLock");
332
synchronized(GetLockOwnerName.threadLock) {
333
GetLockOwnerName.logDebug("enter threadLock");
334
335
GetLockOwnerName.checkTestState(GetLockOwnerName.TS_INIT);
336
337
synchronized(GetLockOwnerName.barrierBlocker) {
338
synchronized(GetLockOwnerName.barrierLaunch) {
339
// tell main we are running
340
GetLockOwnerName.testState = GetLockOwnerName.TS_BLOCKER_RUNNING;
341
GetLockOwnerName.barrierLaunch.notify();
342
}
343
GetLockOwnerName.logDebug("thread waiting");
344
while (GetLockOwnerName.testState != GetLockOwnerName.TS_DONE_BLOCKING) {
345
try {
346
// wait for main to tell us when to exit threadLock
347
GetLockOwnerName.barrierBlocker.wait();
348
} catch (InterruptedException ex) {
349
}
350
}
351
}
352
GetLockOwnerName.logDebug("exit threadLock");
353
}
354
}
355
//
356
// The contender thread:
357
// - tries to grab the threadLock
358
// - grabs threadLock
359
// - releases threadLock
360
//
361
else if (getName().equals("contender")) {
362
synchronized(GetLockOwnerName.barrierLaunch) {
363
// tell main we are running
364
GetLockOwnerName.testState = GetLockOwnerName.TS_CONTENDER_RUNNING;
365
GetLockOwnerName.barrierLaunch.notify();
366
}
367
368
GetLockOwnerName.logDebug("before enter threadLock");
369
synchronized(GetLockOwnerName.threadLock) {
370
GetLockOwnerName.logDebug("enter threadLock");
371
372
GetLockOwnerName.checkTestState(GetLockOwnerName.TS_DONE_BLOCKING);
373
GetLockOwnerName.testState = GetLockOwnerName.TS_CONTENDER_DONE;
374
375
GetLockOwnerName.logDebug("exit threadLock");
376
}
377
}
378
//
379
// The releaser thread:
380
// - tries to grab the barrierBlocker (should not block!)
381
// - grabs barrierBlocker
382
// - releases the blocker thread
383
// - releases barrierBlocker
384
//
385
else if (getName().equals("releaser")) {
386
synchronized(GetLockOwnerName.barrierReleaser) {
387
synchronized(GetLockOwnerName.barrierLaunch) {
388
// tell main we are running
389
GetLockOwnerName.testState = GetLockOwnerName.TS_RELEASER_RUNNING;
390
GetLockOwnerName.barrierLaunch.notify();
391
}
392
GetLockOwnerName.logDebug("thread waiting");
393
while (GetLockOwnerName.testState != GetLockOwnerName.TS_READY_TO_RELEASE) {
394
try {
395
// wait for main to tell us when to continue
396
GetLockOwnerName.barrierReleaser.wait();
397
} catch (InterruptedException ex) {
398
}
399
}
400
}
401
402
GetLockOwnerName.logDebug("before enter barrierBlocker");
403
synchronized (GetLockOwnerName.barrierBlocker) {
404
GetLockOwnerName.logDebug("enter barrierBlocker");
405
406
// tell blocker thread to exit threadLock
407
GetLockOwnerName.testState = GetLockOwnerName.TS_DONE_BLOCKING;
408
GetLockOwnerName.barrierBlocker.notify();
409
410
GetLockOwnerName.logDebug("released blocker thread");
411
GetLockOwnerName.logDebug("exit barrierBlocker");
412
}
413
}
414
}
415
}
416
417