Pure theoretical question about wdf interrupt lock

Hello!

May be such question has been already discussed here, but I didn’t find any references.
The question is simple: suppose I specify spinlock in WDF_INTERRUPT_CONFIG before WdfInterruptCreate, i.e.

WdfSpinLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &devExt->InterruptSpinLock);
//…
WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, …);
interruptConfig.SpinLock = devExt->InterruptSpinLock;
WdfInterruptCreate(,&devExt->Interrupt);

If I do so can I use the below call
WdfSpinLockAcqure(devExt->InterruptSpinLock, NULL);
instead of
WdfInterruptAcqureLock(devExt->Interrupt);

Yes, you can, but you’ll be risking a deadlock.

Each spinlock as an IRQL that’s IMPLICITLY associated with it. The IRQL of the Interupt Spin Lock is DIRQL. When you acquire a spin lock with WdfSpinLockAcquire, it assumes you’re using an ‘standard executive spin lock’ that is associated with IRQL DISPATCH_LEVEL.

Peter
OSR
@OSRDrivers

On Thu, Apr 23, 2015 at 10:09 AM, wrote:

> WdfInterruptAcqureLock

No. This is documented in the man page for WdfSpinLockAcquire
https:
.

Mark Roddy</https:>

Thanks a lot, Peter, that is exactly as I’ve suspected.
In other words, WdfSpinLockAcqure always internally calls KeAcquireSpinLock (or maybe KeAcquireInStackQueuedSpinLock) .

Thank you, Mark.
So what is the purpose of the Spinlock member of the WDF_INTERRUPT_CONFIG?

Igor Slewsarev

No need to guess, now that the WDF Sources are on GitHub. The ultimate function called when you call WdfSpinLockAcquire:

Acquires_lock(this->m_Lock)
__drv_maxIRQL(DISPATCH_LEVEL)
__drv_setsIRQL(DISPATCH_LEVEL)
FORCEINLINE
VOID
MxLockNoDynam::Acquire(
__out __drv_deref(__drv_savesIRQL) KIRQL * OldIrql
)
{
ASSERT_DBGFLAG_INITIALIZED;

KeAcquireSpinLock(&m_Lock, OldIrql);
}

It’s also interesting to note that WDF Verifier will break on attempts to acquire the Interrupt Spin Lock by calling WdfSpinLockAcquire. THAT’s certainly nice:

VOID
WDFEXPORT(WdfSpinLockAcquire)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
__drv_savesIRQL
Requires_lock_not_held(Curr)
Acquires_lock(Curr)
WDFSPINLOCK SpinLock
)
{
DDI_ENTRY();

PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxSpinLock* pLock;

FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
SpinLock,
FX_TYPE_SPIN_LOCK,
(PVOID*) &pLock,
&pFxDriverGlobals);

if (pLock->IsInterruptLock()) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFSPINLOCK %p is associated with an interrupt, "
“cannot be used for normal sync operations”,
SpinLock);
FxVerifierDbgBreakPoint(pFxDriverGlobals);
return;
}

pLock->AcquireLock(
pFxDriverGlobals->FxVerifierLock ? _ReturnAddress() : NULL);
}

It allows you to have multiple ISRs share the same synchronization domain. S’pose you want to share the interrupt spin lock among multiple devices. That is, there’s some underlying shared state that EVERY device of yours uses, that you might need to access.

It’s a rare, and mostly aberrant, requirement. But you do see it.

Peter
OSR
@OSRDrivers

Tangential tidbit:

When multiple WDFINTERRUPTs share the same WDFSPINLOCK, WDF does a cool (and necessary) thing behind the scenes: it calculates the maximum DIRQL at which the lock should be acquired and uses that value as the SynchronizeIrql when it connects each interrupt with IoConnectInterruptEx. Hence WdfInterruptAcquireLock/KeAcquireSpinLock know the correct IRQL to acquire the lock at.

You can see the code that does that here (large file warning):

https://github.com/Microsoft/Windows-Driver-Frameworks/blob/win-10.0.10041.0/src/framework/shared/irphandlers/pnp/pnpstatemachine.cpp#L4089

Good point!

To take this lesson one step further, people might not realize that (because the IRQL is an *implicit* part of the Spin Lock) the Synchronize IRQL is stored in the KINTERRUPT object. So, before an ISR is called, KiInterruptDispatch retrieves the Syncronize IRQL from the KINTERRUPT, sets the current processor’s IRQL to the Synchronize IRQL, and then acquires the device’s Interrupt Spin Lock.

It’s a bit more complicated than that (life USED to be so simple, sigh…) but that’s close-enough to make the point.

I’d point you to the code on GitHub, but…

Peter
OSR
@OSRDrivers

>I’d point you to the code on GitHub, but…

in the background we here Jiminy Cricket singing “When I wish upon a star …”

-dc

Don’t forget… None other than Mark Russinovich (in his infinite wisdom) said that it could happen. IIRC, his exact words were “entirely possible”… “some time in the future”

For those truly motivated, it’s mostly irrelevant. They can already lookup whatever they want in one of the many copies of the Windows Research Kernel that are online.

Peter
OSR
@OSRDrivers