誰も知らないプリエンプション

  • 投稿日:
  • by
  • カテゴリ:



みんな腹の底では良く分かってなくて、曖昧なままに放置されている事柄が多数あります。たいていそういう話は、厳密に分かっていなくても誰も困らないし、実害もないので放置されるわけです。


聞くは一瞬の恥、聞かぬは一生の恥なんですがねぇ。



いまどきは、googleさんがいますので、ググれば恥にもならないわけです。それでも、ネット上の情報はアテにならないという、それ自身が迷信であるという逆説的なデッドロックで思考停止になっている人のいかに多いことか。



さて、スレッドやプロセス、μITRONのようなRTOSならタスクでもいいわけですが、そういうコンテキストがどういう条件で切り替わるかご存知ですか?つまりコンテキストスイッチの条件です。



現在実行中のスレッドよりも優先度の高いスレッド(コンテキスト)が実行可能状態になったら

ここまではどこへ行ってもコンセンサスがあります。実行可能状態というのは、セマフォスピンロックやなどで待っていない状態ですね。つまり暗黙的に上記の条件は、以下のように解釈されます。




  1. 優先度の高いスレッドAが実行中にセマフォで待ちになった。→実行中でなくなる

  2. 次に優先度の高いスレッドBが実行中になる。

  3. しばらくして、セマフォが解放されてスレッドAが実行中になる。


ここまでもご同意いただけると思います。問題は、3番目の、コンテキストスイッチが、具体的にいつ起こるかなのです。


ある人は、スレッドBがシステムコール(OSが用意した関数群)を呼び出して、カーネルに入り込まない限り、コンテキストスイッチは生じないと主張します。つまり、システムコールをまったく呼ばない実装になっているとコンテキストスイッチのタイミングがどんどん遅れると言うのです。(マジデスカ)


別の人は、カーネルが定期的にセマフォの状態を更新するので、そのタイミングでコンテキストスイッチが発生すると主張します。そんな話どこで聞いてきたのよ。


実は、TSSなしの単純なRTOSなら前者はかなり正解に近いです。しかしTSSなしでも割り込みはあります。割り込みハンドラ内でセマフォを解放する、というのはセマフォの典型的なサンプルです。ドライバは、セマフォを待ち、割り込み発生ごとに1回処理を進めます。ちょっと脱線しましたが、OSの割り込み処理はコンテキストスイッチの起こりうるタイミングです。


TSSはタイマー割り込みなので、同じことです。


というわけでコンテキストスイッチのタイミングは以下のようになります



  • システムコール呼び出し時

  • 割り込み発生時(ソフトウェア割り込み含む)


Linuxなどでは、システムコールから戻るとき、割り込みハンドラ終了時の処理でコンテキストスイッチを実行するようです。詳細は調べてください。




割り込みって何だっけ?という状態では、当然コンテキストスイッチについて理解できたことにはなりません。読んでると眠くなる情報処理の教科書には、どんなに薄っぺらくても割り込みのことが書いてあります。あれは無駄ではないのです。





(2008.02.16追記)


Windows3.1系では、明示的にyieldしてCPUを明け渡さないとスケジューラが走らないというツッコミがありました。なるほどプリエンプションがないならそうでしょうが、このエントリではコンテキストスイッチが知らない間に発生することとそれが発生する条件を説明しています。


明示的に指定しないといけないOS、もしかしたらしょうもないμITRONの実装もそうなっているかもしれませんが、において明示的にコンテキストスイッチを起こすための呼び出しが必須な状況で、このエントリで取り上げている話題が気になりますか?