The Big Picture: The Doorbell and the Follow-Up
In Chapter 4 (Section 3) you learned that a device taps the CPU on the shoulder with an interrupt. The hardware side was covered there: IRQ numbers, the APIC, MSI and the IDT table. This section covers the software side: what the driver does when the tap arrives. (Chapter 2 also explained how the CPU saves its place and jumps to a handler.)
Windows splits the work into two steps:
- ISR (Interrupt Service Routine): the urgent part, done at once, in a very short time.
- DPC (Deferred Procedure Call): the follow-up, done a moment later, with a little more room.
Analogy: a doorbell. You run to the door (ISR), see it is the delivery driver and say "wait a moment" (quick acknowledgement). Then, a minute later, you sign for the parcel and unpack it (DPC).
Device ──interrupt──► CPU ──► looks up IDT ──► driver's ISR (very short)
│ "I'll finish later"
▼
queues a DPC
│
CPU finishes the ISR, returns to what it was doing │
▼
DPC runs shortly after (a bit longer, but still brief)
│
▼
complete the IRP (Section 9)
A Quick Look at IRQL (Why the Order Matters)
What it is: Windows uses IRQL (Interrupt Request Level): a number the CPU core is "at." The rule: only something with a higher level can interrupt something with a lower level. It is like a priority ladder.
| IRQL | Name | What runs here |
|---|---|---|
| 0 | PASSIVE_LEVEL | Normal programs and most driver code. Can wait, can use paged memory |
| 1 | APC_LEVEL | Special "asynchronous" kernel calls |
| 2 | DISPATCH_LEVEL | The scheduler and DPCs. Cannot wait; cannot touch pageable memory |
| 3 and up | DIRQL (device IRQLs) | ISRs. Each device gets its own level; hardware interrupts at higher levels block lower ones |
Why does this matter? At DISPATCH_LEVEL and above, the system cannot handle a page fault (a request to bring swapped-out memory back from disk, Chapter 3). If a driver touches memory that has been paged out at this level, Windows has no way to fetch it, so it stops with a blue screen such as IRQL_NOT_LESS_OR_EQUAL or DRIVER_IRQL_NOT_LESS_OR_EQUAL (Section 14). It is one of the most famous driver bugs.
10.1 Interrupt Service Routine (ISR)
What it is: The ISR is the function inside a driver that the CPU runs first when the device's interrupt arrives. The driver registers it when the device starts (Section 6.5): "when interrupt number N fires, call this function." For MSI devices (Chapter 4), a driver can register several.
Rules for an ISR:
| Rule | Why |
|---|---|
| Be very short (microseconds) | At DIRQL, other things (including lower-priority interrupts) are held back |
| Don't wait or block | There's nothing to wake it |
| Only touch non-pageable memory | A page fault here would crash the PC |
| No long loops, no slow calls | The whole core is stuck until you finish |
What an ISR typically does:
- Asks the device: "was it you?" (Some interrupt lines are shared. If the device did not call, return "not mine" so Windows asks the next driver.)
- Reads the status register to learn why the device called.
- Turns off ("acknowledges") the interrupt so the device stops shouting.
- Saves any key facts (for example, a key code or the byte count).
- Queues a DPC to do the rest.
- Returns.
10.2 Deferred Procedure Call (DPC)
What it is: A DPC is a function that the ISR schedules to run soon after, at DISPATCH_LEVEL. By then the CPU has left the high interrupt level, so other devices can be served again. There is room for more work.
What a DPC does:
| Task | Example |
|---|---|
| Process the data | Hand the received network packet to the network stack |
| Complete the IRP | Finish the disk read and send the IRP back up (Section 9.4) |
| Start the next job | Take the next request off the queue and give it to the device |
| Update statistics | Count, log, wake a waiting thread |
DPCs run on the core where they were queued, and Windows runs them before returning to normal thread work. They are still supposed to be short (well under a millisecond is a typical goal). A DPC that runs too long makes the PC feel slow: mouse stutter, audio crackles and dropped network packets.
Longer jobs go further down. If the work is long, the DPC can hand it to a worker thread running at PASSIVE_LEVEL (a normal thread inside the kernel), where waiting is allowed.
10.3 ISR vs DPC Division of Labor
What it is: The art of a good driver is to put each piece of work on the right rung of the ladder.
| ISR | DPC | Worker thread (if needed) | |
|---|---|---|---|
| IRQL | DIRQL (high) | DISPATCH_LEVEL (2) | PASSIVE_LEVEL (0) |
| Time | Microseconds | Short (tens to hundreds of microseconds) | Can be longer |
| Can wait? | No | No | Yes |
| Typical job | Acknowledge, save status | Process data, complete IRP | Heavy work, file access, waiting on other things |
| Can other interrupts of the same level run? | Blocked on this core | Yes, hardware interrupts can break in | Yes |
time ───────────────────────────────────────────────────────────►
IRQL high │ ┌─┐ ISR
│ │ │
DISPATCH 2 │ │ └───────┐ DPC
│ │ │
PASSIVE 0 │───┘ └─────────────── normal thread resumes
▲
the interrupt arrives here
A full example: a network packet arrives
- The NIC (network card) writes the packet into RAM by DMA (Section 11) and raises an interrupt (via MSI-X).
- ISR: "Yes, that was my card." Turns off the interrupt. Queues a DPC. (Microseconds.)
- DPC: Takes the received packet(s) and passes them up to the network stack. Gives the card fresh buffers for the next packets.
- A normal thread (your browser) wakes and reads the data.
Modern network drivers can batch many packets in one DPC, and use MSI-X (Chapter 4) so each CPU core handles its own queue.
When this goes wrong:
| Problem | Symptom | Tool |
|---|---|---|
| Slow ISR/DPC | Audio crackles, mouse lag, video stutter | LatencyMon (a free third-party tool), Windows Performance Analyzer |
| Interrupt storm | High "System interrupts" and "DPC" time in Task Manager (Details tab) | Disable/update the offending device driver |
| ISR touches pageable memory | Blue screen IRQL_NOT_LESS_OR_EQUAL | WinDbg (Section 15) |
| Driver forgets to acknowledge | The device keeps interrupting, so the PC freezes | Driver update |
Hardware ↔ software map (to keep it tidy):
| Stage | Where it is explained |
|---|---|
| Device raises signal, APIC/MSI delivers it | Chapter 4, Section 3 |
| CPU saves state and jumps via the IDT | Chapter 2 and Chapter 4, Section 3.4 |
| ISR, then DPC in the driver | This section |
| DPC completes the IRP | Section 9.4 |
Summary
| Term | Plain meaning |
|---|---|
| ISR | Driver's urgent, super-short reaction to an interrupt |
| DPC | Follow-up job, queued by the ISR, run a moment later at a lower level |
| IRQL | The priority level the CPU core is on; higher levels block lower ones |
| PASSIVE / DISPATCH / DIRQL | Level 0 (normal) / level 2 (DPCs) / device levels (ISRs) |
| Why split? | Keep the high-priority time short, so other devices don't wait |
| Worker thread | Used when the job is long or must wait |
| Classic bug | Touching pageable memory at DISPATCH_LEVEL or higher → blue screen |