NT's interrupt management affects realtime system applicability
One of Windows NT's primary responsibilities is interfacing a computer to its peripheral devices. Like most modern operating systems, NT can dynamically integrate device driver programs to manage devices. Device drivers typically use interrupt signals to communicate with the devices they control. When a device has completed a driver-directed operation or when the device has new data for the driver, the device generates an interrupt signal. Depending on the state of the CPU, either a function within the driver immediately services the device's interrupt, or the CPU queues the interrupt for later servicing.
NT implements interrupt processing differently from many other operating systems, so how NT and NT device drivers process interrupts and how that
processing affects other operations can be confusing. For example, systems
programmers often ask me how interrupts affect thread scheduling--a natural
question because the CPU can receive interrupt signals almost anytime, even
while user programs perform ordinary processing. A common misconception is that
NT won't service low-priority interrupt signals while high-priority threads are
executing time-critical tasks. (For more information about thread priorities and
scheduling, see "Inside the Windows NT Scheduler, Part 1", July 1997.)
The way NT handles interrupt processing affects NT's viability as an
operating system for realtime (time-critical) environments (e.g., aircraft
guidance systems). NT's rich development environment, user interface, and thread
priority scheme make NT attractive to designers of realtime systems. However,
realtime environments require the ability to predict how fast an operating
system will react to interrupts; thus, the way NT implements interrupt handling
affects how suitable it is for realtime applications.
In this column, I'll first provide background information about interrupts
and describe NT's Interrupt Request Level (IRQL) architecture. Next, I'll
present how device drivers register to receive notification of interrupts that
their devices generate and what device drivers typically do upon notification.
Finally, I'll describe the effect of interrupt processing on the NT scheduler
and comment on how NT's interrupt processing affects its applicability for
realtime systems.
Devices and Interrupts
All the major hardware architectures that NT runs on have
interrupt-controller hardware to translate device interrupts into signal levels
that feed into the CPU. The interrupt controller defines the interrupt priority
scheme: When a device triggers an interrupt of a given priority, the controller
masks (or withholds) from the CPU all interrupts of priority less than
or equal to the device interrupt's priority. Until the CPU signals to the
interrupt controller that it has finished servicing an interrupt, the interrupt
controller pends (or puts on hold) lower priority interrupts but lets
higher priority interrupts occur. When the interrupt level on the controller
drops below an interrupt's priority, the controller lets the interrupt proceed
to the CPU.
Device controllers connected to modern CPU buses (such as the popular PCI
bus) dynamically determine which interrupts their device will use. When a device
needs to inform its driver of an event (such as the availability of new data),
it generates an interrupt that the device driver will recognize and acknowledge.
The device driver registers an interrupt service routine (ISR) with the
operating system, and the operating system executes the ISR in response to the
interrupt. The ISR's job is to read status information from the device,
acknowledge the interrupt, and stop the device from signaling the interrupt.
Interrupt Request Levels
NT manages interrupts by mapping interrupt-controller interrupt levels onto
its hardware-independent table of interrupt levels. The hardware abstraction
layer (HAL--the NT module custom-written for individual interrupt controllers,
motherboards, or processor chip-sets) performs the mapping. In a multiprocessor
system, any processor can receive interrupts, so NT maintains an independent
IRQL for each processor. A processor's IRQL represents the level of interrupt
that the CPU is currently masking and directly corresponds to interrupts that
the CPU's interrupt controller masks. Because NT's IRQLs are not tied to any
hardware specification, NT can also map non-hardware interrupt types into its
priority hierarchy. The operating system uses software interrupts primarily to
initiate scheduling operations, such as thread switching, or I/O completion
processing.
When NT services a hardware interrupt, NT sets the processor's IRQL to the
corresponding mapped value in NT's IRQL table. NT programs the interrupt
controller to mask out lower priority interrupts, and device drivers (as well as
NT) can query the IRQL to determine its value. (NT permits some operations only
when the IRQL is less than certain values, as we'll see later.)
The size of NT's IRQL table varies among processor architectures (Intel,
Alpha, etc.) to better map the interrupt levels that standard interrupt
controllers provide, but interrupt levels that device-driver designers and NT's
developers might find interesting have symbolic names. Table 1 summarizes the
symbolic IRQL names and their corresponding numeric values on Intel and Alpha
architectures.