Поделиться через


Функция WdfInterruptTryToAcquireLock (wdfinterrupt.h)

[Применимо к KMDF и UMDF]

Метод WdfInterruptTryToAcquireLock пытается получить пассивную блокировку объекта прерывания.

Синтаксис

BOOLEAN WdfInterruptTryToAcquireLock(
  [in] WDFINTERRUPT Interrupt
);

Параметры

[in] Interrupt

Дескриптор объекта прерывания платформы.

Возвращаемое значение

WdfInterruptTryToAcquireLock возвращает значение TRUE, если успешно получает блокировку прерывания. В противном случае метод возвращает значение FALSE.

Комментарии

Драйверы, использующие обработку прерываний пассивного уровня , вызывают WdfInterruptTryToAcquireLock для запуска последовательности кода, которая выполняется в IRQL = PASSIVE_LEVEL при удержании блокировки прерываний пассивного уровня, настроенной драйвером в WDF_INTERRUPT_CONFIG структуре объекта прерывания.

WdfInterruptTryToAcquireLock пытается получить блокировку, а затем немедленно возвращается, независимо от того, была ли она приобретена блокировка. Если WdfInterruptTryToAcquireLock успешно получает блокировку, платформа вызывает KeEnterCriticalRegion перед возвратом, чтобы обычные APC ядра были отключены.

Для объектов прерываний пассивного уровня драйверы должны вызывать WdfInterruptTryToAcquireLock вместо WdfInterruptAcquireLock при выполнении в произвольном потоке, например функции обратного вызова объекта очереди. Например, драйвер может вызывать WdfInterruptTryToAcquireLock из EvtIoRead. Это позволяет избежать взаимоблокировки, как описано в разделе Примечания статьи WdfInterruptAcquireLock.

При выполнении в не произвольном потоке, например рабочем элементе, драйвер должен использовать WdfInterruptAcquireLock.

Когда драйвер вызывает WdfInterruptReleaseLock, платформа снимает блокировку прерываний.

Примеры

В следующем примере кода показано, как функция обратного вызова EvtIoRead , выполняющаяся в произвольном контексте, может вызвать WdfInterruptTryToAcquireLock перед выполнением работы, связанной с прерыванием. Если метод возвращает значение FALSE, драйвер помещает рабочий элемент в очередь для выполнения работы в произвольном потоке. Драйвер также предоставляет функцию обратного вызова EvtWorkItem , которая вызывает WdfInterruptAcquireLock перед выполнением работы.

В этом примере драйвер указал последовательную диспетчеризацию для очереди. Если драйвер указал любой другой метод диспетчеризации для очереди, драйвер должен использовать дополнительную очередь вручную, чтобы сохранить запросы на обработку в рабочем элементе. Комментарии к коду описывают, где следует добавить такую поддержку.


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

Требования

Требование Значение
Целевая платформа Универсальное
Минимальная версия KMDF 1.11
Минимальная версия UMDF 2,0
Верхняя часть wdfinterrupt.h (включая Wdf.h)
Библиотека Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL PASSIVE_LEVEL
Правила соответствия DDI DriverCreate(kmdf)

См. также раздел

EvtInterruptWorkItem

WDF_INTERRUPT_CONFIG

WdfInterruptAcquireLock

WdfInterruptReleaseLock

WdfIoQueueRetrieveNextRequest

WdfRequestRequeue

WdfWaitLockAcquire