Synchronization and Threaded DPCs
To synchronize access to a memory location that is accessed from both inside and outside a CustomThreadedDpc routine, a driver can use ordinary spin locks or queued spin locks. When doing so, the driver must obey certain rules to correctly synchronize at IRQL = PASSIVE_LEVEL and at IRQL = DISPATCH_LEVEL, because a CustomThreadedDpc routine can execute at both IRQLs.
For an ordinary spin lock, the following rules apply:
To acquire and release the spin lock, the driver can call KeAcquireSpinLock and KeReleaseSpinLock from both inside and outside the CustomThreadedDpc routine.
The driver can call KeAcquireSpinLockForDpc and KeReleaseSpinLockForDpc from inside the CustomThreadedDpc routine. Note that the CustomThreadedDpc routine must not call KeAcquireSpinLockAtDpcLevel or KeReleaseSpinLockFromDpcLevel, because these routines can safely be called only at IRQL = DISPATCH_LEVEL.
The rules for queued spin locks are similar:
To acquire and release the spin lock, the driver can call KeAcquireInStackQueuedSpinLock and KeReleaseInStackQueuedSpinLock from both inside and outside the CustomThreadedDpc routine.
The driver can call KeAcquireInStackQueuedSpinLockForDpc and KeReleaseInStackQueuedSpinLockForDpc from inside the CustomThreadedDpc routine. Note that the CustomThreadedDpc routine must not call KeAcquireInStackQueuedSpinLockAtDpcLevel or KeReleaseInStackQueuedSpinLockFromDpcLevel, because these routines can safely be called only at IRQL = DISPATCH_LEVEL.
Because KeAcquireSpinLockForDpc and KeAcquireInStackQueuedSpinLockForDpc do not reset the IRQL when called at DISPATCH_LEVEL, they execute faster than KeAcquireSpinLock and KeAcquireInStackQueuedSpinLock, respectively.
For more information about spin locks, see Spin Locks.