Interrupt Spin Locks

The classic spin lock is typically acquired at DISPATCH_LEVEL. The raised IRQL ensures that no other thread on the same processor gets to execute, let alone to contend for the lock. It does, however, allow that hardware interrupts can occur. To access a resource that is also accessed by a hardware interrupt, the lock that protects the resource must be acquired at the even higher IRQL that is associated with the interrupt.

When a driver registers a callback routine for servicing a hardware interrupt, it is allocated a KINTERRUPT structure. It can supply a spin lock to associate with this structure or it can elect to use a spin lock that is built into the structure. Among the many other parameters it associates with the interrupt is a SynchronizationIrql at which to acquire this lock. When the interrupt occurs and the kernel calls the service routine, it raises the IRQL and acquires the lock. If at any other time, the driver wants safe access to some resource that might also be accessed from the service routine, then the driver can acquire this same lock at this same IRQL.

The original support for this is the KeSynchronizeExecution function. It specifies a routine to call back, with arbitrary context, having raised the IRQL and acquired the lock. It’s a little cumbersome, and Windows XP instead exposed the IRQL and lock more conveniently: KeAcquireInterruptSpinLock raises the IRQL and acquires the lock so that its caller can then proceed to whatever work is wanted before calling KeReleaseInterruptSpinLock to release the lock and restore the IRQL.