RFR: Update running count of ForkJoinPool when thread pinned

Miao Zheng duke at openjdk.java.net
Mon Dec 20 07:14:11 UTC 2021


In the test case of this PR, when vt0 invoke System.out.println(), it will invoke managedBlock eventually, and create a new ForkJoinWorkerThread. The call stack is :

Thread[#17,ForkJoinPool-1-worker-1,5,CarrierThreads]
    java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:161)
    java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:462)
    java.base/jdk.internal.vm.Continuation.yield0(Continuation.java:447)
    java.base/jdk.internal.vm.Continuation.yield(Continuation.java:407)
    java.base/java.lang.VirtualThread.yieldContinuation(VirtualThread.java:351)
    java.base/java.lang.VirtualThread.park(VirtualThread.java:509)
    java.base/java.lang.System$2.parkVirtualThread(System.java:2570)
    java.base/jdk.internal.misc.VirtualThreads.park(VirtualThreads.java:60)
    java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:219)
    java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
    java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:938)
    java.base/java.util.concurrent.locks.ReentrantLock$Sync.lock(ReentrantLock.java:153)
    java.base/java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:322)
    VTCompensate$2.run(VTCompensate.java:55) <== monitors:1
    java.base/java.lang.VirtualThread.run(VirtualThread.java:270)
    java.base/java.lang.VirtualThread$VThreadContinuation.lambda$new$0(VirtualThread.java:155)
    java.base/jdk.internal.vm.Continuation.enter0(Continuation.java:377)
    java.base/jdk.internal.vm.Continuation.enter(Continuation.java:370)


After create a new ForkJoinWorkerThread, we have two ForkJoinWorkerThread(use -Djdk.defaultScheduler.parallelism=1 for initialization), and vt1 pinned a ForkJoinWorkerThread.

When main thread unlock Reentrantlock, vt0 will re-submit to ForkJoinPool and we have an extra working thread to run vt0. 

But we find the extra compensate working thread not work, it is parked. The call stack is :

"ForkJoinPool-1-worker-2" #18 [31814] daemon prio=5 os_prio=0 cpu=0.42ms elapsed=119.94s tid=0x00007f8cf8005050 nid=31814 waiting on condition  [0x00007f8d4012c000]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base at 19-internal/Native Method)
        at java.util.concurrent.locks.LockSupport.park(java.base at 19-internal/LockSupport.java:371)
        at java.util.concurrent.ForkJoinPool.awaitWork(java.base at 19-internal/ForkJoinPool.java:1706)
        at java.util.concurrent.ForkJoinPool.runWorker(java.base at 19-internal/ForkJoinPool.java:1603)
        at java.util.concurrent.ForkJoinWorkerThread.run(java.base at 19-internal/ForkJoinWorkerThread.java:165)


The problem is when submit vt-0 to ForkJoinPool, it will called signalWork() of ForkJoinPool and signalWork() do nothing because c < 0L(c < 0L means RC < parallelism, in our test case, parallelism is 1 and current running count is 1)

Actually, current running count should be 0 now because pinned thread can not running other task, so we think should update running count of ForkJoinPool before and after pin.

-------------

Commit messages:
 - Update running count of ForkJoinPool when thread pinned

Changes: https://git.openjdk.java.net/loom/pull/83/files
 Webrev: https://webrevs.openjdk.java.net/?repo=loom&pr=83&range=00
  Stats: 90 lines in 3 files changed: 90 ins; 0 del; 0 mod
  Patch: https://git.openjdk.java.net/loom/pull/83.diff
  Fetch: git fetch https://git.openjdk.java.net/loom pull/83/head:pull/83

PR: https://git.openjdk.java.net/loom/pull/83


More information about the loom-dev mailing list