優先順位の逆転はよくある、やや古い問題です。特にリアルタイム要件がある場合、OS プロセスのスケジューリングを扱った人はそれに精通しています。この問題に対するよく知られた解決策はほとんどなく、それぞれに長所と短所があります。
- 重要なセクションを保護するためにすべての割り込みを無効にする
- 優先度の上限
- 優先継承
- ランダムブースティング
優先順位の逆転に対処するためにどの方法を選択してもかまいません。アプリケーションが共有リソースを同期するために明確に定義されたインターフェイスを使用することを考えると、これらはすべて OS カーネルに比較的簡単に実装できます。たとえば、プロセスが などを使用してミューテックスをロックする場合、pthread_mutex_lock
OS はその事実を十分に認識しています。これは、この関数がシステム コールを実行するためです (つまりfutex
、Linux 上で)。カーネルがこの要求を処理すると、誰が何を待っているかを完全かつ明確に把握し、優先順位の逆転を最適に処理する方法を決定できます。
ここで、プロセスがいつミューテックスをロック/ロック解除しているのかをカーネルが認識していないと想像してください。これは、たとえば、アトミック CPU 命令を使用してミューテックスを実装する場合に発生する可能性があります (「ロックフリー」アルゴリズムなど)。次に、優先度の低いプロセスがロックを取得し、優先度の高いタスクのために実行が中断される可能性があります。次に、優先度の高いタスクがスケジュールされると、「スピンロック」をロックしようとして CPU を焼き尽くすだけです。そのようなデッドロックは、システム全体を役に立たなくします。
上記のシナリオと、共有リソースへのアクセスを同期するためにアトミック操作を使用しないようにプログラムを変更できないという事実を考えると、問題は、コードがそうしようとしているときにそれを検出することに要約されます。
実装が難しく、誤検知を引き起こす可能性のある、やや漠然としたヒューリスティックなアイデアがいくつかありました。どうぞ:
- ときどきプログラム カウンターレジスタを見て、コードがタイトなループで CPU を焼き尽くしていることを検出してみてください。コードがその場所で N 回発見された場合、プロセスを一時停止し、他の優先度の低いプロセスを実行してミューテックスのロックを解除できるようにします。この方法は理想からかけ離れており、誤検知が多すぎる可能性があります。
- プロセスを実行できる時間に厳密な制限を設けます。これにより、スケジューラのハード リアルタイム機能がすぐに失われますが、機能する可能性があります。ただし、問題は、「デッドロック」の場合、優先度の高いプロセスが使用中のリソースを取得しようとしてすべての時間枠を浪費することです。
- これが可能かどうかはわかりませんが、別のアイデアは、アトミック CPU 命令を傍受/挿入して、スケジューラにロック/ロック解除の試みを認識させることです。言い換えれば、基本的にアトミック CPU 操作をある種のシステム コールに変換します。そのメカニズムは、MMU がページ フォールトを通知したときに仮想ページ マッピングが作成される方法にいくらか近いものです。
上記のアイデアについてどう思いますか?そのようなコードを検出する他の方法を考えてみてください。