Levels/The kernel: scheduling, interrupts & synchronization/Kernel mechanisms (IRQL, DPC, interrupts)

Level 8 · Chapter 1

Kernel mechanisms (IRQL, DPC, interrupts)

Why kernel mode is not one uniform environment — and why calling the wrong API from the wrong context bugchecks the machine.

System architecture noted that kernel mode itself is internally layered, not a single undifferentiated privileged blob. This chapter is where that claim gets concrete: the rules that split kernel-mode execution into genuinely different contexts, with genuinely different capabilities — rules whose violation is one of the most common causes of a Windows bugcheck.

IRQL: a ceiling on what's legal right now

IRQL (Interrupt Request Level) is best understood as a priority ceiling that determines which kernel operations are currently legal — not a scheduling priority in the sense Scheduling covers, but a hard constraint on what kind of code can run and what it's allowed to do. Ordinary kernel code runs at PASSIVE_LEVEL, where essentially everything is permitted, including operations that might need to wait or sleep. Higher IRQLs progressively restrict what's legal — at DISPATCH_LEVEL, for instance, a thread cannot wait on most kinds of objects or touch pageable memory at all, because doing so could require a page fault, and a page fault can't safely be serviced while running at that level.

Interrupts, ISRs, and why they have to be fast

Hardware interrupts — a network packet arriving, a disk operation completing — cause the CPU to immediately transfer control to an ISR (Interrupt Service Routine), running at a high IRQL corresponding to that specific interrupt. ISRs are deliberately kept extremely short: because they run at high IRQL, with much of the ordinary kernel API surface unavailable to them, and because a long-running ISR would delay every lower-priority interrupt and piece of kernel work behind it, an ISR's job is almost always just "acknowledge the hardware, note that work needs doing, and get out" — not to perform the actual substantial work the interrupt represents.

DPCs: deferring the real work to a safer context

That "actual substantial work" gets handed off via a DPC (Deferred Procedure Call) — a mechanism for queuing work to run shortly afterward, at DISPATCH_LEVEL rather than at the ISR's even-higher interrupt level. DISPATCH_LEVEL is still restrictive (still no waiting on most objects, still no pageable memory access) but meaningfully less so than running directly inside the ISR itself. This two-step handoff — do the absolute minimum in the ISR, defer everything else to a DPC — is the standard pattern nearly every Windows driver follows for handling hardware interrupts, and it's directly why a well-behaved interrupt handler doesn't visibly stall the rest of the system even under heavy device activity.

A worked example: why file I/O from a DPC bugchecks the machine

File I/O fundamentally requires PASSIVE_LEVEL — it might need to wait on a lock, fault in a page, or block on disk access, none of which are legal operations at DISPATCH_LEVEL. A driver that calls file I/O from inside a DPC is violating this IRQL contract directly, and Windows detects this and bugchecks the machine — commonly with DRIVER_IRQL_NOT_LESS_OR_EQUAL — rather than allowing the violation to proceed into genuinely undefined, potentially silently-corrupting behavior. This is a deliberate design choice: a hard, loud, immediate failure (a bugcheck) is considered preferable to a subtle, delayed one (memory corruption that might not manifest visibly until much later, in a completely unrelated part of the system).

A common mistake

Treating "kernel mode" as one uniform environment where the same rules always apply is exactly the misconception this chapter exists to correct. A thread's IRQL at any given moment — not merely the fact that it's running in kernel mode at all — determines what's legal, and code written without tracking which IRQL it's actually running at is a routine, well-documented source of real driver bugs, not a theoretical edge case.

Where this connects

  • Scheduling covers the related but distinct question of which thread runs, once IRQL rules have determined what kind of work is even legal right now.
  • Pool & heap covers why kernel memory allocation itself has to respect these same IRQL constraints — nonpaged pool exists specifically because paged pool can't safely be touched above PASSIVE_LEVEL.