Функция 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) |