Bewerken

Delen via


WdfInterruptTryToAcquireLock function (wdfinterrupt.h)

[Applies to KMDF and UMDF]

The WdfInterruptTryToAcquireLock method attempts to acquire an interrupt object's passive lock.

Syntax

BOOLEAN WdfInterruptTryToAcquireLock(
  [in] WDFINTERRUPT Interrupt
);

Parameters

[in] Interrupt

A handle to a framework interrupt object.

Return value

WdfInterruptTryToAcquireLock returns TRUE if it successfully acquires the interrupt’s lock. Otherwise, the method returns FALSE.

Remarks

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.

WdfInterruptTryToAcquireLock attempts to acquire the lock and then returns immediately, whether it has acquired the lock or not. If WdfInterruptTryToAcquireLock does successfully acquire the lock, the framework calls KeEnterCriticalRegion before returning so that normal kernel APCs are disabled.

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 Remarks section of WdfInterruptAcquireLock.

When running in a non-arbitrary thread, such as a work item, the driver should use WdfInterruptAcquireLock.

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

Examples

The following code example shows how an EvtIoRead callback function, running in an arbitrary context, might call WdfInterruptTryToAcquireLock before performing interrupt-related work. If the method returns FALSE, the driver queues a work item to perform the work in a non-arbitrary thread. The driver also supplies an EvtWorkItem callback function that calls WdfInterruptAcquireLock before it performs the work.

In this example, the driver has specified sequential dispatching for the queue. If the driver specified any other dispatching method for the queue, the driver should use an additional manual queue to retain requests for processing in the work item. Code comments describe where to add such support.


VOID EvtIoRead(
  __in  WDFQUEUE Queue,
  __in  WDFREQUEST Request,
  __in  size_t Length
    )
{
    DEVICE_CONTEXT    devCtx;
    devCtx = GetDeviceContext(WdfIoQueueGetDevice(Queue));
    
    //
    // Do any pre-acquiring interrupt lock work here.
    //
   

    //
    // Check if we can acquire the lock.
    //
    if (WdfInterruptTryToAcquireLock(devCtx->InterruptObject) {
        ReadFunctionLocked(Request);
        WdfInterruptReleaseLock(devCtx->InterruptObject);
        //
        // Do any post-releasing interrupt lock work here.
        // For example: complete the request, and so on.
        //
        ReadFunctionFinish(Request); 
    }
    else {
        WORK_ITEM_CONTEXT ctx;

        ctx = GetWorkItemContext(ReadWorkItem);
        ctx->Request = Request;

        // If previous queue is non-sequential, call WdfRequestForwardToIoQueue 
        // to store request in an additional manual queue.

        WdfWorkItemEnqueue(ReadWorkItem);
    }
}


VOID
EvtReadWorkItemCallback(
    WDFWORKITEM WorkItem
    )
{
    WORK_ITEM_CONTEXT wiCtx;
    DEVICE_CONTEXT    devCtx;

    wiCtx = GetWorkItemContext(ReadWorkItem);
    devCtx = GetDeviceContext(WdfWorkItemGetParentObject(WorkItem));

    // If delivery queue is non-sequential, call WdfIoQueueRetrieveNextRequest 
    // to retrieve request that we stored in EvtIoRead.

    //
    // Acquire interrupt lock.
    //
    WdfInterruptAcquireLock(devCtx->InterruptObject);
    ReadFunctionLocked(wiCtx->Request);
    WdfInterruptReleaseLock(devCtx->InterruptObject);

    //
    // Do any post-releasing interrupt lock work here.
    // For example: complete the request, and so on.
    //
    ReadFunctionFinish(wiCtx->Request); 
}

Requirements

Requirement Value
Target Platform Universal
Minimum KMDF version 1.11
Minimum UMDF version 2.0
Header wdfinterrupt.h (include Wdf.h)
Library Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL PASSIVE_LEVEL
DDI compliance rules DriverCreate(kmdf)

See also

EvtInterruptWorkItem

WDF_INTERRUPT_CONFIG

WdfInterruptAcquireLock

WdfInterruptReleaseLock

WdfIoQueueRetrieveNextRequest

WdfRequestRequeue

WdfWaitLockAcquire