Linux Interrupts
Interrupts are hardware signals generated by I/O devices to request attention from the CPU.
Devices generate interrupts either through physical interrupt lines or via message-signaled interrupts (MSI/MSI-X). These interrupts are routed through an Interrupt Controller (such as PIC, APIC, or GIC), which forwards the interrupt to the processor.
In Linux, interrupt management is handled using an internal data structure called the IRQ descriptor table, implemented as: struct irq_desc irq_desc[NR_IRQS];
Each irq_desc entry corresponds to a Linux IRQ number and contains state and metadata for that interrupt, including status flags, locking information, nesting depth, and a list of registered handlers.
Hardware-specific interrupt control operations are abstracted using struct irq_chip, which provides callbacks such as irq_enable(), irq_disable(), irq_ack(), irq_mask(), and irq_unmask(). This allows Linux to remain architecture-independent.
Device drivers register their interrupt handlers using high-level kernel APIs such as request_irq() or devm_request_irq(). Internally, the kernel creates a struct irq_action for each registered handler. This structure contains the driver’s interrupt handler function, flags, device identifier (dev_id), name, and a pointer to the next handler to support shared interrupts.
Drivers do not directly manipulate irq_desc or irq_action; these are managed entirely by the kernel’s IRQ subsystem.
Interrupt Entry (x86 example)
A hardware device raises an interrupt (line or MSI/MSI-X).
The interrupt controller maps it to a CPU interrupt vector.
The CPU:
Switches to a privileged stack (IRQ/IST stack if configured)
Jumps to the IDT entry stub for that vector.
IDT entry stub - > common_interrupt() → handle_irq_desc() - > irq_desc - > irq_action list (registered handlers)
The vector is mapped to a Linux IRQ number
The kernel looks up:
struct irq_desc *desc;The kernel iterates through:
struct irq_actionEach registered handler is invoked:
handler(irq, dev_id);Bottom Halves: Deferred work is scheduled via:
SoftIRQs
Tasklets
Workqueues
Threaded IRQs
Factors Contributing to Interrupt Latency in Linux
Interrupt latency is the time between a hardware device asserting an interrupt and the system beginning execution of the corresponding interrupt handler. In Linux, this latency is influenced by several hardware and software factors.
1) Hardware Interrupt Delivery Latency
Time for:
Device to raise interrupt
Interrupt controller (PIC/APIC/GIC/MSI) to deliver it
CPU to acknowledge and vector the interrupt
2) Kernel Interrupt Entry Overhead
Time spent in:
Architecture-specific entry stubs
Interrupt vector handling
IRQ number resolution
Lookup of
irq_desc
Occurs before the device ISR is invoked
3) Interrupt Masking and Preemption Effects
Latency increases when:
Interrupts are temporarily disabled (
local_irq_disable)IRQ lines are masked
Higher-priority interrupts are executing
Critical sections and long non-preemptible regions increase latency
4) ISR Execution Time (Hard IRQ Duration)
Long-running ISRs increase latency for:
Other interrupts
SoftIRQs
Best practice:
Keep ISRs short
Defer work to bottom halves
5) Deferred Work (SoftIRQ / Tasklet / Threaded IRQ)
SoftIRQs execute:
On interrupt exit
Or in
ksoftirqd
Heavy softirq processing can:
Delay user-space execution
Increase effective end-to-end interrupt latency
6) Scheduler and System Load
High CPU utilization
IRQ affinity and CPU isolation
NUMA effects