Share via


WdfInterruptAcquireLock callback function

[Applies to KMDF and UMDF]

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.

For passive level interrupt objects, the method begins a code sequence that executes at passive level while holding an interrupt object's passive lock.

Syntax

VOID WdfInterruptAcquireLock(
  _In_ WDFINTERRUPT Interrupt
);

Parameters

  • Interrupt [in]
    A handle to a framework interrupt object.

Return value

None.

A bug check occurs if the driver supplies an invalid object handle.

Remarks

When a driver calls WdfInterruptAcquireLock on a DIRQL interrupt object, the system raises the processor's IRQL to the device's DIRQL and acquires the spin lock that the driver specified in the interrupt object's WDF_INTERRUPT_CONFIG structure. As a result, the interrupt object's EvtInterruptIsr and EvtInterruptSynchronize callback functions (and any other code that calls WdfInterruptAcquireLock for the same interrupt object) cannot execute.

When the driver calls WdfInterruptReleaseLock, the system returns the processor's IRQL to its previous level and releases the spin lock.

When a driver calls WdfInterruptAcquireLock on a passive-level interrupt object, the system acquires the passive-level interrupt lock that the driver configured in the interrupt object's WDF_INTERRUPT_CONFIG structure.

When the driver calls WdfInterruptReleaseLock, the system releases the interrupt lock.

For passive level interrupts, the driver must call WdfInterruptAcquireLock at IRQL = PASSIVE_LEVEL.

Do not call WdfInterruptAcquireLock from an arbitrary thread context, such as a request handler.

You can use WdfInterruptAcquireLock and WdfInterruptReleaseLock if your driver must execute a few lines of code without being preempted and with servicing of device interrupts effectively disabled. For larger sections of code, your driver should provide an EvtInterruptSynchronize callback function.

Your driver cannot call WdfInterruptAcquireLock before the framework has called the driver's EvtInterruptEnable callback function or after the framework has called the driver's EvtInterruptDisable callback function.

After your driver calls WdfInterruptAcquireLock, it must not call the method again for the same interrupt object before calling WdfInterruptReleaseLock.

For more information about the WdfInterruptAcquireLock method, see Synchronizing Interrupt Code.

For more information about handling interrupts in framework-based drivers, see Handling Hardware Interrupts.

For passive-level interrupt objects, drivers must call WdfInterruptTryToAcquireLock instead of WdfInterruptAcquireLock, when running in an arbitrary thread, such as a queue object callback function. For example, the driver might call WdfInterruptTryToAcquireLock from EvtIoRead.

Doing so avoids the possibility of deadlock, as described in the following scenario.

  1. In order to determine if its device interrupted, the function driver for an SPB peripheral device sends I/O to its bus from within its ISR, with the passive-level interrupt lock held.
  2. The bus driver completes a second request in the same thread in which it received the above request.
  3. The completion routine of the second request sends a request to the peripheral driver.
  4. The peripheral driver's I/O dispatch routine calls WdfInterruptAcquireLock, which then deadlocks attempting to acquire the interrupt object's passive lock.

Examples

This code example shows how an EvtProgramDma callback function might acquire an interrupt object's spin lock before it accesses device registers to program a DMA transfer. For a complete example of an EvtProgramDma callback function, see the PLX9x5x sample driver.

BOOLEAN
PLxEvtProgramReadDma(
    IN  WDFDMATRANSACTION  Transaction,
    IN  WDFDEVICE  Device,
    IN  WDFCONTEXT  Context, 
    IN  WDF_DMA_DIRECTION  Direction,
    IN  PSCATTER_GATHER_LIST  SgList
    )
{
    //
    // Obtain driver-defined device object context.
    //
    devExt = PLxGetDeviceContext(Device);

    //
    // Acquire the device interrupt's spin lock.
    //
    WdfInterruptAcquireLock(devExt->Interrupt);

    //
    // Access device registers to program the DMA transfer here. 
    //
...

    //
    // Release the device interrupt's spin lock.
    //
    WdfInterruptReleaseLock(devExt->Interrupt);
}

Requirements

Target platform

Universal

Minimum KMDF version

1.0

Minimum UMDF version

2.0

Header

Wdfinterrupt.h (include Wdf.h)

IRQL

<= DIRQL

DDI compliance rules

DriverCreate, KmdfIrql, KmdfIrql2, WdfInterruptLock, WdfInterruptLockRelease

See also

WdfInterruptTryToAcquireLock

WdfInterruptReleaseLock

WdfInterruptSynchronize

WDF_INTERRUPT_CONFIG

EvtInterruptDisable

EvtInterruptEnable

EvtInterruptIsr

EvtInterruptSynchronize

 

 

Send comments about this topic to Microsoft