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 id=default
26 * @bug 8312498
27 * @summary Basic test for JVMTI GetThreadState with virtual threads
28 * @library /test/lib
29 * @run junit/othervm/native GetThreadStateTest
30 */
31
32 /*
33 * @test id=no-vmcontinuations
34 * @requires vm.continuations
35 * @library /test/lib
36 * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations GetThreadStateTest
37 */
38
39 import java.util.StringJoiner;
40 import java.util.concurrent.atomic.AtomicBoolean;
41 import java.util.concurrent.locks.LockSupport;
42
43 import jdk.test.lib.thread.VThreadPinner;
44 import org.junit.jupiter.api.BeforeAll;
45 import org.junit.jupiter.api.Test;
46 import static org.junit.jupiter.api.Assertions.*;
47
48 class GetThreadStateTest {
49
50 @BeforeAll
51 static void setup() {
52 System.loadLibrary("GetThreadStateTest");
53 init();
54 }
55
56 /**
57 * Test state of new/unstarted thread.
58 */
59 @Test
60 void testUnstarted() {
61 var thread = Thread.ofVirtual().unstarted(() -> { });
62 check(thread, /*new*/ 0);
63 }
64
65 /**
66 * Test state of terminated thread.
67 */
68 @Test
69 void testTerminated() throws Exception {
70 var thread = Thread.ofVirtual().start(() -> { });
71 thread.join();
72 check(thread, JVMTI_THREAD_STATE_TERMINATED);
73 }
88 }
89 });
90 try {
91 // wait for thread to start execution
92 awaitTrue(started);
93
94 // thread should be runnable
95 int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE;
96 check(thread, expected);
97
98 // re-test with interrupt status set
99 thread.interrupt();
100 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
101 } finally {
102 done.set(true);
103 thread.join();
104 }
105 }
106
107 /**
108 * Test state of thread waiting to enter a monitor.
109 */
110 @Test
111 void testMonitorEnter() throws Exception {
112 var started = new AtomicBoolean();
113 Object lock = new Object();
114 var thread = Thread.ofVirtual().unstarted(() -> {
115 started.set(true);
116 synchronized (lock) { }
117 });
118 try {
119 synchronized (lock) {
120 // start thread and wait for it to start execution
121 thread.start();
122 awaitTrue(started);
123
124 // thread should block on monitor enter
125 int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
126 await(thread, expected);
127
128 // re-test with interrupt status set
129 thread.interrupt();
130 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
131 }
132 } finally {
133 thread.join();
134 }
135 }
136
202 JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
203 await(thread, expected);
204
205 // notify so thread waits to re-enter monitor
206 synchronized (lock) {
207 lock.notifyAll();
208 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
209 check(thread, expected);
210
211 // re-test with interrupt status set
212 thread.interrupt();
213 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
214 }
215 } finally {
216 thread.interrupt();
217 thread.join();
218 }
219 }
220
221 /**
222 * Test state of thread parked with LockSupport.park.
223 */
224 @Test
225 void testPark() throws Exception {
226 var started = new AtomicBoolean();
227 var done = new AtomicBoolean();
228 var thread = Thread.ofVirtual().start(() -> {
229 started.set(true);
230 while (!done.get()) {
231 LockSupport.park();
232 }
233 });
234 try {
235 // wait for thread to start execution
236 awaitTrue(started);
237
238 // thread should park
239 int expected = JVMTI_THREAD_STATE_ALIVE |
240 JVMTI_THREAD_STATE_WAITING |
241 JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
242 JVMTI_THREAD_STATE_PARKED;
243 await(thread, expected);
244 } finally {
245 done.set(true);
246 LockSupport.unpark(thread);
247 thread.join();
248 }
249 }
250
251 /**
252 * Test state of thread parked with LockSupport.parkNanos.
253 */
254 @Test
255 void testParkNanos() throws Exception {
256 var started = new AtomicBoolean();
257 var done = new AtomicBoolean();
258 var thread = Thread.ofVirtual().start(() -> {
259 started.set(true);
260 while (!done.get()) {
261 LockSupport.parkNanos(Long.MAX_VALUE);
262 }
263 });
264 try {
265 // wait for thread to start execution
266 awaitTrue(started);
267
268 // thread should park
269 int expected = JVMTI_THREAD_STATE_ALIVE |
270 JVMTI_THREAD_STATE_WAITING |
271 JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
272 JVMTI_THREAD_STATE_PARKED;
273 await(thread, expected);
274 } finally {
275 done.set(true);
276 LockSupport.unpark(thread);
277 thread.join();
278 }
279 }
280
281 /**
282 * Test state of thread parked with LockSupport.park while holding a monitor.
283 */
284 @Test
285 void testParkWhenPinned() throws Exception {
286 var started = new AtomicBoolean();
287 var done = new AtomicBoolean();
288 var thread = Thread.ofVirtual().start(() -> {
289 VThreadPinner.runPinned(() -> {
290 started.set(true);
291 while (!done.get()) {
292 LockSupport.park();
293 }
294 });
295 });
296 try {
297 // wait for thread to start execution
298 awaitTrue(started);
299
300 // thread should park
301 int expected = JVMTI_THREAD_STATE_ALIVE |
302 JVMTI_THREAD_STATE_WAITING |
303 JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
304 JVMTI_THREAD_STATE_PARKED;
305 await(thread, expected);
306 } finally {
307 done.set(true);
308 LockSupport.unpark(thread);
309 thread.join();
310 }
311 }
312
313 /**
314 * Test state of thread parked with LockSupport.parkNanos while holding a monitor.
315 */
316 @Test
317 void testParkNanosWhenPinned() throws Exception {
318 var started = new AtomicBoolean();
319 var done = new AtomicBoolean();
320 var thread = Thread.ofVirtual().start(() -> {
321 VThreadPinner.runPinned(() -> {
322 started.set(true);
323 while (!done.get()) {
324 LockSupport.parkNanos(Long.MAX_VALUE);
325 }
326 });
327 });
328 try {
329 // wait for thread to start execution
330 awaitTrue(started);
331
332 // thread should park
333 int expected = JVMTI_THREAD_STATE_ALIVE |
334 JVMTI_THREAD_STATE_WAITING |
335 JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
336 JVMTI_THREAD_STATE_PARKED;
337 await(thread, expected);
338 } finally {
339 done.set(true);
340 LockSupport.unpark(thread);
341 thread.join();
342 }
343 }
344
345 /**
346 * Waits for the boolean value to become true.
|
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 id=default
26 * @bug 8312498
27 * @summary Basic test for JVMTI GetThreadState with virtual threads
28 * @modules java.base/java.lang:+open
29 * @library /test/lib
30 * @run junit/othervm/native --enable-native-access=ALL-UNNAMED GetThreadStateTest
31 */
32
33 /*
34 * @test id=no-vmcontinuations
35 * @requires vm.continuations
36 * @modules java.base/java.lang:+open
37 * @library /test/lib
38 * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations --enable-native-access=ALL-UNNAMED GetThreadStateTest
39 */
40
41 import java.util.StringJoiner;
42 import java.util.concurrent.atomic.AtomicBoolean;
43 import java.util.concurrent.locks.LockSupport;
44
45 import jdk.test.lib.thread.VThreadRunner;
46 import jdk.test.lib.thread.VThreadPinner;
47 import org.junit.jupiter.api.BeforeAll;
48 import org.junit.jupiter.api.Test;
49 import org.junit.jupiter.params.ParameterizedTest;
50 import org.junit.jupiter.params.provider.ValueSource;
51 import static org.junit.jupiter.api.Assertions.*;
52
53 class GetThreadStateTest {
54
55 @BeforeAll
56 static void setup() {
57 System.loadLibrary("GetThreadStateTest");
58 init();
59
60 // need >=2 carriers for testing pinning when main thread is a virtual thread
61 if (Thread.currentThread().isVirtual()) {
62 VThreadRunner.ensureParallelism(2);
63 }
64 }
65
66 /**
67 * Test state of new/unstarted thread.
68 */
69 @Test
70 void testUnstarted() {
71 var thread = Thread.ofVirtual().unstarted(() -> { });
72 check(thread, /*new*/ 0);
73 }
74
75 /**
76 * Test state of terminated thread.
77 */
78 @Test
79 void testTerminated() throws Exception {
80 var thread = Thread.ofVirtual().start(() -> { });
81 thread.join();
82 check(thread, JVMTI_THREAD_STATE_TERMINATED);
83 }
98 }
99 });
100 try {
101 // wait for thread to start execution
102 awaitTrue(started);
103
104 // thread should be runnable
105 int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE;
106 check(thread, expected);
107
108 // re-test with interrupt status set
109 thread.interrupt();
110 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
111 } finally {
112 done.set(true);
113 thread.join();
114 }
115 }
116
117 /**
118 * Test state of thread waiting to enter a monitor when pinned and not pinned.
119 */
120 @ParameterizedTest
121 @ValueSource(booleans = { true, false })
122 void testMonitorEnter(boolean pinned) throws Exception {
123 var started = new AtomicBoolean();
124 Object lock = new Object();
125 var thread = Thread.ofVirtual().unstarted(() -> {
126 started.set(true);
127 if (pinned) {
128 VThreadPinner.runPinned(() -> {
129 synchronized (lock) { }
130 });
131 } else {
132 synchronized (lock) { }
133 }
134 });
135 try {
136 synchronized (lock) {
137 // start thread and wait for it to start execution
138 thread.start();
139 awaitTrue(started);
140
141 // thread should block on monitor enter
142 int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
143 await(thread, expected);
144
145 // re-test with interrupt status set
146 thread.interrupt();
147 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
148 }
149 } finally {
150 thread.join();
151 }
152 }
153
219 JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
220 await(thread, expected);
221
222 // notify so thread waits to re-enter monitor
223 synchronized (lock) {
224 lock.notifyAll();
225 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
226 check(thread, expected);
227
228 // re-test with interrupt status set
229 thread.interrupt();
230 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
231 }
232 } finally {
233 thread.interrupt();
234 thread.join();
235 }
236 }
237
238 /**
239 * Test state of thread parked with LockSupport.park when pinned and not pinned.
240 */
241 @ParameterizedTest
242 @ValueSource(booleans = { true, false })
243 void testPark(boolean pinned) throws Exception {
244 var started = new AtomicBoolean();
245 var done = new AtomicBoolean();
246 var thread = Thread.ofVirtual().start(() -> {
247 started.set(true);
248 if (pinned) {
249 VThreadPinner.runPinned(() -> {
250 while (!done.get()) {
251 LockSupport.park();
252 }
253 });
254 } else {
255 while (!done.get()) {
256 LockSupport.park();
257 }
258 }
259 });
260 try {
261 // wait for thread to start execution
262 awaitTrue(started);
263
264 // thread should park
265 int expected = JVMTI_THREAD_STATE_ALIVE |
266 JVMTI_THREAD_STATE_WAITING |
267 JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
268 JVMTI_THREAD_STATE_PARKED;
269 await(thread, expected);
270 } finally {
271 done.set(true);
272 LockSupport.unpark(thread);
273 thread.join();
274 }
275 }
276
277 /**
278 * Test state of thread parked with LockSupport.parkNanos when pinned and not pinned.
279 */
280 @ParameterizedTest
281 @ValueSource(booleans = { true, false })
282 void testParkNanos(boolean pinned) throws Exception {
283 var started = new AtomicBoolean();
284 var done = new AtomicBoolean();
285 var thread = Thread.ofVirtual().start(() -> {
286 started.set(true);
287 if (pinned) {
288 VThreadPinner.runPinned(() -> {
289 while (!done.get()) {
290 LockSupport.parkNanos(Long.MAX_VALUE);
291 }
292 });
293 } else {
294 while (!done.get()) {
295 LockSupport.parkNanos(Long.MAX_VALUE);
296 }
297 }
298 });
299 try {
300 // wait for thread to start execution
301 awaitTrue(started);
302
303 // thread should park
304 int expected = JVMTI_THREAD_STATE_ALIVE |
305 JVMTI_THREAD_STATE_WAITING |
306 JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
307 JVMTI_THREAD_STATE_PARKED;
308 await(thread, expected);
309 } finally {
310 done.set(true);
311 LockSupport.unpark(thread);
312 thread.join();
313 }
314 }
315
316 /**
317 * Waits for the boolean value to become true.
|