[AI Readability Summary] PREEMPT_RT improves real-time behavior by moving most interrupt handling into schedulable kernel threads. This reduces unconditional preemption from hard IRQs, shortens jitter for critical RT tasks, and improves system predictability. Keywords: PREEMPT_RT, threaded interrupts, SCHED_FIFO.
Technical Specifications Snapshot
| Parameter | Description |
|---|---|
| Technical Topic | Linux PREEMPT_RT Threaded Interrupts |
| Language | C, Linux Kernel Mechanisms |
| Scheduling Policy | SCHED_FIFO |
| Default IRQ Thread Priority | 50 |
| Key Flags | IRQF_NO_THREAD, IRQF_TIMER, IRQF_PER_CPU |
| Execution Context | Hard IRQ Context / Kernel Thread Context |
| License | CC BY-NC-SA 4.0 (as declared in the original source) |
| Star Count | Not provided by the original page |
| Core Dependencies | Linux Kernel, PREEMPT_RT Patch, IRQ Subsystem, Scheduler |
PREEMPT_RT Changes the Contention Model of Real-Time Systems Through Threaded Interrupts
In the traditional Linux mainline kernel, when a hardware interrupt arrives, it immediately interrupts the current execution flow. At that point, hardware interrupts are disabled locally, while preemption and soft interrupt processing are restricted. The entire path runs in interrupt context and is not directly governed by the normal scheduler.
This means that regardless of whether the CPU is running a user-space process or a high-priority kernel thread, it must yield the CPU as soon as an interrupt arrives. That design makes sense for general-purpose throughput-oriented systems, but in real-time systems it amplifies latency jitter and disrupts the execution window of RT tasks.
AI Visual Insight: This diagram shows that in the traditional kernel, hard IRQs, soft IRQs, and some tasklets execute outside the scheduler’s control. When an interrupt arrives, the CPU switches directly into interrupt context. Neither normal threads nor RT tasks can avoid this kind of preemption through scheduling priority, so system responsiveness depends more on interrupt density than on task priority.
Traditional hard interrupts reduce RT task determinism
The core problem is not that interrupts are always slow. The problem is that they are non-negotiable. Many device interrupts do not contain work that is absolutely urgent, yet they still execute with the highest interruption authority. As a result, even a high-priority RT thread cannot reliably maintain periodic execution.
/* In the traditional model, an interrupt directly preempts the current task */
void hard_irq_arrive(void)
{
disable_local_irq(); // Disable local hard interrupts
enter_interrupt_context(); // Enter interrupt context
handle_device_irq(); // Execute device handling logic immediately
exit_interrupt_context(); // Exit interrupt context
enable_local_irq(); // Re-enable interrupts
}
This code highlights the defining property of traditional hard IRQs: they execute immediately and cannot be deferred by normal scheduling policy.
PREEMPT_RT Converts Most Interrupts Into Schedulable Threads
The central change in PREEMPT_RT is that threaded interrupts are enabled by default. Unless an interrupt explicitly or implicitly carries IRQF_NO_THREAD semantics, most interrupt handlers no longer remain in hard interrupt context for extended processing. Instead, a kernel thread handles the bulk of the work.
As a result, interrupt handling is no longer inherently above all tasks. It can still run at high priority, but whether it runs immediately and whether a higher-priority RT task can suppress it are now determined by scheduling policy.
AI Visual Insight: This diagram shows the restructured interrupt path in PREEMPT_RT. Less critical hard IRQ work, soft IRQs, and tasklets are moved into thread context and arbitrated uniformly by the scheduler. The key change is that an RT task can keep the CPU if it has a higher priority, while IRQ threads wait in line like other real-time threads.
The fundamental benefit of threaded interrupts is that interrupts become manageable
Under the threaded model, much of the work that previously interrupted the CPU unconditionally is deferred into a kernel thread. This does not weaken interrupt handling. Instead, it splits urgency into two parts: the truly time-critical portion remains in a very short hard IRQ top half, while the rest runs in the threaded handler.
irqreturn_t irq_top_half(int irq, void *dev)
{
ack_irq(irq); // Acknowledge the interrupt quickly to minimize hard IRQ time
wake_irq_thread(irq); // Wake the IRQ thread to handle the remaining work
return IRQ_HANDLED; // End the hard IRQ phase as soon as possible
}
This code reflects PREEMPT_RT best practice: keep the hard IRQ path minimal and move complex logic into the threaded phase.
Not Every Interrupt Is Threaded
PREEMPT_RT does not force every IRQ to become a thread. Interrupts marked with IRQF_NO_THREAD still run as traditional hard IRQs, because they often carry architecture-level, timer-level, or per-CPU critical responsibilities and cannot tolerate the semantic changes introduced by thread scheduling.
A typical exception is inter-processor interrupts (IPIs). In addition, interrupts of type IRQF_TIMER and IRQF_PER_CPU usually imply IRQF_NO_THREAD semantics, so they are not threaded either. These interrupts retain stronger immediacy and low-level control.
IRQ threads use a real-time scheduling policy by default
The kernel code discussed in the article shows that IRQ threads are configured with SCHED_FIFO and a default priority of 50. In Linux, the RT priority range is typically 0 to 99, where higher values indicate higher user-visible priority, while the kernel’s internal prio representation uses a reverse mapping.
#define MAX_RT_PRIO 100
void sched_set_fifo(struct task_struct *p)
{
struct sched_param sp = {
.sched_priority = MAX_RT_PRIO / 2, // Default real-time priority: 50
};
sched_setscheduler_nocheck(p, SCHED_FIFO, &sp); // Configure as a FIFO real-time thread
}
static int irq_thread(void *data)
{
sched_set_fifo(current); // Switch the current IRQ thread to the real-time scheduling class
return handle_irq_event(data); // Run the main interrupt logic in thread context
}
This code shows that threaded IRQs are not downgraded into ordinary processes. They are integrated into the real-time scheduling framework to balance responsiveness with preemptibility.
Developers need to redesign interrupt responsibility boundaries
If you are working on driver development or real-time system tuning, the key is not simply to remember that PREEMPT_RT threads interrupts. The real task is to understand which logic must remain in the top half and which work should move into thread context. The former emphasizes the shortest possible path. The latter emphasizes schedulability and preemptibility.
When an RT task has a higher priority than the IRQ thread, the RT task can take the CPU first. This is exactly why PREEMPT_RT improves real-time behavior: interrupts no longer have unconditional execution authority, and the system starts allocating CPU time according to business priority rather than event suddenness.
FAQ
1. Why does PREEMPT_RT reduce RT task jitter?
Because a large portion of interrupt processing moves into schedulable threads, RT tasks with higher priority can suppress less important IRQ threads. This reduces periodic drift caused by unconditional interruption.
2. Does threaded interrupt handling mean every interrupt can be deferred?
No. Interrupts marked with IRQF_NO_THREAD, as well as critical interrupts such as IRQF_TIMER and IRQF_PER_CPU, retain hard IRQ semantics to preserve low-level timing guarantees and architectural control.
3. Is the default IRQ thread priority of 50 always sufficient?
Not necessarily. A priority of 50 is only the default. In a real system, you should tune priorities based on device importance, RT task priority, and latency targets. Otherwise, IRQ threads may still suppress critical workloads, or the system may under-serve interrupt responsiveness.
Core Summary: This article reconstructs the core mechanism behind threaded interrupt handlers in PREEMPT_RT, explaining the execution differences between traditional hard IRQs and threaded interrupts, the exception rules around IRQF_NO_THREAD, the default SCHED_FIFO priority, and how all of this improves RT task latency and jitter.