03 — Real-Time Operating System
Status · reconciled 2026-08-30. The product audio contract is
cpal -> ALSA, with one Auvra process owning the device. JACK is not required by the MVP.
The OS turns the N100 into a deterministic audio appliance. Three concerns: a real-time kernel, the audio stack, and RT tuning for the 4-core N100. (Silent boot is covered in 07.)
1. Real-time kernel: PREEMPT_RT is mainline
Section titled “1. Real-time kernel: PREEMPT_RT is mainline”Since Linux 6.12 (Nov 2024, an LTS kernel) the full PREEMPT_RT preemption model is merged into the mainline kernel — no out-of-tree patch needed.12 x86_64 is fully supported, so the N100 is covered. A fully-preemptible RT kernel is selected with:
# Kernel config (General Setup → Preemption Model → "Fully Preemptible Kernel (Real-Time)")CONFIG_PREEMPT_RT=yCONFIG_HIGH_RES_TIMERS=yCONFIG_NO_HZ_FULL=y # tickless isolated CPUsCONFIG_RCU_NOCB_CPU=y # offload RCU callbacks from RT coresDistro availability in 2026:34
| Distro | RT kernel | How |
|---|---|---|
| Debian 13 “Trixie” | mainline 6.12-rt | apt install linux-image-rt-amd64 — easiest free path |
| Ubuntu 24.04 LTS | 6.8 + RT | via Ubuntu Pro (free ≤ 5 machines); free for all from 26.04 |
| Fedora / Fedora Jam | 6.12+ kernel-rt |
vanilla repos / Jam spin |
| Arch | linux-rt-lts |
AUR |
2. Build approach: prototype vs product
Section titled “2. Build approach: prototype vs product”flowchart LR
subgraph PROTO["Prototype (develop & tune)"]
D["Debian 13 Trixie<br/>+ linux-image-rt-amd64<br/>+ development tools"]
end
subgraph PROD["Shippable product"]
Y["Yocto image<br/>meta-realtime + read-only rootfs<br/>+ RAUC A/B OTA"]
end
D -->|"port app, freeze deps"| Y
- Prototype → Debian 13 Trixie with the packaged RT kernel. Full debugging
tools,
aptconvenience, and the distribution ALSA stack make it fast to stand up.3 - Product → Yocto minimal image: SquashFS read-only rootfs + tmpfs overlay, writable data partition for patches/settings, RAUC A/B updates. Result: < 200 MB image, 3–5 s boot, reproducible, power-loss-safe, nothing of the OS visible to the user.56 Buildroot is a lighter alternative if OTA isn’t required.
Rationale: a desktop audio distro is perfect for development but wrong for an appliance — mutable rootfs (corruption risk on power-cut), slow boot, and exposed internals. The immutable Yocto image fixes all three.
3. Audio stack
Section titled “3. Audio stack”flowchart TB
APP["Auvra app<br/>cpal callback + engine"]
ALSA["ALSA<br/>(bench: snd-usb-audio<br/>integrated: auvra-pcie)"]
HW["Audio interface"]
APP -->|"exclusive PCM stream<br/>64–128 frames"| ALSA --> HW
For a dedicated single-app synth, Auvra uses bare ALSA through cpal:
- ALSA is the stable Linux device ABI for both class-compliant USB bench hardware and the selected FPGA integration target. The Auvra process owns one PCM stream exclusively; no routing server sits in the audio path.
- cpal supplies the Rust callback abstraction used by the same engine on CoreAudio during Mac development. Its Linux backend opens ALSA directly.
- JACK/PipeWire remain optional future platform adapters for desktop routing, recording workflows or development. They are not product dependencies.
The buffer contribution is deterministic; actual round-trip latency also includes converter and driver safety buffers and must therefore be measured on each target interface:
| ALSA period @ 48 kHz | One period | Two-period software budget |
|---|---|---|
| 64 frames | 1.33 ms | 2.67 ms |
| 128 frames | 2.67 ms | 5.33 ms |
| 256 frames | 5.33 ms | 10.67 ms |
4. RT tuning checklist (Intel N100, 4 cores)
Section titled “4. RT tuning checklist (Intel N100, 4 cores)”4-core caveat: isolate 2–3 cores for audio and leave core 0 for the kernel, IRQs, housekeeping and UI. Do not isolate all four — RCU/watchdog/kernel threads will starve.7
Kernel command line
Section titled “Kernel command line”isolcpus=1,2,3 nohz_full=1,2,3 rcu_nocbs=1,2,3 \threadirqs irqaffinity=0 \intel_idle.max_cstate=1 processor.max_cstate=1 \intel_pstate=disable skew_tick=1 tsc=nowatchdog nosoftlockup rcu_nocb_poll| Flag | Effect |
|---|---|
isolcpus=1,2,3 |
Remove cores 1–3 from the scheduler; pin the synth with taskset/chrt. |
nohz_full=1,2,3 |
Stop the scheduling tick on isolated cores → no periodic timer jitter. |
rcu_nocbs=1,2,3 |
Offload RCU callbacks to core 0. |
threadirqs / irqaffinity=0 |
Threaded IRQs, all pinned to core 0 (off the audio cores). |
intel_idle.max_cstate=1 / processor.max_cstate=1 |
Cap C-states → avoid deep-sleep exit latency (100–300 µs). |
intel_pstate=disable |
Lets the performance cpufreq governor lock clocks. |
tsc=nowatchdog nosoftlockup skew_tick=1 |
Remove watchdog/lock-detector preemption bursts. |
Runtime
Section titled “Runtime”# performance governorecho performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor# allow unthrottled RT on isolated coresecho -1 > /proc/sys/kernel/sched_rt_runtime_usLimits — /etc/security/limits.conf
Section titled “Limits — /etc/security/limits.conf”@audio - rtprio 95@audio - memlock unlimited@audio - nice -19Add the synth user to the audio group; ensure pam_limits.so is active. The engine should mlockall() to avoid page-fault stalls.
IRQ priorities
Section titled “IRQ priorities”Use the rtirq script to raise the sound-card IRQ thread priority (e.g. snd at 85) after boot — complementary to threadirqs.
Verify, don’t assume
Section titled “Verify, don’t assume”# scheduling jitter under load (target Max < ~30 µs with isolation)taskset -c 1 cyclictest -m -p90 -i500 -D 30m -h400 -q# detect SMI/firmware-induced stalls the kernel can't seehwlatdetect --duration=60# config auditpip install rtcqs && rtcqsN100 field note: at least one report found that disabling BIOS C-states increased latency on N100 hardware — its firmware manages idle well, and the kernel
*.max_cstate=1flags suffice. Measure both ways withcyclictestbefore committing BIOS changes.7
SMIs (System Management Interrupts)
Section titled “SMIs (System Management Interrupts)”SMIs are invisible to the kernel and can add 50–300 µs. Reduce them in BIOS: disable unused VT-x/VT-d, USB legacy support, and aggressive power features; lock the CPU frequency. There is no kernel fix — detect with hwlatdetect.8
5. What “done” looks like
Section titled “5. What “done” looks like”cyclictestMax jitter < 30 µs under load (video/USB/network stress).- The
cpal -> ALSAstream is stable at 64–128 frames with no xruns over an hour of playing. hwlatdetectshows no SMI spikes > 50 µs.
Footnotes
Section titled “Footnotes”-
Phoronix, “Real-Time PREEMPT_RT Support Merged For Linux 6.12.” https://www.phoronix.com/news/Linux-6.12-Does-Real-Time ↩
-
Linux Foundation RT wiki, “PREEMPT_RT versions.” https://wiki.linuxfoundation.org/realtime/preempt_rt_versions ↩
-
Debian,
linux-image-rt-amd64(Trixie). https://packages.debian.org/trixie/linux-image-rt-amd64 ↩ ↩2 -
Canonical, “Real-time Ubuntu 24.04 LTS.” https://ubuntu.com/blog/real-time-24-04 ↩
-
Incredibuild, “Yocto vs Buildroot.” https://www.incredibuild.com/blog/yocto-or-buildroot-which-to-use-when-building-your-custom-embedded-systems ↩
-
meta-readonly-rootfs-overlay(SquashFS + OverlayFS for Yocto). https://github.com/marcusfolkesson/meta-readonly-rootfs-overlay ↩ -
LinuxCNC forum, “Intel N100” latency thread (isolcpus, C-state finding). https://forum.linuxcnc.org/18-computer/50817-intel-n100 ↩ ↩2
-
Linux Foundation, “SMI latency” debugging guide. https://wiki.linuxfoundation.org/realtime/documentation/howto/debugging/smi-latency/start ↩