割り込み処理の排他

linuxとしては、デバイスからの割り込みがどのCPUに入っても問題がないように作られており、複数の割り込みハンドラが別々のCPU上で動作する。割り込みハンドラ間で共有する資源がある場合、ハンドラ間で割り込みの排他を行う必要がある。

また、Linuxカーネル処理も複数のCPU上で並列動作するが、これらのカーネル処理からも上記資源を参照することがあり、その場合排他処理が必要となる。

排他処理動作の基本方針は以下の通りである。

  • 同じレベルのIRQレベルの割り込みハンドラはシステム上に一つしか 存在しないようにする。
    • 割り込みハンドラ実行中は、irq_descにIRQ_INPROGRESS フラグを立てる。
    • 割り込みが発生したとき、もしその発生したIRQレベルと 同じレベルの割り込みハンドラを実行しているCPUが存在 (irq_descにIRQ_INPROGRESSが立っている)した場合、 割り込みハンドラの実行を委ね (irq_descにIRQ_PENDINGフラグを立てる)、 そのCPUは何もせず割り込みから復帰する。
    • あるIRQレベルに対応した割り込みハンドラを実行しているCPUが 割り込みから復帰するとき、そのレベルに対する割り込み要求が 保留(irq_descのIRQ_PENDINGフラグ)になっていないかチェックを 行い、もし保留になっている場合再度同じIRQレベルの割り込みを 自CPUに強制的に発生させる(hw_resend_irq関数)。
img126.gif
  • 異なるレベルのIRQレベルのハンドラは、別CPU上で並列動作可能 とする(禁止しない)。ローカルCPUに対して異なるIRQレベルの 割り込みハンドラがネストすることも許す。
  • 異なるIRQレベルの割り込みハンドラ間で共有する資源、 および割り込みハンドラとLinuxカーネル本体処理とで 共有される資源の排他処理は、スピンロックを利用して行う。
    • 先に説明したspin_lock_irq()、spin_unlock_irq()関数を 利用する。他のCPU上で排他対象資源をアクセス中にその資源の ロックを行おうとした場合、ローカルCPUはそのロック解除を ビジーウェイトで待ち続ける。他のCPU上で排他対象資源を アクセスしているのがLinuxカーネル本体でも割り込みハンドラでも 同じである。また、ローカルCPU上で動作している処理が Linuxカーネル本体でも割り込みハンドラでも同様である。

また、Linuxカーネルはシステム全体の割り込みを全て禁止する方法も提供している。cli関数(global_cli関数)がその処理を行う。いづれかのCPUでこの関数が呼び出されると、システム上では割り込みハンドラおよび旧型のBHハンドラの実行は禁止される。他のCPUが割り込み禁止区間走行中に当CPUが割り込みを受けた場合、他のCPU上の割り込み禁止区間終了(sti...global_sti関数)を当CPUはビジーウェイトして待ち続ける。

逆に、他のCPUで割り込みハンドラの実行中の時は、当CPUは割り込み禁止区間に入ることはできず、当CPUはハンドラ終了を待ち続ける。

下図に、二つのCPU上での割り込みハンドラと割り込み禁止区間が相互に同期をとりながら実行する様子を示す。縦軸は時間を表し、時間の経過に従って下方向へ進んで行く。

img127.gif

 

(NIS)HirokazuTakahashi
2000年12月09日 (土) 23時55分06秒 JST
1