FREE RAG Converter Online -- RAGconverter.com
The shared vocabulary of Kairos. Ticks, priorities, generational handles,
list.c remade over indices, FreeRTOSConfig.h as a trait, and the four seams
every other package is generic over. No C, no FFI, no pointers, no allocator,
no architecture.
- The types:
Tick<W>at 16/32/64 bits with the wrapping and overflow rulesxTickCountfollows;Priorityvalidated against the config;Handle<K>— a generational index (u16slot +u16generation), never a pointer — andArena<K, T, N>, which answers a stale handle withError::Goneinstead of touching freed memory;Lists<N, L>,list.cremade over indices with sentinel and cursor semantics intact; oneCopyErrorwhosepd_code()maps to the C return codes. - The seams:
Config(FreeRTOSConfig.has a trait with associated consts), plusPort,Heap,HooksandTrace— the last with oneEventper oracle trace macro, 42 of them, which is what makes a line-by-line diff against the C kernel possible at all.
Known gaps. This is vocabulary, not behaviour: no scheduler, no queue, no
timer, no port, no heap. Those are the sibling crates. MAX_PRIORITIES,
arena sizes and list capacities are compile-time constants, so a system's
geometry is declared rather than allocated.
- This package's plan: docs/plans/rusty_rtos_core.md
- Every number: docs/LEDGER.md
- The family plan: Kairos
docs/plans/rtos-mission.md
Claims discipline: this README makes no performance or capability claim that is not backed by a test, a benchmark ledger entry, or a kill test recorded in the plan. "Scaffold" means scaffold. "Sim only" means the sim port; "builds, not flashed" means no chip has run it.
This crate is not diffed against the C kernel directly — it has no behaviour of its own to diff. It is proven through the kernel that uses it: the Kairos conformance corpus produces traces byte-identical to the C kernel's for 100,000 ticks a scenario, and the ready lists, delayed lists and handle arena those traces exercise are all in this crate.
| corpus scenarios byte-identical to the C kernel | 19 |
| architectures the corpus runs on | host, ARMv7-M, RV32, Xtensa LX7 |
| of those, on silicon rather than an emulator | Xtensa LX7 (XIAO ESP32-S3), 18/18 |
unsafe blocks in this crate |
0, enforced by #![forbid(unsafe_code)] |
kairos conform --all --ticks 100000 # from the Kairos umbrellaWhat the list is proven on separately. Lists carries its own rotation
tests, because "a ready task is never chosen" has exactly two causes — it is
not in the list the scheduler looks at, or the cursor is not moving — and
nothing else tells them apart. They cover rotation across other lists being
used, emptied and refilled in between.
Still open: nothing in this crate is timed on a part; the timing rows are the kernel's and the port's.
This crate owns the four pieces a tickless port is built from, and no policy:
| piece | what it is |
|---|---|
Config::USE_TICKLESS_IDLE |
configUSE_TICKLESS_IDLE. Off by default, so a build that ignores it is byte-identical to the C |
Config::EXPECTED_IDLE_TIME_BEFORE_SLEEP |
the sleep floor, 2 ticks |
Port::suppress_ticks_and_sleep |
returns how many ticks it actually slept; returning zero declines, and is the default. A port that overclaims is clamped, not trusted |
trace::Scheduling + is_suppressible |
the projection: passes every event except the three heartbeat kinds, so the schedule can be compared across a suppressed run |
One caveat about Scheduling, learned on silicon. Its guarantee covers
which events happen and in what order. It does not make their tick
stamps invariant on real hardware, where a tick stamp also records how long the
work took — and two arms that sleep differently do not take the same time. On a
simulator, where time is critical-section exits, the stamps are invariant and a
line-for-line diff is sound. Off it, compare the order and bound the clock
separately.
Measured: 401 timer interrupts to 0 on QEMU Cortex-M, 400 to 0 on a XIAO ESP32-S3, with a byte-identical schedule digest in both arms of each.
use rusty_rtos_core::config::Config;
use rusty_rtos_core::handle::{Handle, TaskKind};
use rusty_rtos_core::tick::{Bits32, Tick};
// `FreeRTOSConfig.h`, as a trait. The geometry is declared, not allocated.
#[derive(Debug, Clone, Copy, Default)]
struct MyConfig;
impl Config for MyConfig {
type Tick = Bits32;
const TICK_RATE_HZ: u32 = 1000;
const MAX_PRIORITIES: u8 = 5;
const MINIMAL_STACK_SIZE: usize = 128;
const MAX_TASK_NAME_LEN: usize = 16;
const TIMER_TASK_PRIORITY: u8 = 2;
const TIMER_TASK_STACK_DEPTH: usize = 256;
const TIMER_QUEUE_LENGTH: usize = 10;
const NOTIFICATION_ARRAY_ENTRIES: usize = 3;
}
fn main() {
// A tick wraps the way `xTickCount` wraps, at the width you chose.
let t: Tick<Bits32> = Tick::from_raw(u32::MAX as u64);
assert_eq!(t.wrapping_add(2).raw(), 1);
// A handle is an index plus a generation, so a stale one is detectable
// rather than dangling. This is the property that removes a whole class
// of use-after-free from the kernel above.
let h: Handle<TaskKind> = Handle::new(3, 1);
assert_eq!(h.index(), 3);
assert_ne!(h, Handle::new(3, 2)); // same slot, older generation
}The one row this crate owns is its list, measured against the list.c it
remakes.
| arm | instructions per list operation | vs C |
|---|---|---|
FreeRTOS list.c, -O2, 64-bit |
22.32 | 1.00× |
rusty_rtos_core::list, 64-bit |
18.47 | 0.83× — faster than the C |
FreeRTOS list.c, -O2, 32-bit |
33.42 | 1.00× |
rusty_rtos_core::list, 32-bit |
23.00 | 0.69× — faster than the C |
Re-measured for 0.2.1. It was 46.45 and 2.081× at first, then 34.22 and
1.533×. What closed the gap was reading each node a call touches once
(next_and_value and prev_of replace an accessor that returned more than any
caller needed; link_between takes the after its callers already hold), the
end markers living in the same array as the items so an ordered walk stops on
the marker's MAX value without ever testing for the end — which is exactly
what list.c does — and, in 0.2.1, dropping a marker test in the round-robin
that the wrap above it had already made unreachable.
The per-list cursor and count deliberately stay in their own small array rather than in the marker node, where they would fit the padding exactly. That was built and measured: it loses 3.6%, because a separate array is a no-alias fact the optimiser uses to keep node fields in registers across every count update.
Method: callgrind, three run lengths, the cost taken as the slope so
fixed setup cannot flatter it — and both arms print checksum
7de9075f4deb23e5, which is how you know they did the same work. It cost the
corpus nothing: 18 scenarios still identical to the C kernel at 100,000 ticks,
every arm's ticks, yields, exits and lines equal to the digit.
bench/list-cost/run.sh # from the Kairos umbrellaFor two cores (0.2.4). move_to_end fuses the remove-and-reinsert the SMP
scheduler makes on every switch into one list operation, and the iterator the
scheduler walks a ready list with ends on its count alone. On the two-core
demo corpus (callgrind, 20,000 ticks, the 64-bit host) the two together are
worth about 850,000 instructions on semtest's 67.6 million; the list-cost
row above does not use either and is unchanged. The kernel's README has the
whole two-core campaign.
no_std everywhere, with an alloc rung and a std rung above it. The crate
knows nothing about a CPU, so "portable" here means it compiles and its tests
pass, not that a scheduler ran.
| target | builds | corpus runs above it |
|---|---|---|
| host (x86-64 Windows, Linux) | ✅ | ✅ |
thumbv7m-none-eabi (Cortex-M3) |
✅ | ✅ |
riscv32imac-unknown-none-elf |
✅ | ✅ |
xtensa-esp32s3-none-elf |
✅ | ✅ on silicon |
Default features are std; --no-default-features is pure core.
crates/rusty_rtos_core no_std (+ alloc); forbid(unsafe); no dependencies; the crate every package uses
crates/rusty_rtos_alloc the family's allocator seam: rusty_alloc-api at an exact pin, declared only by deliverables
firmware/ per-chip example projects, excluded from the workspace
docs/plans/ this package's plan and its hardening audit
docs/LEDGER.md every number, with its method line
cargo test --workspace # host: the tests
cargo check -p rusty_rtos_core --no-default-features \
--target thumbv7em-none-eabihf # Cortex-M4F class, no alloc
cargo check -p rusty_rtos_core --no-default-features --features alloc \
--target riscv32imac-unknown-none-elf # ESP32-C6 class, with allocCI holds the core to thumbv7em-none-eabihf, thumbv8m.main-none-eabihf,
riscv32imac-unknown-none-elf and riscv32imafc-unknown-none-elf, with and
without alloc, plus cargo deny check. Firmware examples (Xtensa needs the
esp toolchain; Cortex-M and RISC-V work on stable) are built from their own
directories under firmware/.
The threat model states what this unit protects, who it protects it from, and the residual risks it does not cover, each with an owner, a review date and the condition that closes it.
Two are worth knowing before you adopt it:
- A forged or stale handle cannot reach a live object. Handles carry a
generation, a free slot is marked above anything a C caller can forge, and
that is checked exhaustively, then fuzzed against a reference model
(
fuzz/lists_arena). - No secret enters this crate by design. A value you store in an arena or a list is yours to zeroize; if this crate ever gains a type meant for key material, the model says so and reopens.
This crate is part of Kairos —
FreeRTOS remade in memory-safe Rust, as independent packages that expose the API
a FreeRTOS developer already knows and prove every scheduling decision against
the C kernel's own trace. rusty_rtos_core is the bottom of that stack: every other crate depends on it and it depends on nothing.
Where this sits for Mata. Kairos is the real-time layer on the device
itself, and rusty_rtos_mqtt is the way out of it.
Paired with the MATA distributed cloud, robotics and sensor data has two
routes — read it on the machine, or reach it through the cloud — with the same
memory-safe crates at both ends.
The family:
rusty_rtos_core (the shared vocabulary),
rusty_rtos_kernel (the scheduler),
rusty_rtos_port (the architecture seam),
rusty_rtos_heap (the allocators),
rusty_rtos_json (coreJSON),
rusty_rtos_sntp (coreSNTP),
rusty_rtos_mqtt (coreMQTT),
rusty_rtos_backoff (backoffAlgorithm),
rusty_rtos-capi (the C ABI) and
rusty_rtos_demo (the conformance corpus).
All ten are on crates.io. Also check out
the rest of github.com/remade-with-rust.
Mata Network builds sovereign, self-hostable privacy infrastructure — "stop sacrificing your privacy for convenience": wallet & identity, a password manager, a contact manager, and a browser extension that stops your information leaking as you browse.
Remade With Rust is our open-source home for the permissively-licensed building blocks that work depends on — including remade_ffmpeg_rs (the FFmpeg alternative) and FFAI (the AI media toolkit).
MIT OR Apache-2.0, at your option. FreeRTOS is MIT-licensed by Amazon.com, Inc. or its affiliates; this crate remakes its API and behaviour from the published sources and links no FreeRTOS code.
Tier critical-path · Audited 2026-10-01 (deep) · v1.0.0 gates 14/16 · Full checklist
██████████████████░░ 91% · 30 Completed · 0 Scheduled · 3 Incomplete · 22 N/A
| Phase | ✅ Completed | 🗓 Scheduled | ⬜ Incomplete | · N/A |
|---|---|---|---|---|
| 0 — Threat modeling | 2 | 0 | 0 | 0 |
| 1 — Toolchain | 3 | 0 | 0 | 1 |
| 2 — Supply chain | 7 | 0 | 1 | 0 |
| 3 — Code level | 7 | 0 | 0 | 0 |
| 4 — Static analysis | 1 | 0 | 0 | 0 |
| 5 — Dynamic analysis | 3 | 0 | 0 | 0 |
| 6 — Fuzzing and properties | 3 | 0 | 1 | 0 |
| 7 — Formal verification | 0 | 0 | 0 | 1 |
| 8 — Build and binary | 0 | 0 | 0 | 2 |
| 9 — Runtime privilege | 0 | 0 | 0 | 1 |
| 10 — Cryptography | 0 | 0 | 0 | 3 |
| 11 — CI/CD, release, and operations | 4 | 0 | 1 | 0 |
| 12 — Compliance controls | 0 | 0 | 0 | 14 |
| Total | 30 | 0 | 3 | 22 |
Architect — Tim Almond — accountable for this unit's security design; rendered