Funzione WdfInterruptTryToAcquireLock (wdfinterrupt.h)
[Si applica a KMDF e UMDF]
Il metodo WdfInterruptTryToAcquireLock tenta di acquisire il blocco passivo di un oggetto interrupt.
Sintassi
BOOLEAN WdfInterruptTryToAcquireLock(
[in] WDFINTERRUPT Interrupt
);
Parametri
[in] Interrupt
Handle per un oggetto di interruzione del framework.
Valore restituito
WdfInterruptTryToAcquireLock restituisce TRUE se acquisisce correttamente il blocco dell'interrupt. In caso contrario, il metodo restituisce FALSE.
Commenti
I driver che usano la gestione degli interruzioni a livello passivochiamano WdfInterruptTryToAcquireLock per avviare una sequenza di codice eseguita in IRQL = PASSIVE_LEVEL mantenendo il blocco di interruzione a livello passivo configurato dal driver nella struttura WDF_INTERRUPT_CONFIG dell'oggetto di interruzione.
WdfInterruptTryToAcquireLock tenta di acquisire il blocco e quindi restituisce immediatamente, indipendentemente dal fatto che abbia acquisito il blocco o meno. Se WdfInterruptTryToAcquireLock acquisisce correttamente il blocco, il framework chiama KeEnterCriticalRegion prima di restituire in modo che le API del kernel normali siano disabilitate.
Per gli oggetti di interruzione a livello passivo, i driver devono chiamare WdfInterruptTryToAcquireLock anziché WdfInterruptAcquireLock, quando vengono eseguiti in un thread arbitrario, ad esempio una funzione di callback dell'oggetto queue. Ad esempio, il driver potrebbe chiamare WdfInterruptTryToAcquireLock da EvtIoRead. In questo modo si evita la possibilità di deadlock, come descritto nella sezione Osservazioni di WdfInterruptAcquireLock.
Quando viene eseguito in un thread non arbitrario, ad esempio un elemento di lavoro, il driver deve usare WdfInterruptAcquireLock.
Quando il driver chiama WdfInterruptReleaseLock, il framework rilascia il blocco di interruzione.
Esempio
Nell'esempio di codice seguente viene illustrato come una funzione di callback EvtIoRead , in esecuzione in un contesto arbitrario, potrebbe chiamare WdfInterruptTryToAcquireLock prima di eseguire un lavoro correlato all'interruzione. Se il metodo restituisce FALSE, il driver accoda un elemento di lavoro per eseguire il lavoro in un thread non arbitrario. Il driver fornisce anche una funzione di callback EvtWorkItem che chiama WdfInterruptAcquireLock prima di eseguire il lavoro.
In questo esempio, il driver ha specificato l'invio sequenziale per la coda. Se il driver ha specificato qualsiasi altro metodo di invio per la coda, il driver deve usare una coda manuale aggiuntiva per conservare le richieste di elaborazione nell'elemento di lavoro. I commenti di codice descrivono dove aggiungere tale supporto.
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);
}
Requisiti
Requisito | Valore |
---|---|
Piattaforma di destinazione | Universale |
Versione KMDF minima | 1.11 |
Versione UMDF minima | 2,0 |
Intestazione | wdfinterrupt.h (include Wdf.h) |
Libreria | Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF) |
IRQL | PASSIVE_LEVEL |
Regole di conformità DDI | DriverCreate(kmdf) |