---
title: Interrupts
source: 'https://academia.sh/en/courses/how-computers-work/interrupts'
course: 'How Computers Work'
language: en
updated: '2026-08-17T18:08:13+00:00'
license: 'CC BY-SA 4.0'
---

# Interrupts

Notifying the processor of external events, saving context, interrupt types, and the foundation of preemptive multitasking.

The previous lessons treated the processor as a closed system: it fetches
instructions, decodes them, executes them, and moves to the next one. A computer,
however, interacts with the outside world. A key is pressed, a disk read completes, a
packet arrives from the network. When these events will occur cannot be known in
advance.

This lesson asks: how is a processor occupied with its own cycle notified that
something has happened in the outside world?

## Polling and Its Limit

The first solution that comes to mind is **polling**: the program asks the device's
status at regular intervals.

```
    loop:
        read device status
        if data not ready, go to loop
        process data
```

Polling has two costs. If the device stays unready for a long time, the processor
spins without producing any work; each query spends a memory access and a few
instructions. If, on the other hand, the query interval is widened, latency increases
instead: the time between the event occurring and it being noticed grows longer.

Polling is not bad under every condition. When events arrive very frequently and at
predictable intervals, polling can cost less than the fixed overhead of interrupt
handling. It cannot, however, serve as a general solution.

## The Interrupt Mechanism

An **interrupt** is a signal a device sends to the processor. When the processor
receives this signal, it completes the instruction it is executing and transfers flow
elsewhere on its own. The steps are:

1. The instruction currently executing completes.
2. **The context is saved:** the program counter and the necessary registers are
   written aside so that flow can later resume where it left off.
3. Using the interrupt number, the address of the relevant handler is read from the
   **interrupt vector table**.
4. This address is written to the program counter; the **interrupt handler** runs.
5. When the handler finishes, the context is restored, and the interrupted program
   continues without noticing it was interrupted.

From the interrupted program's point of view, nothing has happened: the registers are
the same, the program counter is where it is expected to be. Only the elapsed time
differs.

This mechanism's cost is not zero. Saving and restoring context does a few
instructions' worth of work and can disturb cache contents. Keeping interrupt handlers
short is therefore a design rule: the handler does only what is urgent, and leaves
long-running work to a task that runs afterward.

## Types of Interrupts

The events that interrupt flow are not all of one kind.

A **hardware interrupt** is asynchronous: it comes from an external device and has no
relation to which instruction the program is on. The keyboard, disk controller, network
interface, and timer belong to this class.

An **exception**, or **trap**, is synchronous: it is produced by the instruction
currently executing. Division by zero, an invalid instruction, an unauthorized memory
access, and a page fault belong to this class. Rerunning the same program with the same
input produces the exception at the same point.

The distinction is practical: an asynchronous interrupt can be deferred, a synchronous
exception cannot — the instruction cannot complete until the exception is handled.

A **software interrupt** is a trap the program produces at its own request, and it
underlies operating system calls. A user program cannot directly access hardware for
work that requires privilege (opening a file, creating a network socket); instead, it
produces a trap, privileged code runs, and returns the result. The boundary between
user mode and kernel mode is drawn at this point.

## The Timer Interrupt and Preemption

The most important interrupt does not come from the outside world but from the
processor's own timer. This timer produces an interrupt at regular intervals.

The consequence is decisive: no program can hold the processor indefinitely. When the
timer interrupt arrives, control passes to the operating system; the operating system
saves the running program's context, loads another program's context, and flow
continues from there. This scheme is called **preemptive multitasking**.

Without preemption, multitasking would depend on programs' voluntary cooperation; a
single program caught in an infinite loop would lock up the entire system. Process and
thread scheduling, in the operating system concepts course, is built on this
foundation.

## Direct Memory Access

Interrupts make it cheap for a device to say "I'm ready"; but if moving the data is
still the processor's job, the gain stays limited. Taking a block read from disk byte
by byte into registers and writing it to memory ties the processor down to the moving
work.

**Direct memory access** hands the transfer off to a separate controller. The processor
only defines the request: source, destination address, and length. The controller
carries out the transfer itself; the processor executes other instructions in the
meantime. When the transfer finishes, the controller produces an interrupt.

This scheme reveals the real gain of interrupts: the processor neither waits for the
data nor moves it; it only starts the transfer and is notified when it finishes. The
same principle continues in higher layers — asynchronous input/output interfaces
repeat the "issue the request, collect the result when notified" pattern at the
software level.

The cost is that shared memory now has two writers: while the controller modifies
memory, the processor's cache may hold a stale copy of that region. Maintaining
consistency is the responsibility of hardware and the driver.

## Masking and Priority

A new interrupt can arrive while an interrupt handler is running. Hardware manages this
with two tools.

**Masking:** Specific interrupts can be temporarily suppressed. Short pieces of code
that would produce an inconsistent state if interrupted — critical sections — run with
interrupts disabled. Keeping this period long directly increases the system's delay in
responding to external events.

**Priority:** Interrupts are graded by importance; a high-priority interrupt can
interrupt a low-priority handler. Nested interrupts mean contexts accumulate on the
stack.

There is also a class of interrupts that cannot be suppressed at all: non-maskable
interrupts, reserved for events such as hardware failure, for which deferral would be
meaningless.

## Reflection in the Program

An interrupt is a hardware-level concept, but its traces are visible in software. An
operating system signal is the process-level equivalent of an interrupt: wherever flow
happens to be, the registered handler runs and flow then continues from where it left
off.

```python
import signal, time

interrupt_count = 0

def timer_handler(signal_num, frame):
    """Runs wherever flow happens to be, then returns."""
    global interrupt_count
    interrupt_count += 1

signal.signal(signal.SIGALRM, timer_handler)
signal.setitimer(signal.ITIMER_REAL, 0.05, 0.05)    # a signal every 50 ms

start = time.perf_counter()
counter = 0
while time.perf_counter() - start < 0.5:            # half a second of a busy loop
    counter += 1

signal.setitimer(signal.ITIMER_REAL, 0)             # stop the timer
print(interrupt_count)                              # around 9
```

The loop contains no line waiting for the signal; yet the handler has run roughly nine
times. This is the distinguishing trait of the interrupt concept: control is
transferred without the flow itself requesting it.

The limit of this analogy should also be noted. Operating system signals are not
hardware interrupts; the runtime processes them at safe points. Still, the idea of flow
being interrupted from outside is the same.

The same idea continues in higher layers: asynchronous input/output, event loops, and
callback-based interfaces are the software-level equivalents of the "notify me when
ready" principle.

## Summary

- Polling queries device status at regular intervals; it either spends processor time
  or increases latency.
- An interrupt is a signal a device sends to the processor; the processor saves the
  context, runs the handler, and resumes flow from where it left off.
- Hardware interrupts are asynchronous, exceptions are synchronous; software interrupts
  underlie operating system calls.
- The timer interrupt ensures no program can hold the processor indefinitely, and
  makes preemptive multitasking possible.
- Interrupts are masked in critical sections; the longer masking lasts, the more the
  system's response delay grows.
- Interrupt handlers are kept short; saving and restoring context is costly.

## Next Step

This topic's remaining question is the operation itself: what happens in hardware when
an add instruction runs? The next lesson shows how arithmetic is built from logic
gates, and why two's complement representation needs no separate circuit for
subtraction.
