23
24 /**
25 * @test
26 * @bug 8284161 8286788
27 * @summary Test that a carrier thread waits on a virtual thread
28 * @requires vm.continuations
29 * @modules java.base/java.lang:+open
30 * @run junit CarrierThreadWaits
31 */
32
33 /**
34 * @test
35 * @requires vm.continuations & vm.debug
36 * @modules java.base/java.lang:+open
37 * @run junit/othervm -XX:LockingMode=0 CarrierThreadWaits
38 */
39
40 import java.lang.management.LockInfo;
41 import java.lang.management.ManagementFactory;
42 import java.lang.management.ThreadInfo;
43 import java.util.concurrent.CountDownLatch;
44 import java.util.concurrent.Executor;
45 import java.util.concurrent.ForkJoinPool;
46 import java.util.concurrent.atomic.AtomicBoolean;
47 import java.util.concurrent.atomic.AtomicReference;
48
49 import org.junit.jupiter.api.Test;
50 import static org.junit.jupiter.api.Assertions.*;
51
52 class CarrierThreadWaits {
53
54 @Test
55 void testCarrierThreadWaiting() throws Exception {
56 try (ForkJoinPool pool = new ForkJoinPool(1)) {
57 var carrierRef = new AtomicReference<Thread>();
58 Executor scheduler = task -> {
59 pool.submit(() -> {
60 carrierRef.set(Thread.currentThread());
61 task.run();
62 });
63 };
64
65 // start a virtual thread that spins and remains mounted until "done"
66 var latch = new CountDownLatch(1);
67 var done = new AtomicBoolean();
68 Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
69 Thread vthread = builder.start(() -> {
70 latch.countDown();
71 while (!done.get()) {
72 Thread.onSpinWait();
73 }
74 });
75
76 // wait for virtual thread to execute
77 latch.await();
78
79 try {
80 long carrierId = carrierRef.get().threadId();
81 long vthreadId = vthread.threadId();
82
83 // carrier thread should be on WAITING on virtual thread
84 ThreadInfo ti = ManagementFactory.getThreadMXBean().getThreadInfo(carrierId);
85 assertTrue(ti.getThreadState() == Thread.State.WAITING);
86 assertEquals(vthread.getClass().getName(), ti.getLockInfo().getClassName());
87 assertTrue(ti.getLockInfo().getIdentityHashCode() == System.identityHashCode(vthread));
88 assertTrue(ti.getLockOwnerId() == vthreadId);
89
90 } finally {
91 done.set(true);
92 }
93 }
94 }
95
96 }
|
23
24 /**
25 * @test
26 * @bug 8284161 8286788
27 * @summary Test that a carrier thread waits on a virtual thread
28 * @requires vm.continuations
29 * @modules java.base/java.lang:+open
30 * @run junit CarrierThreadWaits
31 */
32
33 /**
34 * @test
35 * @requires vm.continuations & vm.debug
36 * @modules java.base/java.lang:+open
37 * @run junit/othervm -XX:LockingMode=0 CarrierThreadWaits
38 */
39
40 import java.lang.management.LockInfo;
41 import java.lang.management.ManagementFactory;
42 import java.lang.management.ThreadInfo;
43 import java.util.concurrent.Executor;
44 import java.util.concurrent.ForkJoinPool;
45 import java.util.concurrent.atomic.AtomicBoolean;
46 import java.util.concurrent.atomic.AtomicReference;
47
48 import org.junit.jupiter.api.Test;
49 import static org.junit.jupiter.api.Assertions.*;
50
51 class CarrierThreadWaits {
52
53 @Test
54 void testCarrierThreadWaiting() throws Exception {
55 try (ForkJoinPool pool = new ForkJoinPool(1)) {
56 var carrierRef = new AtomicReference<Thread>();
57 var vthreadRef = new AtomicReference<Thread>();
58
59 Executor scheduler = task -> {
60 pool.submit(() -> {
61 Thread carrier = Thread.currentThread();
62 carrierRef.set(carrier);
63 Thread vthread = vthreadRef.get();
64
65 System.err.format("%s run task (%s) ...%n", carrier, vthread);
66 task.run();
67 System.err.format("%s task done (%s)%n", carrier, vthread);
68 });
69 };
70
71 // start a virtual thread that spins and remains mounted until "done"
72 var started = new AtomicBoolean();
73 var done = new AtomicBoolean();
74 Thread.Builder builder = ThreadBuilders.virtualThreadBuilder(scheduler);
75 Thread vthread = builder.unstarted(() -> {
76 started.set(true);
77 while (!done.get()) {
78 Thread.onSpinWait();
79 }
80 });
81 vthreadRef.set(vthread);
82 vthread.start();
83
84 try {
85 // wait for virtual thread to start
86 while (!started.get()) {
87 Thread.sleep(10);
88 }
89
90 Thread carrier = carrierRef.get();
91
92 long carrierId = carrier.threadId();
93 long vthreadId = vthread.threadId();
94
95 // carrier thread should be on WAITING on virtual thread
96 ThreadInfo ti = ManagementFactory.getThreadMXBean().getThreadInfo(carrierId);
97 Thread.State state = ti.getThreadState();
98 LockInfo lockInfo = ti.getLockInfo();
99 assertEquals(Thread.State.WAITING, state);
100 assertNotNull(lockInfo);
101 assertEquals(vthread.getClass().getName(), lockInfo.getClassName());
102 assertEquals(System.identityHashCode(vthread), lockInfo.getIdentityHashCode());
103 assertEquals(vthreadId, ti.getLockOwnerId());
104 } finally {
105 done.set(true);
106 }
107 }
108 }
109
110 }
|