Expand description
Timer-backed sleep / sleep_until futures — the RTEMS backend for
crate::runtime::task::sleep / crate::runtime::task::sleep_until
(decision A2, increment W3b item 4).
§Model
A hosted build sleeps via tokio::time::sleep, whose waker is driven by the
tokio timer wheel. RTEMS has no such wheel, so a Sleep future arms a
one-shot entry on the DelayedTimer:
on its first poll it schedules a wakeup for its deadline; when that wakeup
fires it wakes the future’s stored waker, and the next poll — now past the
deadline — returns Ready. This is the same deadline-ordered timer thread
that backs C callbackRequestDelayed (callback.c:410-419); a Sleep is
just that facility with the “callback” being “wake this future”.
§Why the wakeup runs on the timer thread, not the callback pool
The wakeup is armed via TimerHandle::schedule_wake, so it runs inline
on the timer thread rather than being dispatched to the callback pool.
Waking is a non-blocking waker.wake() (an unpark for a park_on driver,
a task re-enqueue for super::future_exec, or a tokio task-schedule) and
needs no worker, so it does not take one. Routing the wake off the band keeps
the band’s sole job “run futures” and makes the wake uniform for every
sleeper — bare spawned tails and periodic-scan interval alike.
This is also what closed the sleep-wake self-deadlock (bug_pattern rtems-exec-sleep-wake-band-deadlock): back when future_exec parked a pool
worker for a spawned future’s whole life, a wake dispatched to the same
single-worker band sat behind the very worker it had to wake. That executor
is cooperative now and releases its worker at every suspension, so the wake
would no longer starve — but a wake that costs a worker is still the wrong
shape, and Inline remains the rule.
§Lazy arming and drop-cancel
The deadline is fixed when the Sleep is constructed (now + dur for
sleep, the given instant for sleep_until), matching tokio, but the
timer entry is armed lazily on the first poll — a Sleep that is
created and dropped without ever being awaited schedules nothing.
A Sleep owns the queue entry it arms: TimerHandle::schedule_wake
hands back a WakeKey, and Sleep’s Drop both clears the stored waker
and cancels that key. Clearing the waker is what makes the cancel clean — a
wake that races the drop finds no waker and wakes nobody — and cancelling the
key is what makes it free: the entry holds a clone of the shared
Arc<Mutex<SleepState>>, so leaving it queued keeps that cell and the OS
mutex inside it alive for the entire remaining delay.
That retention is not theoretical and not small. A select! arm holding a
long-period interval tick re-arms a fresh Sleep on every loop iteration
and drops it when another arm wins, so an uncancellable entry accumulates at
the loop’s iteration rate for the whole period. Measured on VxWorks 7 against
the PVA search engine’s 180 s BEACON_CLEAN_INTERVAL tick: ~124 live entries
at ~184 B each, released in one batch every 180 s
(doc/vxworks-dial-attempt-residue-on-target-measurement.md).
Cancellation is a property of the wake path only.
TimerHandle::schedule — C callbackRequestDelayed
(callback.c:410-419) — stays fire-and-forget, because there the caller
keeps no handle and the queue is the only owner.
Structs§
- Sleep
- A future that completes at a fixed deadline, driven by the delayed-callback
timer — the RTEMS-side mirror of
tokio::time::Sleep. - Timer
Interval - A periodic ticker over the delayed-callback timer — the RTEMS backend for
crate::runtime::task::interval. Mirrorstokio::time::Intervalwith its defaultMissedTickBehavior::Burst: the first tick is immediate and tick deadlines are anchored at construction (start + period,start + 2·period, …), so an overdue tick fires immediately and successive overdue ticks burst back-to-back until the schedule is caught up.
Functions§
- interval
- Build a periodic ticker firing every
period, backed bytimer— the runtime-free mirror oftokio::time::interval. - sleep
- A future completing
durfrom now — mirrorstokio::time::sleep. The deadline is fixed at construction; the timer entry arms on first poll. - sleep_
until - A future completing at
deadline— mirrorstokio::time::sleep_until. A deadline already in the past makes the future ready on its first poll without arming a timer entry.