16.2  Using Spin Locks

Spin locks are Kernel-defined, kernel-mode-only synchronization mechanisms, exported as an opaque type: KSPIN_LOCK. A spin lock can be used to protect shared data or resources from simultaneous access by routines that can execute concurrently and at raised IRQL in Windows NT SMP machines.

Many NT components use spin locks, including NT drivers. Any kind of NT driver might use one or more executive spin locks. For example, most NT file systems use an interlocked work queue in the FSD’s device extension to store IRPs that are processed both by the file system’s worker-thread callback routines and by the FSD. An interlocked work queue is protected by an executive spin lock, used to resolve contention among the FSD trying to insert IRPs into the queue and any threads simultaneously trying to remove IRPs. As another example, the system floppy controller driver uses two executive spin locks. One executive spin lock protects an interlocked work queue shared with this driver’s device-dedicated thread; the other protects a timer object shared by three driver routines.

Every NT driver that has an ISR uses an interrupt spin lock to protect any data or hardware shared between its ISR and its SynchCritSection routine(s) that are usually called from a driver’s StartIo and DpcForIsr routines. An interrupt spin lock is associated with the set of interrupt objects created when such a driver calls IoConnectInterrupt, as described in Chapter 3.

All designers of NT drivers that use a spin lock should follow these guidelines:

·Provide the storage for any data or resource protected by a spin lock and for the corresponding spin lock in resident system-space memory (nonpaged pool, as shown in Figure 16.3). A driver must provide the storage for any executive spin locks it uses. However, a device driver need not provide the storage for an interrupt spin lock unless it has a multivector ISR or has more than one ISR, as described in Chapter 3.

·Call KeInitializeSpinLock to initialize each spin lock for which the driver provides storage before using it to synchronize access to the shared data or resource it protects.

·Call every support routine that uses a spin lock at an appropriate IRQL, generally at <= DISPATCH_LEVEL for executive spin locks or at <= DIRQL for an interrupt spin lock associated with the driver’s interrupt object(s).

·Implement routines to execute as quickly as possible while they hold a spin lock. No routine should hold a spin lock for longer than 25 microseconds.

·Never implement routines that do any of the following while holding a spin lock:

·Cause hardware exceptions or raise software exceptions

·Attempt to access pageable memory

·Make a recursive call that would cause a deadlock or could cause a spin lock to be held for longer than 25 microseconds

·Attempt to acquire another spin lock if doing so might cause a deadlock

·Call an external routine that violates any of the preceding rules

The following subsections explain these guidelines in more detail.