Skip to main content

Module exec_lock

Module exec_lock 

Source
Expand description

phase-509 P9b – the executor’s lock (RFC-0108 “As built in P9b”). phase-509 P9b item 1 (RFC-0108 “As built in P9b”) – the executor’s lock.

RFC-0108 runs one executor per core with one worker thread per preemption level. Every path that touches the executor’s state – a worker’s pass, and every C / C++ FFI entry a callback or another thread calls – then has to be serialised, and that is this lock: a port-provided, RECURSIVE, PRIORITY-INHERITING mutex (nros_platform_mutex_rec_* on every port), which the runner installs on the executor before a second thread can reach it.

An executor with no lock installed (every one-level image, every Rust &mut user) takes the None arm: a guard is one predictable branch and nothing else, so this seam changes no behaviour where it is not installed.

Why recursive: an owned pass (spin_once(&mut self)), and a pass whose lock has no thread identity, hold the lock across each user callback, so a callback that calls back into the executor (timer_cancel, *_release, a parameter call) re-enters it on the same thread.

Item 2 – the callback window. A shared or band pass (Executor::spin_once_shared, Executor::spin_band_once) whose lock carries the port’s thread identity (ExecLock::with_thread_id) gives the lock for each user callback and takes it back after (Window). The entry stays marked running (its slot tag), so no other pass dispatches or probes it and its release is deferred; a Running record names the thread running it, so an entry operation from another thread is told apart from one the callback makes itself: the entry accessors answer as for a stale handle, and a timer cancel or reset is deferred to the callback’s return.

Why priority-inheriting: a less urgent worker holding the lock for a bookkeeping step must run at the waiter’s priority, so a more urgent level’s blocking is bounded by ONE critical section (RFC-0108 B_i).

Interrupt handlers never take it: arrivals go through the scheduler’s lock-free ready word and the wake object, exactly as before.

Structs§

ExecGuard
Holds the executor’s lock for its own lifetime: taken at ExecGuard::acquire, given at drop. With no lock installed it holds nothing.
ExecLock
The executor’s lock: the port’s recursive priority-inheriting mutex and the two calls that take and give it. Installed once, before any second thread can reach the executor (super::Executor::set_exec_lock), and never changed while one can.

Type Aliases§

ExecLockFn
A port’s lock or unlock entry, nros_platform_mutex_rec_lock’s shape: 0 on success, negative on failure.
ThreadIdFn
The calling thread’s identity, as the port names it (k_current_get, pthread_self): equal on one thread, distinct across live threads.