Condividi tramite


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)

Vedi anche

EvtInterruptWorkItem

WDF_INTERRUPT_CONFIG

WdfInterruptAcquireLock

WdfInterruptReleaseLock

WdfIoQueueRetrieveNextRequest

WdfRequestRequeue

WdfWaitLockAcquire