Absolute-grid cyclic dispatch¶
Detailed design for the absolute-grid cyclic dispatch of Absolute-grid cyclic dispat... (REQ_0268)
(under Cyclic scan execution (FEAT_0011)): the self-computed grid timer, the Linux
timerfd master-tick wake path, the Grid | Legacy toggle, and
the scan-count-plus-skip-signal lateness anchoring of Lateness grid anchored on s... (ADR_0101).
The two dispatch modes differ in how the WaitSet decides when to wake. The
Legacy path arms an iceoryx2 attach_interval heartbeat and computes
a relative epoll timeout from a now sampled before the syscall, so
the wakeup→dispatch round-trip δ leaks into every interval and lateness
accumulates. The Grid path (production, Linux) blocks on the readiness
of a single absolute timerfd armed at base_period and dispatches the
due tasks in a post-wait take_due pass, immune to the millisecond
rounding of the relative timeout:
flowchart TD
Mode{"DispatchMode"}
subgraph Legacy["Legacy (relative timer)"]
LArm["WaitSet::attach_interval(period)"]
LWait["epoll timeout = now + period<br/>(now sampled pre-syscall)"]
LWake["wake at-or-after timeout<br/>δ round-trip uncorrected"]
LDisp["dispatch on attach_interval callback"]
LDrift["realized period = period + δ̄<br/>→ lateness accumulates"]
LArm --> LWait --> LWake --> LDisp --> LDrift --> LWait
end
subgraph Grid["Grid (absolute timerfd, Linux)"]
GEpoch["sample scheduling epoch once<br/>at dispatch_loop entry (CyclicClock)"]
GArm["arm single master timerfd<br/>TFD_TIMER_ABSTIME @ base_period = gcd"]
GBlock["WaitSet blocks Duration::MAX on<br/>fd-readiness (attach_notification)"]
GTick["kernel hrtimer makes fd readable<br/>at exact grid point, auto-rearms"]
GDrain["drain timerfd (8-byte read)<br/>drain() > 0 gates the pass"]
GDue["GridTimer::take_due(now):<br/>collect due tasks, skip-realign stalls"]
GDisp["post-wait pass dispatches each<br/>due task; barrier_and_record"]
GEpoch --> GArm --> GBlock --> GTick --> GDrain --> GDue --> GDisp --> GBlock
end
Mode -->|"Legacy (default non-Linux)"| Legacy
Mode -->|"Grid (default Linux)"| Grid
Architecture Decision: Absolute-grid cyclic dispatch via Linux timerfd; self-computed epoll timeout fails on ms-rounding ADR_0100
|
Context. The first real-hardware telemetry capture (the
Root cause (iceoryx2 0.8.1 source): cyclic ticks arm via
Decision. Stop using This supersedes the original self-computed-timeout decision (a
Alternatives weighed.
Consequences. Long-run lateness is bounded. Pi5 FIFO A/B of the
single master timerfd ( Metric caveat. Per-task deadline lateness (REQ_0106)’s |
The structural surface that realises Absolute-grid cyclic dispat... (ADR_0100), in
Wiring: on Linux the single master |
Concrete changes in
|
|
|
Context. Issue #46: Per-task deadline lateness (REQ_0106)’s original grid-slot
reconstruction ( Decision. Advance the lateness grid slot by exactly one per
scan attempt plus a dispatcher-signalled skip count
(Per-task skipped-slot count (REQ_0840)), and anchor Rejected alternatives.
Consequences. Coalesced catch-up pairs report one transient
positive spike and heal; dispatcher skips re-anchor through the
signal and become observable ( |
Context. In released Decision. Promote the existing Rejected alternatives.
Consequences. The at-most-one-submit contract holds by
construction, not by accident of the per-callback barrier, so the
barrier-consolidation slice can proceed. A task with two fired
attachments in one wake-phase now runs once (draining all pending
input via |
Architecture Decision: AttachmentMap — sorted-Vec O(log n) attachment-to-task resolution with lazy-learn dual identity ADR_0106
|
Context. Decision. A single sorted Dual identity / lazy-learn. A deadline attachment’s missed-deadline
fire is the precomputable Deliberate flattening. Consequences. Steady-state resolution is O(log n) and allocation-free
(capacity reserved at |