FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

MITのxv6を読もう - 第4章 ロック獲得時の割り込み処理(Interrupt handlers) -

6.828 / Fall 2014

ロックを獲得しているときに問題となるものとして、ロック最中に割り込みが発生したときについての説明だ。 ロックを獲得している最中に割り込みが発生して、その割り込みルーチンが同じロックを獲得しようとしていると、デッドロックになってしまう。

例えば、タイマ割り込みハンドラ(3364行目)はticksをインクリメントするが、他のCPUが同時にsys_sleepに入ると、その変数を利用する。 この場合は、tickslockロック変数により、2つのCPUが単一の変数にアクセスすることを防いでいる。

割り込みが発生してもデッドロックを発生させないためならば、プロセッサは逆に、ロックを獲得している最中に割り込みを許可してはならない。 xv6の実装としては、割り込み可能な状態では決してロックは獲得せず、割り込み禁止状態にしてからロックを獲得する、という機構になっている。

他にも、割り込み許可の状態を管理するために、割り込み不許可の操作をスタックで管理している。これがpushcliとpopcliである。 acquire関数はロックを獲得する前にpushcliを呼び出し、ロックを解放した後にpopcliを呼び出す。 この関数はカウントを行っており、pushcliを2回呼んだときに、popcliを2回呼び出すことによりその操作を取り消すことができる、というからくりだ。 この方法により、もしコードが2つの異なるロックを獲得すると、どちらのロックも解放されなければ割り込みが有効とはならない、従って、デッドロックが発生する可能性を除去する、という仕組みになっている。

あとは最後にメモリオーダリングについての説明もある (Memory Ordering)

プロセッサによっては、メモリのオーダリングの管理手法がまちまちなため、メモリアクセスがアウトオブオーダで実行された結果、誤った結果を招くことがある、という話。 アウトオブオーダであっても、メモリのストア操作については基本的にオーダを守るべきなのだが、もしメモリアクセスの順番が変わった場合、場合によってはデッドロックが発生する。

これを防ぐためには、やはりアトミック命令(x86ではxchg命令)を利用するのが最適だと思われる。アトミック命令はメモリからの読み込みとメモリへの書き込みを1命令内で分割されることなく実行するので、読み込みをしてから書き込みをするまでにメモリの内容が書き変わってしまう、ということはない。