implement a pipe based sleep strategy using the IO subsystem
Data:
Global:
hint pipe
sleepers count
Per worker:
dispatch hint buffer
in flight flag
Sleep:
if we have no sleep request in flight
Atomic increment sleep count
Remember that we are sleeping
Prepare read cqe from the hint pipe to dispatch hint buffer
Prevent the completer from reaping completions on this worker's IoContext
Wait until IO completions occurred
NotifyEmper(n):
if observed sleepers <= 0
return
// Determine how many we are responsible to wake
do
toWakeup = min(observed sleepers, n)
while (!CAS(sleepers, toWakeup))
write toWakeup hints to the hint pipe
NotifyAnywhere(n):
// Ensure all n notifications take effect
while (!CAS(sleepers, observed sleepers - n))
if observed sleeping <= -n
return
toWakeup = min(observed sleeping, n)
write toWakeup hints to the hint pipe
onNewWorkCompletion:
reset in flight flag
allow completer to reap completions on this IoContext
AbstractWorkStealingScheduler::nextFiber
.
This allows workers to check the dispatch hint after there
where no local work to execute.
This is a trade-off where we trade slower wakeup - a just awoken worker
will check for local work - against a faster dispatch hot path when
we have work to do in our local WSQ.Thanks to Florian Schmaus flow@cs.fau.de for spotting bugs and suggesting improvements.