← Previous Lecture | Next Lecture →
PREEMPT_RT Linux Kernel Tutorial: Build a Real-Time Kernel from Source (Updated 2026)
Free Linux Kernel Programming Course • Free Linux Device Drivers Course • Free Embedded Systems Course
Intermediate
14 min
6.12+ LTS
Linux Kernel Programming
If you are searching for a hands-on PREEMPT_RT Linux kernel tutorial, you are in the right place. This lesson is part of EmbeddedPathashala’s free Linux kernel programming course and free Linux device drivers course, and it walks you through what the real-time Linux kernel actually is, why it matters for embedded systems, and how to configure and build one yourself on a modern kernel.
What You Will Learn
- What the PREEMPT_RT patch set is and why it exists
- The big 2024 milestone: PREEMPT_RT becoming part of mainline Linux
- How to enable and build a real-time Linux kernel today, with no external patch needed
- How to verify that your system is really running in real-time mode
- Design rules for user-space and driver code that must behave deterministically
- Common mistakes beginners make when building their first RT kernel
Prerequisites
- Comfort with basic Linux commands and building software from source
- A Linux kernel source tree (mainline.org or your distribution’s source package)
- Familiarity with
make menuconfigfrom our earlier kernel-building lessons - A test machine or virtual machine you don’t mind rebooting a few times
Why a Standard Linux Kernel Is Not “Real Time”
Standard, general-purpose Linux is designed to maximize overall throughput — it tries to keep every CPU busy and every process fed, but it makes no promise about exactly when any single task will run. A background job doing disk I/O is free to hold a lock or occupy the CPU for a little while longer if that improves overall system efficiency. For a web server or a desktop, that trade-off is perfectly fine. For a robot arm, a motor controller, or an industrial protocol stack, an occasional multi-millisecond delay can be the difference between a working product and a safety incident.
This gap between “usually fast” and “guaranteed on time” is exactly what the real-time Linux effort set out to close.
What Is PREEMPT_RT?
PREEMPT_RT is a long-running engineering effort, started in the early 2000s, to make almost every part of the Linux kernel preemptible — meaning a high-priority task can interrupt lower-priority kernel work almost anywhere, not just at a handful of safe points. Instead of forking Linux into a separate real-time operating system, the project’s philosophy was always to feed its changes back into mainline Linux over time.
Three ideas sit at the heart of PREEMPT_RT:
- Threaded interrupt handlers — most interrupt processing runs inside a schedulable kernel thread instead of in a hard, non-preemptible context, so a high-priority user task can still cut in.
- Sleeping (RT) spinlocks — ordinary spinlocks are converted into a mutex-like primitive with priority inheritance, so a low-priority task holding a lock cannot silently block a high-priority one for long.
- High-resolution, priority-aware scheduling — nanosecond-resolution timers and a scheduler tuned for predictable wake-up latency instead of raw throughput.
The 2024 Milestone: PREEMPT_RT Is Now Part of Mainline
Here is the update that most older tutorials and books miss: for roughly two decades, PREEMPT_RT lived as an out-of-tree patch that you had to download separately and apply on top of a matching mainline kernel version. That changed in September 2024, when the final pieces of PREEMPT_RT were merged directly into Linux kernel version 6.12, which also became that year’s Long Term Support (LTS) release.
What this means for you in practice:
- On kernel 6.12 and newer, you no longer need to hunt for a separate
-rtpatch file that matches your exact kernel version. - A configuration option,
CONFIG_PREEMPT_RT, is available directly insidemake menuconfigunder the preemption model settings. - Driver and subsystem maintainers are now expected to keep real-time compatibility in mind by default, instead of an external patch trying to catch up after the fact.
- If you’re on an older kernel (5.x or early 6.x), the classic external
-rtpatch workflow described in older books is still the correct approach — the mainline option only applies from 6.12 onward.
| Milestone | What Happened |
|---|---|
| Early 2000s | PREEMPT_RT project begins as an out-of-tree patch set |
| 2007–2014 | Threaded IRQs, high-resolution timers, lockdep, and deadline scheduling merge piece by piece into mainline |
| September 2024 | Final RT pieces merged; PREEMPT_RT becomes a standard mainline config option in Linux 6.12 |
| Today | Real-time support ships in-tree for x86_64, ARM64, and RISC-V, with more architectures being added |
Step-by-Step: Building a Real-Time Kernel on 6.12+
The overall workflow follows the same kernel-building steps you learned earlier in this course, with one extra menu choice.
Step 1: Get a Recent Kernel Source Tree
git clone --depth 1 --branch v6.12 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
Step 2: Start From a Known-Good Config
cp /boot/config-$(uname -r) .config
make olddefconfig
Step 3: Select the Fully Preemptible Model
make menuconfig
# General Setup ---> Preemption Model ---> (X) Fully Preemptible Kernel (Real-Time)
If the fully preemptible choice is not visible, enable the expert-level option that exposes advanced preemption settings first, then return to the Preemption Model menu.
Step 4: Set a Recognizable Version Suffix
General Setup ---> Local version - append to kernel release ---> -rt-epk
Giving your build a custom suffix like -rt-epk makes it easy to pick out later in the GRUB boot menu and in uname -r.
Step 5: Build and Install
make -j$(nproc)
sudo make modules_install
sudo make install
Step 6: Reboot and Select the New Kernel
Hold Shift during boot (BIOS systems) to force the GRUB menu to appear, then choose the newly built real-time kernel entry.
Step 7: Verify Real-Time Mode Is Active
uname -r
# example: 6.12.16-rt-epk
cat /sys/kernel/realtime
# expected output: 1
The /sys/kernel/realtime file is the most reliable check — it only appears and only reports 1 when CONFIG_PREEMPT_RT is actually compiled in and active, regardless of what your kernel version string looks like.
A Real-Time Kernel Alone Is Not Enough
This is the point most beginners miss. Booting an RT kernel does not automatically make your application deterministic. Real-time behavior has to be designed into your user-space code and drivers as well:
- Lock down memory — use
mlockall()so your process’s pages cannot be paged out, avoiding unpredictable page-fault latency at the worst possible moment. - Pre-fault your stack and heap — touch memory you plan to use before entering your time-critical loop, so the first real page fault doesn’t happen mid-deadline.
- Set the right scheduling policy and priority — use
SCHED_FIFOorSCHED_DEADLINEwithsched_setscheduler()instead of the default time-sharing policy. - Isolate CPUs — use the
isolcpusandnohz_fullboot parameters together with CPU affinity so your real-time thread doesn’t compete with the rest of the system on the same core. - Avoid blocking system calls in the hot path — logging, dynamic memory allocation, and unbounded I/O all introduce latency you cannot bound in advance.
Common Mistakes and Troubleshooting
| Symptom | Likely Cause & Fix |
|---|---|
/sys/kernel/realtime is missing | Your running kernel isn’t actually the RT build — check GRUB default entry and uname -r. |
| Fully Preemptible option missing in menuconfig | Enable “Configure standard kernel features (expert users)” under General Setup first. |
| High latency despite RT kernel | Firmware-level System Management Interrupts (SMI), power-saving C-states, or an unbounded user-space loop are usually the culprit — not the kernel config. |
| Build fails on GCC version mismatch | Match your GCC version to what the chosen kernel release expects; check Documentation/process/changes.rst in the source tree. |
Best Practices
- Always benchmark before and after enabling PREEMPT_RT — some workloads that are throughput-bound can actually get slower under RT scheduling.
- Keep a non-RT kernel entry in GRUB as a fallback while you’re still testing.
- Version-control your
.configfile alongside your project so builds are reproducible. - Document the exact kernel command-line parameters (
isolcpus,nohz_full,irqaffinity) you used — they matter as much as the kernel config itself.
Performance and Security Considerations
Performance: PREEMPT_RT trades some raw throughput for lower, more predictable worst-case latency. Systems that need maximum bandwidth (large file servers, batch compute) rarely benefit from it; systems that need bounded response time (motor control, data acquisition, industrial protocol stacks) usually do.
Security: real-time scheduling classes can starve normal processes if misused — a runaway SCHED_FIFO task can lock out everything else on a core. Linux mitigates this with sched_rt_runtime_us, which reserves a slice of CPU time for non-real-time tasks by default; don’t disable it without a good reason on a production system.
Key Takeaways
- PREEMPT_RT converts most of the Linux kernel into preemptible, priority-aware code so high-priority tasks aren’t blocked for long.
- Since kernel 6.12, real-time support is built into mainline Linux — no external patch is required for new projects.
- Enabling the config option is only half the job; user-space and driver code must also be written for determinism.
- A real-time Linux kernel provides soft real-time guarantees, not the hard guarantees of a microcontroller RTOS.
Conclusion
The merge of PREEMPT_RT into mainline Linux is one of the most significant embedded Linux milestones of the last few years, and it directly affects how you should approach real-time projects today. Instead of chasing a matching out-of-tree patch for your exact kernel version, you can now select real-time preemption straight from make menuconfig on kernel 6.12 and later. In the next lesson in this free Linux kernel programming course, we’ll go deeper into exactly how the internal mechanisms — spinlocks, threaded IRQs, and the scheduler — differ between the standard and real-time preemption models, and in the lesson after that, we’ll measure real latency numbers on your own hardware.
Frequently Asked Questions About PREEMPT_RT
Only if you’re building a kernel older than 6.12. From 6.12 onward, PREEMPT_RT is a standard mainline configuration option.
No. It provides soft real-time behavior with very low, statistically bounded latency. Applications needing hard guarantees (flight control, anti-lock brakes) typically use a dedicated RTOS or a co-processor instead.
x86_64, ARM64, and RISC-V were supported at merge time, with further architecture support continuing to expand.
Practically speaking, plan for at least 32 MB of RAM for the kernel and core services; real applications will need more depending on their workload.
It can reduce peak throughput slightly because of the added preemption checks and locking overhead, but for latency-sensitive workloads the predictability gain is usually worth the trade-off.
Read /sys/kernel/realtime. If it exists and prints 1, real-time preemption is active on the running kernel.
Next up: Mainline vs PREEMPT_RT internals, then hands-on latency measurement with cyclictest and rtla.
Browse the Full Course Join EmbeddedPathashala
2 Comments