Partager via


WdfInterruptTryToAcquireLock, fonction (wdfinterrupt.h)

[S’applique à KMDF et UMDF]

La méthode WdfInterruptTryToAcquireLock tente d’acquérir le verrou passif d’un objet d’interruption.

Syntaxe

BOOLEAN WdfInterruptTryToAcquireLock(
  [in] WDFINTERRUPT Interrupt
);

Paramètres

[in] Interrupt

Handle pour un objet d’interruption de framework.

Valeur retournée

WdfInterruptTryToAcquireLock retourne TRUE s’il acquiert correctement le verrou de l’interruption. Sinon, la méthode retourne FALSE.

Remarques

Les pilotes qui utilisent la gestion des interruptions de niveau passif appellent WdfInterruptTryToAcquireLock pour démarrer une séquence de code qui s’exécute à IRQL = PASSIVE_LEVEL tout en maintenant le verrou d’interruption de niveau passif que le pilote a configuré dans la structure WDF_INTERRUPT_CONFIG de l’objet d’interruption.

WdfInterruptTryToAcquireLock tente d’acquérir le verrou, puis retourne immédiatement, qu’il ait acquis le verrou ou non. Si WdfInterruptTryToAcquireLock acquiert correctement le verrou, l’infrastructure appelle KeEnterCriticalRegion avant de retourner afin que les API de noyau normales soient désactivées.

Pour les objets d’interruption de niveau passif, les pilotes doivent appeler WdfInterruptTryToAcquireLock au lieu de WdfInterruptAcquireLock, lors de l’exécution dans un thread arbitraire, tel qu’une fonction de rappel d’objet file d’attente. Par exemple, le pilote peut appeler WdfInterruptTryToAcquireLock à partir d’EvtIoRead. Cela permet d’éviter le risque d’interblocage, comme décrit dans la section Remarques de WdfInterruptAcquireLock.

Lors de l’exécution dans un thread non arbitraire, tel qu’un élément de travail, le pilote doit utiliser WdfInterruptAcquireLock.

Lorsque le pilote appelle WdfInterruptReleaseLock, le framework libère le verrou d’interruption.

Exemples

L’exemple de code suivant montre comment une fonction de rappel EvtIoRead , exécutée dans un contexte arbitraire, peut appeler WdfInterruptTryToAcquireLock avant d’effectuer un travail lié aux interruptions. Si la méthode retourne FALSE, le pilote met en file d’attente un élément de travail pour effectuer le travail dans un thread non arbitraire. Le pilote fournit également une fonction de rappel EvtWorkItem qui appelle WdfInterruptAcquireLock avant d’effectuer le travail.

Dans cet exemple, le pilote a spécifié la répartition séquentielle pour la file d’attente. Si le pilote a spécifié une autre méthode de répartition pour la file d’attente, il doit utiliser une file d’attente manuelle supplémentaire pour conserver les demandes de traitement dans l’élément de travail. Les commentaires de code décrivent où ajouter ce 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); 
}

Configuration requise

Condition requise Valeur
Plateforme cible Universal
Version KMDF minimale 1.11
Version UMDF minimale 2.0
En-tête wdfinterrupt.h (inclure Wdf.h)
Bibliothèque Wdf01000.sys (KMDF) ; WUDFx02000.dll (UMDF)
IRQL PASSIVE_LEVEL
Règles de conformité DDI DriverCreate(kmdf)

Voir aussi

EvtInterruptWorkItem

WDF_INTERRUPT_CONFIG

WdfInterruptAcquireLock

WdfInterruptReleaseLock

WdfIoQueueRetrieveNextRequest

WdfRequestRequeue

WdfWaitLockAcquire