diff --git a/ROADMAP.md b/ROADMAP.md index 4716dbd..e8388c2 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -113,6 +113,26 @@ shared instead" check. In scope only if the data demands it. ## Later +### Unwakeable idle sleep when io is absent (terminal-wake residual) +The `(Some(deadline), None)` idle branch — timers pending, io subsystem never +initialized — blocks in `thread::sleep` with no wake mechanism at all. The +terminal wake (writes the wake pipe at AllDone) cannot reach it: no io, no +pipe. Same stall as the fixed bug, in any no-io runtime: a sibling that +blocked on an orphaned deadline sleeps it out in full after everything else +finished. Candidates, mutually exclusive: (a) clamp the sleep (cheap, but +turns idle into periodic wakeups), or (b) park the branch on a condvar/futex +the AllDone path signals — and at that point consider making the condvar the +idle primitive for the no-io runtime generally (a cross-thread unpark could +signal it too, see below). Decide before any no-io deployment. + +### Cross-thread unpark +`RuntimeInner::enqueue` does not wake idle sibling schedulers — only io +completions write the wake pipe. Mid-flight this is masked (the enqueuing +thread is awake and eats the work itself), but it costs parallelism: work +enqueued by a busy thread waits until the sibling's idle poll times out. +Candidate from the urus chunk-2 session; needs bench evidence (does the +shared-queue handoff latency actually show up?) before a mechanism is picked. + ### Per-switch cost (context shims, epoch protocol) The shootout's residual: per-wake latency is 0.16–0.18 µs at N=1 and 0.8–1.2 µs at N=8+, dominated by the context-switch shims and the epoch