Typically, a driver's InterruptService routines (ISRs) must share access to driver data and hardware resources with other driver routines. Since ISRs execute in an interrupt context at an elevated IRQL, and since a system might have multiple processors, it is important to synchronize access to shared data and resources so that each routine can be guaranteed to temporarily have exclusive access to this shared information, without interruption.
The system supports this synchronization by enabling you to define critical sections of code. These critical sections must be the only places where shared data and resources are accessed. The system guarantees this code exclusive access to shared information by raising the processor's IRQL and acquiring a spin lock before executing the code. Critical sections reside only in ISRs and SynchCritSection routines. The system calls an ISR when a device interrupts. Drivers call SynchCritSection routines by using KeSynchronizeExecution.
Raising the processor's IRQL to the device's DIRQL value prevents the current processor from being interrupted, except by a higher-priority device. Acquiring a spin lock prevents other processors from executing any critical section code associated with that spin lock. (This spin lock is sometimes called an interrupt spin lock.)
A driver specifies the DIRQL value and spin lock the system will use by supplying SynchronizeIrql and SpinLock parameters when calling IoConnectInterrupt. The values specified for these parameters should be determined as follows:
For a driver that supports a single vector, critical sections execute at the device's DIRQL, and they use a system-supplied spin lock. For a driver that supports multiple vectors and a single set of resources, all critical sections execute at the highest DIRQL used by any interrupt, and they all use a single, driver-supplied spin lock.
For information about writing and calling critical sections, see Using Critical Sections.
The alternative to using critical sections is to serialize IRP processing. That is, a driver would have to complete each I/O request before starting device I/O operations for the next IRP. While this makes it almost impossible for the ISR and another routine, such as a DpcForIsr or CustomDpc routine, to access shared state concurrently, handling IRPs in this manner severely limits I/O throughput for most devices. Note that a driver that serializes its IRP processing can run no faster on SMP machines than in uniprocessor machines.