WavePci ミニポート ドライバーにおける信頼性の問題
WavePci ミニポート ドライバーは、ポート ドライバーから受け取るマッピングを追跡する必要があります。 WavePci ミニポート ドライバーは、ドライバー スレッド間で共有されるデータ構造内にマッピングのリストを維持します。 また、ドライバー スレッドは、新しいマッピングをハードウェア キューに追加したり、完了したマッピングをキューから削除したりするために、DMA チャネルへのアクセスを共有する必要があります。 データの破損を防ぐために、ミニポート ドライバーはスピン ロックを使用して、共有データ構造およびペリフェラルへのアクセスをシリアル化します。 スピン ロックは、共有データとハードウェア キューを 2 つ以上のドライバー スレッドによる同時アクセスから保護します。
マッピングを管理するドライバーの部分を開発する場合、ベンダーは次の点に特に注意を払う必要があります。
スピン ロック
潜在的なデッドロックを回避するために、ミニポート ドライバーは、マッピングを取得または解放するために Portcls.sys を呼び出すときに独自のスピン ロックを保持してはなりません。 Microsoft Windows Driver Kit (WDK) の Ac97 サンプル ドライバーは、この原理を示しています。 IPortWavePciStream::GetMapping または IPortWavePciStream::ReleaseMapping を呼び出す前に、サンプル ドライバーは KeReleaseSpinLock を呼び出してスピン ロックを解放します。 GetMapping または ReleaseMapping 呼び出しが返された後、ドライバーは KeAcquireSpinLock を呼び出してスピン ロックを再度取得します。 スピン ロックの解放と取得の呼び出しの間、ドライバー スレッドはマッピングのリストに排他的にアクセスできると想定してはなりません。 この保護されていない期間に共有データにアクセスすることは危険です。 スピン ロックの解放と取得の間の間隔が短い場合、2 つのドライバー スレッド間の競合状態によってデータが破損する可能性も低くなります。 これは、結果として生じる障害が断続的であるため、追跡が困難であることを意味します。 スピン ロックを解放して取得した後、適切に作成されたドライバーは、共有データ構造のコンテンツにアクセスするために以前に使用していた一時ポインターまたはインデックスが無効になっていると想定する必要があります。
IRP のキャンセル
再生またはキャプチャ ストリームの処理中のいつでも、IRP をキャンセルすると、オペレーティング システムがミニポート ドライバーが取得した 1 つ以上のマッピングを取り消す可能性があります。 これが発生すると、ポート ドライバーは IMiniportWavePciStream::RevokeMappings 方式を呼び出して、ミニポート ドライバーに通知します。 取り消されたマッピングからのデータの再生や、取り消されたマッピングへのデータのキャプチャを回避するには、ミニポート ドライバーはソフトウェア リストと DMA コントローラーのハードウェア キューの両方からマッピングを削除する必要があります。 ソフトウェア リストとハードウェア キューはドライバー スレッド間で共有されるため、これらの操作を確実に実行するにはある程度の注意が必要です。
たとえば、取り消されるマッピングのセットには、リリースされたばかり、またはリリースされようとしているマッピングが含まれる場合があります。 この場合、2 つのドライバー スレッドが同時に DMA キューから同じマッピングを削除しようとする可能性があります。 ドライバーが同時アクセスを防止できなかった場合、キューを管理するレジスターまたはメモリー構造内のデータが破損する可能性があります。
動作するコード例については、Windows Driver Kit (WDK) の Ac97 サンプル ドライバーを参照してください。