Skip to main content

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///
24/// Returns `false` — and installs nothing — when this build has no wake
25/// object to park on. That build keeps the millisecond `wake_wait_ms` path it
26/// already had, which is why every caller can treat this as advisory.
27///
28/// `granularity_us` is the finest park the primitive can express. The PORT
29/// states it, because only the port knows: an RTOS tick is a coarser limit
30/// than the ABI signature (ThreadX ticks at 100 Hz) and a timespec primitive a
31/// finer one (issue 1242).
32#[cfg(all(feature = "alloc", feature = "rmw-cffi"))]
33pub fn install_port_park(
34    executor: &mut Executor<'_>,
35    park: ParkUntilFn,
36    granularity_us: u64,
37) -> bool {
38    let wake = executor.wake_raw_ptr();
39    if wake.is_null() {
40        return false;
41    }
42    executor.set_park_primitive(park, wake, granularity_us);
43    true
44}