Crates.io | linux-rtic |
lib.rs | linux-rtic |
version | 0.1.1 |
source | src |
created_at | 2021-10-12 21:14:48.984749 |
updated_at | 2021-10-15 10:11:51.354702 |
description | A Real-Time Interrupt-driven Concurrency (RTIC) implementation for Linux |
homepage | https://github.com/chemicstry/linux-rtic |
repository | https://github.com/chemicstry/linux-rtic |
max_upload_size | |
id | 464205 |
size | 58,229 |
An RTIC implementation for real-time Linux.
This implementation of RTIC is based on std::thread
by spawning a thread for each task priority group. Threads are initialized with SCHED_FIFO
real-time policy. Task priorities correspond 1:1 to Linux priorities and usually have a range of 1-99.
Scheduling of tasks is done by futex-queue, which cleverly utilizes futex syscall to wait on both immediate and scheduled (timed) tasks on a single syscall. No timer thread (and additional context switching) is required.
Original cortex-m-rtic uses Stack Resource Policy (SRP), but it is difficult to emulate in userspace Linux. Firstly, setting thread priority for each lock/unlock involves an expensive syscall (~10us on Raspberry Pi 4). Secondly, setting thread priority does not guarantee that lower priority thread will not run. Lower priority thread can be executed on a different core, or when higher priority thread is suspended (i.e. I/O syscall). While it is possible to fix memory safety issues by a backup synchronisation mechanism (mutex), the syscall overhead is too high for real-time applications.
To solve the issue, a pcp-mutex library was written, which implements Original Priority Ceiling Protocol (OPCP). This allows preserving two important properties of SRP: bounding priority inversion and statically preventing deadlocks. This mutex is lock-free in the fast path. Technical details are in the pcp-mutex README.
Scheduling tasks in userspace threads is slow due to context switching overhead (~10us on Raspberry Pi 4) and other approaches were explored:
no_std
. Also, resource locking slower, because of signal masking syscalls.Running examples requires Linux with PREEMPT-RT patched kernel for SCHED_FIFO
and root privileges. This requirement can be lifted by compiling with --no-default-features
, but then all tasks will share the same priority.
Build:
cargo build --release --example priority_inversion
Run (requires sudo for sched_setscheduler
syscall):
sudo target/release/examples/priority_inversion
Single core:
sudo taskset -c 1 target/release/examples/priority_inversion
No real-time priorities:
cargo run --release --example priority_inversion --no-default-features
PREEMPT-RT
kernel patch and compile kernel with CONFIG_PREEMPT_RT_FULL
to reduce non-preemptable sections in the kernel.cpufreq-set -g performance
.isolcpus
kernel parameter to run RTIC on an isolated core.spi0
) is scheduled with real-time priority: sudo chrt -f -p 50 $(pidof spi0)
.This work was done as a part of my Thesis at University of Twente.