RFR: Update running count of ForkJoinPool when thread pinned [v3]

Miao Zheng duke at openjdk.java.net
Wed Dec 22 02:05:39 UTC 2021


On Wed, 22 Dec 2021 02:01:43 GMT, Miao Zheng <duke at openjdk.java.net> wrote:

>> 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 :
>> 
>> at java.base/java.util.concurrent.ForkJoinPool.tryCompensate(ForkJoinPool.java:1789)
>>         at java.base/java.util.concurrent.ForkJoinPool.compensatedBlock(ForkJoinPool.java:3448)
>>         at java.base/jdk.internal.misc.Blocker.managedBlock(Blocker.java:185)
>>         at java.base/java.io.FileOutputStream.write(FileOutputStream.java:365)
>>         at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:126)
>>         at java.base/java.io.BufferedOutputStream.lockedFlush(BufferedOutputStream.java:251)
>>         at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:239)
>>         at java.base/java.io.PrintStream.lockedWrite(PrintStream.java:655)
>>         at java.base/java.io.PrintStream.write(PrintStream.java:633)
>>         at java.base/sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:308)
>>         at java.base/sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:404)
>>         at java.base/sun.nio.cs.StreamEncoder.lockedFlushBuffer(StreamEncoder.java:126)
>>         at java.base/sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:113)
>>         at java.base/java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:176)
>>         at java.base/java.io.PrintStream.lockedWriteln(PrintStream.java:859)
>>         at java.base/java.io.PrintStream.writeln(PrintStream.java:836)
>>         at java.base/java.io.PrintStream.println(PrintStream.java:1178)
>>         at VTCompensate$1.run(VTCompensate.java:45)
>>         at java.base/java.lang.VirtualThread.run(VirtualThread.java:270)
>>         at java.base/java.lang.VirtualThread$VThreadContinuation.lambda$new$0(VirtualThread.java:155)
>>         at java.base/jdk.internal.vm.Continuation.enter0(Continuation.java:377)
>>         at 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 re-submit vt-0 to ForkJoinPool, it will call signalWork() of ForkJoinPool and signalWork() do nothing because current c > 0L and the judgement of c < 0L will jump over the loop(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.
>
> Miao Zheng has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR.

Thanks for your response.

I found there are many logic of managedBlock added to Loom. And there are many original paths to managedBlock which will invoke tryCompensate eventually.

The problem of this PR is compensated threads may not be used when RC of FJP greater than -Djdk.defaultScheduler.parallelism while pin happens.

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

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


More information about the loom-dev mailing list