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) |