Synchronizing Interrupt Code
[This topic applies to UMDF 1.x.]
All driver code that accesses the interrupt data buffer must be synchronized so that only one routine accesses the data at a time.
You can synchronize interrupt code by using either manual interrupt locking or automatic callback serialization.
If a driver needs to synchronize any code using the interrupt lock, it calls IWDFInterrupt::AcquireInterruptLock and IWDFInterrupt::ReleaseInterruptLock. For example, a driver acquires and releases the interrupt lock in its OnInterruptWorkItem callback routine by using these methods. However, in I/O dispatch callbacks (such as OnRead and OnWrite), the driver first calls IWDFInterrupt::TryToAcquireInterruptLock to decide whether to queue a work item or do the work in same thread to avoid potential deadlock. For an example of a deadlock scenario that can be caused by calling IWDFInterrupt::AcquireInterruptLock from an arbitrary thread context, see the Remarks section of IWDFInterrupt::AcquireInterruptLock.
If IWDFInterrupt::TryToAcquireInterruptLock returns TRUE, the driver has acquired the interrupt lock in the same thread. In this case, the driver performs the work that required that lock, and then calls ReleaseInterruptLock. If IWDFInterrupt::TryToAcquireInterruptLock returns FALSE, the driver queues a work item and performs the work in its OnWorkItem callback. In this case, the work item must not use automatic serialization.
A UMDF driver can request automatic callback synchronization by calling IWDFDeviceInitialize::SetLockingConstraint with the LockType parameter set to WdfDeviceLevel.
As a result, UMDF serializes the driver's OnInterruptWorkItem callbacks with I/O queue, request cancellation, and file object callback routines. In this scenario, UMDF uses the callback lock instead of a per-interrupt object lock.