WdfInterruptTryToAcquireLock() vs WdfInterruptAcquireLock()

Hey All,
Is it possible to use WdfInterruptAcquireLock() instead of WdfInterruptTryToAcquireLock() in a KMDF driver if you are not using passive interrupt handling (WDF_INTERRUPT_CONFIG::PassiveHandling == FALSE)? The docs are pretty clear on passive interrupt handling, but pretty fuzzy without passive interrupt handling. I’ve tried WdfInterruptTryToAcquireLock() in a EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL callback and it consistently fails and I have to resort to a work item which seems pretty excessive for just setting 1 little variable shared between multiple callbacks.
I need all this to synchronize data between an EVT_WDF_INTERRUPT_ISR, an EVT_WDF_INTERRUPT_DPC and EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL. For context, the EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL basically blocks the calling user space thread until a hardware event is triggered, the EVT_WDF_INTERRUPT_ISR is triggered by the hardware which sets a flag on a shared variable and queues up the EVT_WDF_INTERRUPT_DPC via WdfInterruptQueueDpcForIsr() that completes the original blocking EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL request using WdfRequestComplete().
Thanks!

The docs are pretty clear on passive interrupt handling, but pretty fuzzy without passive interrupt handling

Well, I don’t really know what you mean by " fuzzy" in this context, but let’s look at the following MSDN article

https://msdn.microsoft.com/library/windows/hardware/ff547340

It starts right with the following line

[begin quote]

The WdfInterruptAcquireLock method begins a code sequence that executes at the device’s device interrupt request level (DIRQL) while holding an interrupt object’s spin lock.

[end quote]

In other words, the official documentation seems to be VERY clear and precise on this matter, don’t you think - it makes it clear that WdfInterruptAcquireLock() is perfectly usable by the drivers that handle interrupts at DIRQL. Furthermore, the documentation makes it clear the same thing does NOT apply to WdfInterruptTryToAcquireLock()

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdfinterrupt/nf-wdfinterrupt-wdfinterrupttrytoacquirelock

[begin quote]

Drivers that use passive-level interrupt handling call WdfInterruptTryToAcquireLock to start a code sequence that executes at IRQL = PASSIVE_LEVEL while holding the passive-level interrupt lock that the driver configured in the interrupt object’s WDF_INTERRUPT_CONFIG structure.

[end quote]

The “only” question that may possibly arise at this point is “WTF does the OP want to call WdfInterruptTryToAcquireLock() if his driver does not use passive-level interrupt handling, in the first place???”…

Anton Bassov

Just use WdfInterrupAcquireLock… it’s what we all do.

the EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL basically blocks the calling user space thread until a hardware event is triggered

That’s not a very good driver design in the world of Windows. First, your EvtDeviceControl is called in an arbitrary process/thread context. So if you blockmthere, you can’t be certain what thread you’re blocking. And, even if you are blocking the thread that sent the Request to you, that’s generally considered bad practice.

Doing this then”right” way (what would be the Windows way) is easy. Just start the Request in EvtDeviceControl… do not complete it. Instead, save the Request handle someplace (you could put it in a variable in your Device context, or put it in a WDF Queue… then, after the interrupt, in your DPC, simply come,etc the Request.

The calling thread sends the Device Control synchronously, and doesn’t continue running until it’s completed. Quite easy, right?

Peter

OK, thanks I went ahead and ditched the work item and am just using WdfInterrupAcquireLock().
Peter, thanks but that is what I’m doing, I probably just didn’t phrase it well. I have a variable set by the ISR to indicate the hardware event triggered. In the EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL I acquire the interrupt lock and check this variable. If it’s set I just call WdfRequestComplete() right there and if not I store this WDFREQUEST and call WdfRequestMarkCancelableEx(). in the interrupt’s DPC I acquire the interrupt lock and if the variable is set, I call WdfRequestComplete() on the stored WDFREQUEST. So the request may complete immediately if the hardware already triggered or later via the DPC.