同期と排他

割り込み関連を色々見ていく中で、その前の章 (3 章) の「同期と排他」の部分の理解が微妙な気がしてきた。ので、教科書以外の書籍等にも再度目を通しつつ整理してみた。
amazon:詳解 Linux カーネルによると_リエントラント_という言葉が出てくる。そこには「つまり、同時に複数のプロセスをカーネルモードで実行することがあります。」(amazon:詳解 Linux カーネルより引用)とある。複数のプロセスを同時に実行して矛盾が生じない、という意味でリエントラントを実現する方法の一つとして以下の記述がある。

リエントラント性を実現する方法のひとつは、ローカル変数だけを変更し、グローバル変数は変更しないような関数を書くことです。

(amazon:詳解 Linux カーネルより引用)
似たような記述を見たような気がするなぁ、と思ってたらやはりamazon:Linux カーネル解析入門にも切り口は異なるけれども同様の意図な記述が 3-1 コンテキストを理解する にあった。
グローバル変数を何かの形で限定して変更する、という事とリソースの競合を避ける、という事はおおざっぱに言って同一の意味を示すと判断して構わんハズ。
で、こうした競合した状態 (race condition ) を避けるためにカーネル的ないくつかの手法を用意しているとの事。
基本的な解としては、1 ステップの命令で何とかなりそうなナニ (グローバル変数への代入等) とそれ以外、という切り分けをしている模様。amazon:詳解 Linux カーネルでは以下の切り分けをしている。

  • アトミックな操作 (atomic operation)
  • クリティカルリージョン (critical region)

カーネルがリエントラントな状態を保つためにどのようなテクを使っているか、もう少し整理してみると、amazon:詳解 Linux カーネルでは以下の方法との説明あり。

  • カーネルモードプロセスのノンプリエンティブ性
  • アトミック操作 (不可分操作)
  • 割り込みの禁止
  • ロック


amazon:詳解 Linux カーネルより引用<余談>
アトミックって何だよ、と言っててフォローまで頂いていたナニが出てきた。ぢつは、amazon:Linux カーネル解析入門にも atomic_inc なナニが出ているのを発見。ページが薄めだからサンプルで紹介しているアレについてもポイント高いものを使ったんだろな、と。
この「同期と排他」って部分はきちんと理解しておく必要があるな、と思うのでもう少し整理してみたいな、と。

追記

リエントラント、について IBMdeveloperWorks に良い文章を発見。自分の参考として以下に引用しておく。

再入可能(reentrant)なファンクションというのは、同時に一つ以上のタスクが、(データが改変されることを心配せず)並行して使うことのできるものを言います。逆に再入不可(non-reentrant)のファンクションというのは、一つ以上のタスクで共有することができないものです。共有するためには、セマフォーを使うことによって、あるいは重要なコード部分の実行中には割り込みを不可とすることによって、相互排除が保証されている必要があります。再入可能なファンクションには、任意の時に割り込むことができ、データを失うことなく後から処理を続行できます。再入可能なファンクションであれば、ローカル変数を使うか、あるいはグローバル変数を使用している場合にはデータを保護するようになっています。
再入可能なファンクションは、

  • 連続的なコールに対して静的データを保持せず、
  • 静的データに対するポインターを戻さず(すべてのデータはファンクションを呼び出す側が提供する)、
  • ローカル・データを使う、あるいはグローバル・データの場合はそのローカル・コピーを作ることで確実に保護し、
  • 再入不可のファンクションを呼んではなりません。

再入可能とスレッド・セーフとを混同しないでください。プログラマーの観点からは、これらは別々の概念です。ファンクションは再入可能であることもでき、スレッド・セーフであることもでき、その両方であることもでき、どちらでもない、ということも可能です。再入不可のファンクションを、複数のスレッドが使うことはできません。さらに、再入不可のファンクションをスレッド・セーフにすることもできません。
IBM Linux:安全なシグナル処理のために再入可能ファンクションを使うより引用

引用多いな ...