nros_node/executor/port_park.rs
1// Copyright (c) 2026, NEWSLab NTU.
2// SPDX-License-Identifier: Apache-2.0
3
4//! phase-436 W7 — installing a port's park primitive, in one place.
5//!
6//! Every Rust board entry that wires the seam needs the same three steps and
7//! the same non-obvious constraint, so they live here rather than being spelt
8//! once per board and drifting.
9//!
10//! **The constraint.** A `ParkUntilFn` must wait on the executor's OWN wake
11//! object. The backend's listener signals that one, and [`spin_once`] drops
12//! its transport drain to non-blocking once a port has parked — so a park on
13//! any other object cannot be broken by data arriving, and sleeps out its full
14//! deadline with a message already waiting. That is worse than not parking at
15//! all, it passes every test, and it is invisible in a quiet run.
16//!
17//! [`spin_once`]: crate::executor::Executor::spin_once
18
19#[cfg(all(feature = "alloc", feature = "rmw-cffi"))]
20use super::spin::{Executor, ParkUntilFn};
21
22/// Install `park` on `executor`, waiting on the executor's own wake object.
23/// The park is its worker's (phase-509 P6, RFC-0108 D7): the one-level
24/// executor has one worker, and a worker of a scheduler with several levels
25/// parks on its own wake object, which only its band's arrivals signal.
26///
27/// Returns `false` — and installs nothing — when this build has no wake
28/// object to park on. That build keeps the millisecond `wake_wait_ms` path it
29/// already had, which is why every caller can treat this as advisory.
30///
31/// `granularity_us` is the finest park the primitive can express. The PORT
32/// states it, because only the port knows: an RTOS tick is a coarser limit
33/// than the ABI signature (ThreadX ticks at 100 Hz) and a timespec primitive a
34/// finer one (issue 1242).
35#[cfg(all(feature = "alloc", feature = "rmw-cffi"))]
36pub fn install_port_park(
37 executor: &mut Executor<'_>,
38 park: ParkUntilFn,
39 granularity_us: u64,
40) -> bool {
41 let wake = executor.wake_raw_ptr();
42 if wake.is_null() {
43 return false;
44 }
45 executor.set_park_primitive(park, wake, granularity_us);
46 true
47}