仕組みは単純です。
プロセスA,Bがミューテックスセマフォを介して結合されると、それぞれの優先度に関係なく相手の実行をブロックしてしまうのです。
たとえば、Aが最高優先度のデータ処理プロセス、Bが最低優先度の画面表示系だとします。
処理されたデータをグローバル変数で受け渡すなら、ミューテックスセマフォで保護するのは当然のことです。
Bが先にセマフォをtakeした場合、Aはセマフォをtakeしようとしたところでブロックされます。
このとき優先度は関係ありません。
もし、Bがセマフォをgiveしないで、別の中優先度のプロセスCが実行可能状態になったらどうでしょうか。Bが次に実行可能となるのは、Bよりも高い優先度を持つすべてのプロセスが待ち状態になるときです。
思い出してください。Bは画面表示プロセスで、「たのプロセスを邪魔にしないように」低い優先度を与えているのです。ということはつまり、相当時間が経たないとBにCPUは回ってきません。
しかしそれで無限に待たされることもないはずです。いずれはBにCPUが回ってきて、セマフォはgiveされます。
しかし、プロセスAは最高優先度にも関わらず、「B以外のすべてのプロセスの仕事が済んでから」でないとセマフォをtakeできないのです。
この厄介な現象は、Bがセマフォをtakeしてgiveするまでの間に、Aがセマフォをtakeしようとしたときに起こります。そんな微妙なタイミングが頻繁に奇怪な現象を引き起こすのには理由があります。
図で書けばごくごく短いじかんのはずで、発生確率は隕石がフライドチキンの店の看板を打ち抜くほど低そうにみえるのです。ですが、経験的に以下のようなことが原因となって、おこりにくいはずのことがしょっちゅう起こります。
- Bは最低優先度なのでのっそり動く(危険期間の拡大)
- Aは最高優先度なのですばやく動く
解決するには、A→Bにはリングバッファを設置すればよいだけです。すべてのデータを取りこぼしてはいけない画面表示なんてありえません。
FIFO/キューを設置してはいけません。間接的にセマフォを介するのと同じだからです。
コメント