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) |