do_IRQ 呼び出し以降の排他処理
割り込み処理の全体をざっくり見渡してみる。
__do_IRQ() の呼出し元の do_IRQ() では排他な手続きは行なっていないものと勝手読み。handle_IRQ_event() ではどうなっているか、という事も気になるんで無理矢理 inline で展開させてみた。
__do_IRQ() { spin_lock(&desc->lock); PIC に 割り込みマスク指示および EOI の送信 (EFLAGS の退避と復帰) (中略) for(多くて 2 回繰り返し) { spin_unlock(&desc->lock); action_ret = handle_IRQ_event(irq, regs, action); # 無理矢理 inline 展開してみたり (こら # inline 展開ココカラ if( action->flags が SA_INTERRUPT でない場合 ) local_irq_enable(); do { ret = action->handler(irq, action->dev_id, regs); action = action->next; } while (action が NULL でない間) local_irq_disable(); # inline 展開ココマデ spin_lock(&desc->lock); } PIC に割り込みアンマスク指示 (EFLAGS の退避と復帰) spin_unlock(&desc->lock); }
とりあえず UP で i8259A な環境を前提として意味を類推してみる前に ....
一点気になるのは、action->flags が SA_INTERRUPT でない場合の処理。ちなみに flags が SA_INTERRUPT な状態というのは、割り込みハンドラ内で別の割り込みに応答しないようにする、との情報あり。なので SA_INTERRUPT でない場合には sti するというのは理解できるんですが、どこで cli しているのでしょうか。ちなみに action->handler() を呼び出すループを脱出した時点で cli は実行。これもどこで sti するんだろう。
整理すると
- action->flags が SA_INTERRUPT な状態であれば別な割り込みに応答しない
うーむ。ワケワカ。
とりあえず、もっかいよく見てみる必要あり。PIC のマニュアルやら intel のマニュアルやらもよく見た方が良いかも、と思いつつ。(多分また何かをスッ飛ばしてるんだろな。とほほ)
キ※チガイなエントリになっているとは思いますが、思考の過程を残す、とゆーコトで勘弁して下さい。
追加で何点か気づいた点を列挙。
- 割り込みマスク〜アンマスク間では PIC 的に当該 IRQ 番号の割り込みが抑止されている状態。
- EFLAGS の IF がどういった状態で __do_IRQ() に飛んでくるのかが微妙。(これは上記の通り)
優先して調べてみる必要あり? - 異なる IRQ に割り込まれる可能性あり?(これも EFLAGS レジスタの IF の状態による)
- 割り込みマスク/アンマスク処理中に IRQ 番号ユニークなスピンロックで排他をかけている (割り込みマスク/アンマスクはポイント高い処理なので同一 IRQ な割り込みの発生の可能性を考慮して同期処理をしている?)
- action->handler() な処理の詳細はドライバのソースを読まんと分からん
追記
intel なマニュアルにヒントになりそうな記述 (上巻の 6.4.1.割り込み/例外処理プロシージャのコール操作とリターン操作) を発見。別途きちんと確認してみます。