次の方法で共有


CustomTimerDpc ルーチンの使用

以前に設定したタイマー オブジェクトを無効にするには、ドライバーが KeCancelTimer を呼び出します。 このルーチンは、システムのタイマー キューからタイマー オブジェクトを削除します。 一般に、タイマー オブジェクトはシグナル状態に設定されず、CustomTimerDpc ルーチンは実行キューに登録されません。 ただし、KeCancelTimer が呼び出されたときにタイマーの有効期限が切れそうになると、KeCancelTimer がタイム キューにアクセスする前に有効期限が切れてします可能性があります。この場合、シグナリングと DPC キューが発生します。

以前に指定した Timer ポインターと Dpc ポインターを持つ KeSetTimer または KeSetTimerEx を、前に指定した間隔の有効期限が切れる前に呼び出すと、次の効果があります。

  • カーネルは、オブジェクトをシグナル状態に設定したり、CustomTimerDpc ルーチンをキューに入れたりせずに、タイマー キューからタイマー オブジェクトを削除します。

  • カーネルは、新しい DueTime 値を使用して、タイマー キュー内のタイマー オブジェクトを再挿入します。

異なる目的で同じタイマー オブジェクトを使用すると、競合状態や深刻なドライバー エラーが発生する可能性があります。 たとえば、ドライバーは、CustomTimerDpc ルーチンへの呼び出しを設定し、ドライバー専用スレッドで待機を設定する両方の 1 つのタイマー オブジェクトを指定するとします。 ドライバー専用スレッドが共通タイマー オブジェクトの KeSetTimerKeSetTimerEx、または KeCancelTimer を呼び出すたびに、タイマー オブジェクトが CustomTimerDpc 呼び出し用に既にキューに登録されている場合、スレッドは CustomTimerDpc ルーチンの呼び出しを取り消します。

ドライバーに CustomTimerDpc ルーチンがあり、非ビット スレッド コンテキストでタイマー オブジェクトを待機する場合は、次の操作を行う必要があります。

  • スレッド コンテキスト依存タイマー オブジェクトを非ビット スレッド コンテキストでは使用しないでください。その逆も同様です。

  • CustomTimerDpc ルーチンごとに個別のタイマー オブジェクトを割り当てます。 非ビット スレッド コンテキストで呼び出されるドライバー スレッドまたはドライバー ルーチンの各セットは、それ自身の "待機可能" タイマー オブジェクトのセットを持つ必要があります。

CustomTimerDpc ルーチンを使用する場合は、ドライバーが KeSetTimer または KeSetTimerEx への呼び出しで渡す間隔を慎重に選択します。 さらに、この呼び出しを行うドライバー ルーチンから同じタイマー オブジェクトを使用して KeCancelTimer を呼び出す場合、特に SMP プラットフォームで発生する可能性のあるすべての影響を考慮してください。

CustomTimerDpc ルーチンについては、次の点に注意してください。

特定の DPC ルーチンを表す DPC オブジェクトのインスタンス化は、任意の時点で 1 つだけ実行キューに入れられます。

2 番目のドライバー ルーチンが KeSetTimer または KeSetTimerEx を呼び出して、最初の呼び出し元によって指定された間隔が経過する前に同じ CustomTimerDpc ルーチンを実行する場合、CustomTimerDpc ルーチンは、2 番目の呼び出し元によって指定された間隔の有効期限が切れた後にのみ実行されます。 このような状況では、CustomTimerDpc は、最初のルーチンが KeSetTimer または KeSetTimerEx と呼ばれる作業を行いません。

CustomTimerDpc ルーチンを持ち、定期的なタイマーを使用するドライバーの場合:

ドライバーは、DPC ルーチンから定期的なタイマーの割り当てを解除できません。 ドライバーは、DPC ルーチンから非周期タイマーの割り当てを解除できます。

CustomDpc ルーチンと CustomTimerDpc ルーチンの両方を持つドライバーの次の設計ガイドラインを考慮してください。

競合状態を防ぐために、同じ Dpc ポインターを KeSetTimer または KeSetTimerExKeInsertQueueDpc に渡さないようにします。

つまり、ドライバーの StartIo ルーチンが KeSetTimer または KeSetTimerEx を呼び出して CustomTimerDpc ルーチンをキューに入れ、ドライバーの ISR が同じ Dpc ポインターを持つ別のプロセッサから KeInsertQueueDpc を同時に呼び出すとします。 この DPC ルーチンは、プロセッサ上の IRQL が DISPATCH_LEVEL を下回った場合、またはタイマー間隔の有効期限が切れた場合、どちらか早い方に実行されます。 どちらが先でも、StartIo または ISR に必要な作業は DPC ルーチンによって削除されます。

さらに、機能が非常に異なる 2 つの標準ドライバー ルーチンで使用される DPC は、個別の CustomTimerDpc ルーチンと CustomDpc ルーチンよりもパフォーマンス特性が低くなります。 DPC は、StartIo ルーチンまたは ISR がキューに入れる原因となった条件に応じて、実行する操作を決定する必要があります。 DPC でこれらの条件をテストすると、追加の CPU サイクルが使用されます。