スピン ロックの概要

スピン ロックはカーネル定義のカーネル モード専用同期メカニズムであり、非透過的な型としてエクスポートされます:KSPIN_LOCK。 スピン ロックを使用して、共有データまたはリソースを同時アクセスから保護できます。 IRQL <= DISPATCH_LEVELで実行する場合、ドライバーは KeAcquireInStackQueuedSpinLock KeReleaseInStackQueuedSpinLock を使用して、キューに格納されたスピン ロックとしてスピン ロックを取得して解放できます。

または、IRQL >= DISPATCH_LEVEL で実行されている呼び出し元は、ドライバーのパフォーマンスを向上させるために、KeAcquireSpinLockAtDpcLevel KeReleaseSpinLockFromDpcLevel を呼び出すことができます。

多くのコンポーネントでは、ドライバーを含むスピン ロックが使用されます。 どのような種類のドライバーでも、1 つ以上 のエグゼクティブ スピン ロックを使用できます。 たとえば、ほとんどのファイル システムでは、ファイル システム ドライバー (FSD) のデバイス拡張機能のインターロックされた作業キューを使用して、ファイル システムのワーカー スレッド コールバック ルーチンと FSD の両方によって処理される IRP を格納します。 インターロックされた作業キューは、エグゼクティブ スピン ロックによって保護されます。これは、キューに IRP を挿入しようとしている FSD と、IRP を同時に削除しようとするスレッド間の競合を解決します。 別の例として、システム フロッピー コントローラー ドライバーは、2 つのエグゼクティブ スピン ロックを使用します。 1 つのエグゼクティブ スピン ロックは、このドライバーのデバイス専用スレッドと共有されている連動作業キューを保護します。もう一方は、3 つのドライバー ルーチンによって共有されるタイマー オブジェクトを保護します。

キューに置かれたスピン ロックは、マルチプロセッサ マシンでの高い競合ロックに対する通常のスピン ロックよりも優れたパフォーマンスを提供します。 詳細については、「キューに入ったスピン ロック」を参照してください。 ドライバーは、KeAcquireSpinLock KeReleaseSpinLock を使用して、通常のスピン ロックとしてスピン ロックを取得および解放することもできます。

単純なデータ構造へのアクセスを同期するために、ドライバーは ExInterlockedXxx ルーチンのいずれかを使用して、データ構造へのアトミック アクセスを確保できます。 これらのルーチンを使用するドライバーは、スピン ロックを明示的に取得または解放する必要はありません。

ISR を持つすべてのドライバーは、割り込みスピン ロックを使用して、通常は StartIo ルーチンと DpcForIsr ルーチンから呼び出される、ISR とその SynchCritSection ルーチンの間で共有されているデータまたはハードウェアを保護します。 割り込みスピン ロックは、「ISR の登録」の説明に従って、ドライバーが IoConnectInterrupt を呼び出したときに作成された割り込みオブジェクトのセットに関連付けられます。

ドライバーでスピン ロックを使用するには、次のガイドラインに従います。

  • スピン ロックによって保護されているデータまたはリソース、および常駐システム空間メモリ内の対応するスピン ロック用の記憶域を提供します (非ページ プール (仮想メモリスペースと物理メモリ図を参照)。 ドライバーは、使用するエグゼクティブ スピン ロックの記憶域を提供する必要があります。 ただし、デバイス ドライバーは、マルチベクトル ISR を持っているか、ISR の登録に関する説明に従って複数の ISR を持っていない限り、割り込みスピン ロックの記憶域を提供する必要はありません。

  • KeInitializeSpinLock を呼び出して、ドライバーが記憶域を提供する各スピン ロックを初期化してから、保護する共有データまたはリソースへのアクセスを同期します。

  • 適切な IRQL でスピン ロックを使用するすべてのサポート ルーチンを呼び出します。通常 <は、エグゼクティブ スピン ロックの場合は DISPATCH_LEVEL、ドライバーの割り込みオブジェクトに関連付けられている割り込みスピン ロックの場合は at <= DIRQL です。

  • スピン ロックを保持している間、できるだけ迅速に実行するルーチンを実装します。 25 マイクロ秒を超えるスピン ロックを保持するルーチンはありません。

  • スピン ロックを保持している間は、次のいずれかを実行するルーチンを実装しないでください。

    • ハードウェア例外を発生させるか、ソフトウェア例外を発生させます。

    • ページング可能なメモリへのアクセスを試みます。

    • デッドロックの原因となる再帰呼び出しを行うか、スピン ロックが 25 マイクロ秒を超えて保持される可能性があります。

    • 別のスピン ロックを取得しようとすると、デッドロックが発生する可能性があります。

    • 上記の規則のいずれかに違反する外部ルーチンを呼び出します。