Table 10-3 summarizes the synchronization techniques that are available to WDF drivers.
Technique | UMDF usage | KMDF usage |
---|---|---|
Framework-created object presentation lock for device object and queue objects | Acquire and release with IWDFObject::AcquireLock and IWDFObject::ReleaseLock on the device or queue object. | Acquire and release with WdfObjectAcquireLock and WdfObjectReleaseLock. |
Synchronization scope | Configure with IWDFDeviceInitialize::SetLockingConstraint. | Configure in object attributes structure for driver, device, queue, and file objects. |
Automatic serialization | Not applicable. | Configure in object configuration structure for DPCs, timers, and work items. |
Execution level | Not applicable. | Configure in object attributes structure for driver, device, file, and general objects. |
Wait lock | Not applicable; use a Windows critical section. | Create and manipulate with WdfWaitLockXxx methods. |
Spin lock | Not applicable; UMDF drivers do not require synchronization at raised IRQL. | Create and manipulate with WdfSpinLockXxx methods. |
Events, mutexes, and other Windows-defined mechanisms | Use Windows API functions. | Use Windows kernel-mode DDI functions. |
Interlocked functions | Use Windows API functions. | Use Windows kernel-mode DDI functions. |
The following are some general guidelines for implementing synchronization in WDF drivers:
Use the WDF synchronization features for WDF objects and callbacks. To perform arithmetic or logical operations on a variable or to coordinate your driver's activities with non-WDF features and drivers, use the Windows mechanisms.
Consider the capabilities of your device when you design the I/O queues for your driver, and set the dispatch method and synchronization scope to achieve the required level of concurrency.
Understand the types of data that your driver's callback functions share and whether the shared access is read-only or read-write. Use locks only when the driver's queue dispatch method and synchronization scope do not serialize access for you.
Do not use a lock just to prevent the deletion of an object. Take out a reference instead, and let the framework manage the lifetime.
If your driver uses more than one lock, always acquire the locks in the same order and release them in the opposite order of acquisition to avoid deadlocks. That is, if your driver acquires lock A before lock B, it should release lock B before releasing lock A.
For KMDF drivers, understand the IRQL at which each function can run.