WdfInterruptTryToAcquireLock 関数 (wdfinterrupt.h)

[KMDF と UMDF に適用]

WdfInterruptTryToAcquireLock メソッドは、割り込みオブジェクトのパッシブ ロックの取得を試みます。

構文

BOOLEAN WdfInterruptTryToAcquireLock(
  [in] WDFINTERRUPT Interrupt
);

パラメーター

[in] Interrupt

フレームワーク割り込みオブジェクトへのハンドル。

戻り値

割り込みのロックが正常に取得された場合、WdfInterruptTryToAcquireLock は TRUE を返します。 それ以外の場合、メソッドは FALSE を返します。

注釈

パッシブ レベルの割り込み処理を使用するドライバーは、WdfInterruptTryToAcquireLock を呼び出して、割り込みオブジェクトのWDF_INTERRUPT_CONFIG構造でドライバーが構成したパッシブ レベルの割り込みロックを保持しながら、IRQL = PASSIVE_LEVELで実行されるコード シーケンスを開始します。

WdfInterruptTryToAcquireLock はロックの取得を試み、ロックを取得したかどうかに関係なく、すぐにを返します。 WdfInterruptTryToAcquireLock が正常にロックを取得した場合、フレームワークは、通常のカーネル APCs が無効になるように、戻る前に KeEnterCriticalRegion を呼び出します。

パッシブ レベルの割り込みオブジェクトの場合、ドライバーは、キュー オブジェクトコールバック関数などの任意のスレッドで実行されている場合、WdfInterruptAcquireLock ではなく WdfInterruptTryToAcquireLock を呼び出す必要があります。 たとえば、ドライバーは EvtIoRead から WdfInterruptTryToAcquireLock を呼び出す場合があります。 これにより、 WdfInterruptAcquireLock の「解説」セクションで説明されているように、デッドロックの可能性を回避できます。

任意でないスレッド (作業項目など) で実行する場合、ドライバーは WdfInterruptAcquireLock を使用する必要があります。

ドライバーが WdfInterruptReleaseLock を呼び出すと、フレームワークは割り込みロックを解放します。

次のコード例は、割り込み関連の作業を実行する前に、任意のコンテキストで実行されている EvtIoRead コールバック関数が WdfInterruptTryToAcquireLock を 呼び出す方法を示しています。 メソッドが FALSE を返す場合、ドライバーは、任意でないスレッドで作業を実行する作業項目をキューに入れます。 ドライバーは、作業を実行する前に WdfInterruptAcquireLock を呼び出す EvtWorkItem コールバック関数も提供します。

この例では、ドライバーはキューの 順次 ディスパッチを指定しています。 ドライバーがキューに 対して他のディスパッチメソッドを 指定した場合、ドライバーは追加の手動キューを使用して、作業項目での処理要求を保持する必要があります。 コード コメントでは、このようなサポートを追加する場所について説明します。


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
Header wdfinterrupt.h (Wdf.h を含む)
Library Wdf01000.sys (KMDF);WUDFx02000.dll (UMDF)
IRQL PASSIVE_LEVEL
DDI コンプライアンス規則 DriverCreate(kmdf)

こちらもご覧ください

EvtInterruptWorkItem

WDF_INTERRUPT_CONFIG

WdfInterruptAcquireLock

WdfInterruptReleaseLock

WdfIoQueueRetrieveNextRequest

WdfRequestRequeue

WdfWaitLockAcquire