Expand description
Holding still for a set time, waiting for nothing.
§Why this exists
Some hardware needs a gap that no register reports: let a reset bit land before the next write,
give a port the recovery time a specification demands before it is addressed. Nothing can be read to
say the gap is over, so this is not a wait - there is no condition, only a
duration. Drivers wrote it by hand, and the copies disagreed about the one case that matters, a
machine whose clock the kernel could not calibrate:
genet’sdelay_usyielded once, which returns at once when nothing else is runnable;xhci’s two holds built their length fromduration_cycles, which floors to one counter tick there, so they held for nothing at all.
Both are the same mistake in the direction that matters. A hold is a MINIMUM: the device needs at least this long, and the safe error is too long, never too short.
§What it does
use godspeed::driver::delay;
use godspeed::driver::wait::Budget;
m.write32(CMD, SW_RESET);
delay::hold(ctx, Budget::us(10)); // the reset bit needs time to land; nothing says when it has
m.write32(CMD, 0);On a calibrated machine hold spins for the duration, measured by the counter. It does not
sleep: on every port but ARMv7 (whose sub-tick sleep is not relied on here) the kernel’s sleep
floors at a scheduler quantum, nominally 10 ms (CLAUDE.md 9.1), which would
turn a 10 us hold into a thousand times that. hold_parked sleeps first and spins out the
rest, for holds of tens of milliseconds where the core matters more than the microsecond: it can
run up to a quantum long, which a minimum allows, and is never short. It has three callers (ehci,
wifi-usb’s rtl8188 backend, and sdk/audio’s settings read, pausing between retries), and it is
in on probation: docs/driver-library.md 1l says why.
On an uncalibrated one both sleep whole quanta, as many as the duration needs at the nominal
10 ms: the quantum is measured by the kernel’s tick rather than the counter nobody could calibrate,
so it is the one duration left, and it errs long. super::wait::calibrated says which case this
machine is in.
It does not log, for the reason wait does not: it cannot fail.
Functions§
- hold
- Hold for at least
d. Spins on a calibrated machine; sleeps whole scheduler quanta on one that is not. See the module documentation. - hold_
parked - Hold for at least
d, PARKED: sleep through it, then spin out whatever the sleep left. For holds of tens of milliseconds - a USB reset, a debounce - where the core matters more than waking on the microsecond.