Skip to main content

zerodds_rt_linux/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3
4//! Crate `zerodds-rt-linux`. Safety classification: **COMFORT** (FFI-Boundary
5//! per Konvention — siehe `docs/architecture/04_safety_by_architecture.md`
6//! §2.3 COMFORT-Klasse).
7//!
8//! Linux Real-Time-Scheduling Adapter — `sched_setattr` (FIFO/RR/DEADLINE)
9//! + `sched_setaffinity` (CPU-Pinning) + `current_scheduler()`.
10//!
11//! ## Schichten-Position
12//!
13//! Layer 4 — Core Services. Linux-spezifische FFI-Schicht; auf
14//! Nicht-Linux-Targets sind alle Public-APIs `io::Error::Unsupported`.
15//!
16//! # Warum COMFORT statt SAFE
17//!
18//! Diese Crate ist die einzige Stelle im ZeroDDS-Workspace, an der
19//! `unsafe`-Syscalls in den Runtime-Pfad gelangen. Der Rest des
20//! Workspaces bleibt `forbid(unsafe_code)` bzw. SAFE. Begruendung:
21//!
22//! * Linux-RT-Profile (SCHED_FIFO, SCHED_RR, SCHED_DEADLINE) und
23//!   CPU-Pinning sind **nur** ueber Syscalls erreichbar.
24//! * `nix` als sicherer Wrapper traegt 12 transitive Crates und
25//!   liefert keinen `sched_setattr`/`SCHED_DEADLINE`-Support.
26//! * `libc` ist die transitive Standard-Dep — kein zusaetzlicher
27//!   Footprint, FFI-Definitionen sind seit Jahren stabil.
28//!
29//! # Architektur
30//!
31//! Drei Module, jeweils mit klaren Invarianten:
32//!
33//! * [`scheduler`] — `SchedulerProfile`-Enum + `apply_to_current_thread`.
34//! * [`affinity`] — `pin_current_thread_to_cpus` mit `cpu_set_t`.
35//! * `syscalls` (privates Modul) — alle `unsafe { libc::... }`-Calls liegen hier; jede
36//!   Funktion ist eine duenne, dokumentierte Wrapper-Schicht ueber
37//!   einem einzelnen Linux-Syscall, mit `// SAFETY:`-Kommentar pro
38//!   Block.
39//!
40//! Auf Nicht-Linux-Targets liefern alle Public-APIs
41//! `io::Error::Unsupported` und kompilieren ohne libc — der Workspace
42//! baut weiter auf macOS/Windows.
43//!
44//! # Privilegien
45//!
46//! `SCHED_FIFO`/`SCHED_RR` mit Priority > 0 + `SCHED_DEADLINE` brauchen
47//! `CAP_SYS_NICE` (effective). Default-User-Tests bekommen `EPERM`
48//! zurueck — die Test-Suite handelt das als "skipped" und behauptet
49//! nicht, der Pfad sei verifiziert.
50//!
51//! # Threat-Model + Invarianten
52//!
53//! Alle FFI-Calls in diesem Crate halten folgende Invarianten ein:
54//!
55//! 1. **Kein Pointer-Outliving:** jeder an einen Syscall uebergebene
56//!    Pointer zeigt auf eine Stack-lokale Struktur, deren Lebensdauer
57//!    den Syscall ueberlappt. Kein Heap, kein 'static-Aliasing.
58//! 2. **Kein FD-Leak:** keiner der genutzten Syscalls erzeugt File-
59//!    Descriptors.
60//! 3. **Kein Memory-Aliasing:** Buffer sind exklusiv (`&mut T`)
61//!    waehrend des Aufrufs.
62//! 4. **Errno-zu-Result:** jeder Syscall-Returnwert wird per
63//!    `io::Error::last_os_error()` in ein Rust-`io::Result` gehoben;
64//!    `errno` wird genau einmal gelesen, vor jeder weiteren libc-
65//!    Operation.
66//! 5. **Keine Mut-Aliasing-Race:** alle Calls beziehen sich auf den
67//!    **eigenen** Thread (`tid = 0` ist Linux-Konvention fuer
68//!    "calling thread"), nicht auf andere Threads — dort waeren
69//!    Race-Conditions zwischen User-Code und Syscall denkbar.
70//!
71//! # Test-Strategie
72//!
73//! * Alle Tests nutzen `#[cfg(target_os = "linux")]`.
74//! * Tests, die `EPERM` produzieren (FIFO mit prio>0, DEADLINE),
75//!   pruefen den Errno-Pfad statt das Setting zu erzwingen.
76//! * `current_scheduler()` ist privilegienfrei und wird per
77//!   Round-Trip-Test nach `apply` verifiziert (sofern erlaubt).
78//!
79//! Spec: keine OMG-Spec — Linux-Kernel-API. References:
80//! `sched(7)`, `sched_setattr(2)`, `sched_setaffinity(2)`.
81
82#![cfg_attr(not(feature = "std"), no_std)]
83#![warn(missing_docs)]
84
85#[cfg(feature = "std")]
86extern crate std;
87
88pub mod affinity;
89pub mod scheduler;
90
91#[cfg(target_os = "linux")]
92mod syscalls;
93
94pub use affinity::pin_current_thread_to_cpus;
95pub use scheduler::{RunningSchedulerInfo, SchedulerKind, SchedulerProfile};