Skip to main content

Command Palette

Search for a command to run...

Linux Interrupts

Published
•3 min read•View as Markdown

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)

  1. A hardware device raises an interrupt (line or MSI/MSI-X).

  2. The interrupt controller maps it to a CPU interrupt vector.

  3. 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)

  1. The vector is mapped to a Linux IRQ number

  2. The kernel looks up: struct irq_desc *desc;

  3. The kernel iterates through: struct irq_action

  4. Each registered handler is invoked: handler(irq, dev_id);

  5. 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

More from this blog

Systems-N-Sentience

12 posts

Systems N Sentience is a technology blog that explores the foundations and evolution of modern computing systems.