285 TestClass.m();
286 });
287
288 try {
289 synchronized (LockHolder.lock) {
290 vthread.start();
291 // wait for thread to start and block
292 awaitTrue(started);
293 await(vthread, Thread.State.BLOCKED);
294 }
295 } finally {
296 vthread.join();
297 recording.stop();
298 }
299
300 assertContainsPinnedEvent(recording, vthread);
301 }
302 }
303
304 /**
305 * Test jdk.VirtualThreadPinned event when waiting for a class initializer.
306 */
307 @Test
308 void testWaitingForClassInitializer() throws Exception {
309 class TestClass {
310 static {
311 LockSupport.park();
312 }
313 static void m() {
314 // do nothing
315 }
316 }
317
318 try (Recording recording = new Recording()) {
319 recording.enable("jdk.VirtualThreadPinned");
320 recording.start();
321
322 var started1 = new AtomicBoolean();
323 var started2 = new AtomicBoolean();
324
325 Thread vthread1 = Thread.ofVirtual().unstarted(() -> {
326 started1.set(true);
327 TestClass.m();
328 });
329 Thread vthread2 = Thread.ofVirtual().unstarted(() -> {
330 started2.set(true);
331 TestClass.m();
332 });
333
334 try {
335 // start first virtual thread and wait for it to start + park
336 vthread1.start();
337 awaitTrue(started1);
338 await(vthread1, Thread.State.WAITING);
339
340 // start second virtual thread and wait for it to start
341 vthread2.start();
342 awaitTrue(started2);
343
344 // give time for second virtual thread to wait on the MutexLocker
345 Thread.sleep(3000);
346
347 } finally {
348 LockSupport.unpark(vthread1);
349 vthread1.join();
350 vthread2.join();
351 recording.stop();
352 }
353
354 // the recording should have a pinned event for vthread2
355 assertContainsPinnedEvent(recording, vthread2);
356 }
357 }
358
359 /**
360 * Test jdk.VirtualThreadSubmitFailed event.
361 */
362 @Test
363 void testVirtualThreadSubmitFailed() throws Exception {
364 try (Recording recording = new Recording()) {
|
285 TestClass.m();
286 });
287
288 try {
289 synchronized (LockHolder.lock) {
290 vthread.start();
291 // wait for thread to start and block
292 awaitTrue(started);
293 await(vthread, Thread.State.BLOCKED);
294 }
295 } finally {
296 vthread.join();
297 recording.stop();
298 }
299
300 assertContainsPinnedEvent(recording, vthread);
301 }
302 }
303
304 /**
305 * Test jdk.VirtualThreadPinned event when waiting for a class initializer while pinned.
306 */
307 @Test
308 void testWaitingForClassInitializerWhenPinned() throws Exception {
309 class TestClass {
310 static {
311 LockSupport.park();
312 }
313 static void m() {
314 // do nothing
315 }
316 }
317
318 try (Recording recording = new Recording()) {
319 recording.enable("jdk.VirtualThreadPinned");
320 recording.start();
321
322 var started1 = new AtomicBoolean();
323 var started2 = new AtomicBoolean();
324
325 Thread vthread1 = Thread.ofVirtual().unstarted(() -> {
326 started1.set(true);
327 TestClass.m();
328 });
329 Thread vthread2 = Thread.ofVirtual().unstarted(() -> {
330 started2.set(true);
331 VThreadPinner.runPinned(() -> {
332 TestClass.m();
333 });
334 });
335
336 try {
337 // start first virtual thread and wait for it to start + park
338 vthread1.start();
339 awaitTrue(started1);
340 await(vthread1, Thread.State.WAITING);
341
342 // start second virtual thread and wait for it to start
343 vthread2.start();
344 awaitTrue(started2);
345
346 // give time for second virtual thread to wait in VM
347 Thread.sleep(3000);
348
349 } finally {
350 LockSupport.unpark(vthread1);
351 vthread1.join();
352 vthread2.join();
353 recording.stop();
354 }
355
356 // the recording should have a pinned event for vthread2
357 assertContainsPinnedEvent(recording, vthread2);
358 }
359 }
360
361 /**
362 * Test jdk.VirtualThreadSubmitFailed event.
363 */
364 @Test
365 void testVirtualThreadSubmitFailed() throws Exception {
366 try (Recording recording = new Recording()) {
|