Expand description
RFC-0052 / phase-296 W3b.4/.5 — on-target contract monitors.
The baked shape mirrors Phase 211.H’s qos_overrides: codegen emits a
&'static [MonitorSpec] table (plus one static PubMonitorCell per
contracted publisher) from the SystemModel’s contract layer; the entry
installs it on the executor before entity creation. An uncontracted
image bakes an empty table — every path below dead-code-eliminates.
Publish counting is an atomic bump on the publisher handle (no clock,
no lock on the hot path); the rate check runs on spin ticks over a
~RATE_CHECK_INTERVAL_US window and pushes violations into a small
ring the entry glue drains into the nros-diagnostics reporter.
W3b.5 adds three more rules on the same drain:
max-age-runtime— subscriber take-age (epoch_now - header.stamppeeked from the raw CDR buffer atRosMessage::STAMP_OFFSET, recorded into aSubMonitorCellon the take path).max-latency-runtime— node-path (take → publish) latency: the dispatch elapsed time is attributed to every monitored publisher whose counter advanced during that dispatch (an upper bound on take → publish, measured on the executor’s monotonic clock). The span is callback entry to exit, for every dispatch kind: a timer callback is timed whether it fires in the drains or in the trigger-miss sweep (phase-474 I6), and a service call it makes is inside the span. The timer’s release jitter (a late start) is not part of it; that isrelease-jitter-runtime.deadline-miss-runtime— a dispatched callback ran past its bound SchedContext’sdeadline_us; what ELSE happens is the tier’sDeadlineAction.
phase10-B3 adds the route rule beside it:
route-latency-runtime– a node path whose trigger is an INPUT is budgeted from the TAKE of that input to its output, and on a node that reads its input on a timer tick that span includes the wait for the next tick.max-latency-runtimetimes one dispatch and cannot see the wait, so a route made of a long tick wait and a slow dispatch could exceed its budget while every callback passed. The executor stamps the dispatch that takes the trigger input (the earliest take not yet answered) and, at the end of a dispatch that published one of the path’s outputs, judges take-to-dispatch-end against the path’smax_latency_ms(route_take,route_judge). Record only: the rule has no action.
phase-462 W2 adds one more on the same drain, and it is the other half of
what the contract’s on_violation lowers to:
silence-runtime– a contracted subscription that took NOTHING for a wholemax_age_mswindow (check_silence). A violation is either “the callback ran too long”, which is the deadline action, or “the input stopped coming”, which is this; the four rules above can only see the first kind.
Structs§
- AgeMonitor
Spec - One monitored subscriber endpoint (W3b.5 age contracts). Separate
table from
MonitorSpec— sub contracts key different endpoints and need no publish counter. - Guard
Spec - One fault a hazard covers: a topic, or a redundant set of topics.
- Hazard
Cell - One hazard’s observer state. Baked as a
staticbeside the spec, the wayPubMonitorCellis, so the observer adds a slice to theExecutorvalue and nothing per hazard (issue 0961). - Hazard
Spec - One contracted hazard (
contracts.hazards), lowered by the bake. - Monitor
Arming - phase-474 I2 – when an executor’s contract monitors start judging.
- Monitor
Spec - One monitored publisher endpoint.
- Monitor
Table Full - A monitor table longer than the executor can watch – phase-496 W1.
- PubMonitor
Cell - One contracted publisher’s counters. Baked as a
staticby codegen (or declared by the fixture); the publisher handle bumpscounton every publish, the executor reads deltas on spin ticks. - Reaction
Event - phase-503 – what the reaction hook receives when a supervised route
passes its deadline.
repr(C): the C ABI hands the same struct through. - SubMonitor
Cell - One contracted subscriber’s take-age accumulator (W3b.5). The take
path records
epoch_now - header.stampper message (fetch_max); the age check drains it (swap 0) per window. - Violation
- A detected contract violation, in the play_launch rule-id vocabulary.
- Violation
Record - phase-474 I1 – the image-wide violation record a debugger reads by NAME, for a board whose console reaches nobody.
- Violation
Slot - One slot of the SWD record. Every field is a
u32on every target, so the layout is the same on a 32-bit board and a 64-bit host.
Enums§
- Guard
Ref - One guard member: which monitor row’s verdict says this topic has faulted.
Constants§
- MARKER_
VIOLATION - phase-474 I1 – trace marker: a stored violation,
seq << 8 | rule code. The id block continuescallback_trace’s 16-20; ids 1-7 are the application’s and are never used here. - MARKER_
VIOLATION_ DECLARED - phase-474 I1 – trace marker:
declared. - MARKER_
VIOLATION_ FQN - phase-474 I1 – trace marker: the endpoint ref’s
fqn_hash. - MARKER_
VIOLATION_ MEASURED - phase-474 I1 – trace marker:
measured. - MAX_
AGE_ MONITORS - Max AGE-monitored subscriptions per executor – the second table, on its
own knob (
NROS_EXECUTOR_MAX_AGE_MONITORS, derived fromage_rows) so an image with rate contracts and no age contracts pays for one table only. - MAX_
MONITORS - Max RATE/LATENCY-monitored endpoints per executor (inline table, no_std).
- MAX_
VIOLATIONS - Violation ring depth, per executor, and the slot count of the image-wide
SWD record (
ViolationRecord). - MECHANISM_
EXECUTOR - phase-503 –
MonitorSpec::mechanism: checked in the executor’s spin loop. Catches a slow route, not a callback that never returns. - MECHANISM_
TIMER - phase-503 –
MonitorSpec::mechanism: an independent timer outside the executor (the port’s), which also catches a stuck callback. - NO_SINK
HazardSpec::sinkwhen the hazard’s reaction states nosafe_statepublisher this image monitors: the observer reports detection and recovery, and no reaction.- RATE_
CHECK_ INTERVAL_ US - Rate-check window (µs). Matches play_launch’s ~5 s time-based trigger so both runtimes converge on comparable cadence.
- REACTION_
NONE - phase-503 –
MonitorSpec::reaction_id: no reaction named. - RECORD_
HEADER_ WORDS u32words in theViolationRecordheader, before the first slot.- RECORD_
MAGIC "NRVR"– nano-ros violation record.- RECORD_
SLOT_ WORDS u32words in oneViolationSlot.- RECORD_
VERSION ViolationRecordlayout version. Bump on any field change; a reader refuses a version it does not know (scripts/read-violation-record.py).- REPORT_
DEFER_ MAX_ US - phase-474 I7 – the longest a pending verdict waits for a slot with slack before it is reported anyway, in microseconds. Bounds the deferral on an executor whose timers never leave a gap as long as the report costs.
- REPORT_
QUEUE - phase-474 I7 – how many stored verdicts wait for the sink. A verdict
stored while the queue is full evicts the oldest pending one, which is
counted (
ReportQueue::overflowed); both stay in the ring and the SWD record. Four is theDiagnosticArraystatus capacity of the generated type, so one coalesced report never needs more. - ROUTE_
PENDING - phase10-B3 –
PubMonitorCell::route: a take of the trigger input is waiting for this output. - ROUTE_
SLOT_ MASK - phase10-B3 –
PubMonitorCell::route: the bound slot + 1. - ROUTE_
VIOLATED - phase10-B3 –
PubMonitorCell::route: the last judged route was over its budget (report once until one is within it, as the latency rule does). - RULE_
IDS - phase-474 I1 – every rule id the executor reports, in WIRE ORDER: a rule’s numeric code is its index here plus one, and 0 means “not a rule this table knows”.
Functions§
- check_
capacity_ against check_table_capacityagainst explicit capacities, so the refusal is testable at any knob value without rebuilding the crate.- check_
table_ capacity - Whether a table of
n_rowsrate/latency rows andn_agesage rows fits this build’s executor. The rate table is judged first. - fqn_
hash - 32-bit FNV-1a of an endpoint ref – the identity a trace marker and the SWD
record carry for
Violation::fqn(a string neither can hold). - observe_
publish_ stamp - Peek
Time { i32 sec; u32 nanosec }little-endian atoffsetin a raw CDR receive buffer (encapsulation header included) and return µs since the UNIX epoch.Nonewhen the buffer is too short or the stamp is pre-epoch/zero (unstamped messages never fire age monitors). Record the age of the stamp a publisher just put on the wire. - peek_
stamp_ us - request_
monitor_ arming - phase-474 I2 – the application says its start-up is over: arm the
contract monitors of every executor in the image that waits for this
(
NROS_MONITOR_ARM_ON_CALL, orExecutor::set_monitor_arming). - route_
next_ due_ us - phase-503 – time from now to the earliest deadline of a pending supervised
route, in microseconds (0 when one is already due), or
Nonewhen no supervised route is waiting. This is the executor’s wake source for the rule, and what a port’s independent timer (MECHANISM_TIMER) arms on. - rule_
code - The wire code of
rule(RULE_IDSindex + 1), or 0 for a rule the table does not know. - rule_
name - The rule a wire code names, or
Nonefor 0 / an unknown code. - violation_
marker_ words - phase-474 I1 – the four
(marker_id, arg)events one stored violation becomes in a trace (callback_traceemits them, in this order, when thetrace-callbacksfeature is on and a sink is installed).seqis the executor’s sequence number; its low 24 bits ride in the first event.
Type Aliases§
- Reaction
Hook Fn - phase-503 – the reaction hook: called on the spin thread, inside
spin_once, once per missed route deadline. It must not block; it starts the fallback (or hands it to another thread) and returns.ctxis what was registered with the hook. - Violation
Sink - Issue 1635 – where an executor hands its violations when the image asked
it to (
Executor::set_violation_sink).