Fix deadlock (#10545)
yieldCapability() was not prepared to be called by a Task that is not either a worker or a bound Task. This could happen if we ended up in yieldCapability via this call stack: performGC() scheduleDoGC() requestSync() yieldCapability() and there were a few other ways this could happen via requestSync. The fix is to handle this case in yieldCapability(): when the Task is not a worker or a bound Task, we put it on the returning_workers queue, where it will be woken up again. Summary of changes: * `yieldCapability`: factored out subroutine waitForWorkerCapability` * `waitForReturnCapability` renamed to `waitForCapability`, and factored out subroutine `waitForReturnCapability` * `releaseCapabilityAndQueue` worker renamed to `enqueueWorker`, does not take a lock and no longer tests if `!isBoundTask()` * `yieldCapability` adjusted for refactorings, only change in behavior is when it is not a worker or bound task. Test Plan: * new test concurrent/should_run/performGC * validate Reviewers: niteria, austin, ezyang, bgamari Subscribers: thomie, bgamari Differential Revision: https://phabricator.haskell.org/D997 GHC Trac Issues: #10545 (cherry picked from commit 111ba4be)
Showing
- rts/Capability.c 186 additions, 115 deletionsrts/Capability.c
- rts/Capability.h 1 addition, 7 deletionsrts/Capability.h
- rts/RtsAPI.c 1 addition, 1 deletionrts/RtsAPI.c
- rts/Schedule.c 7 additions, 7 deletionsrts/Schedule.c
- rts/Task.h 11 additions, 0 deletionsrts/Task.h
- testsuite/tests/concurrent/should_run/RandomPGC.hs 597 additions, 0 deletionstestsuite/tests/concurrent/should_run/RandomPGC.hs
- testsuite/tests/concurrent/should_run/all.T 4 additions, 0 deletionstestsuite/tests/concurrent/should_run/all.T
- testsuite/tests/concurrent/should_run/performGC.hs 24 additions, 0 deletionstestsuite/tests/concurrent/should_run/performGC.hs
- testsuite/tests/concurrent/should_run/performGC.stdout 400 additions, 0 deletionstestsuite/tests/concurrent/should_run/performGC.stdout
Loading
Please register or sign in to comment