sti は誰が、のオチ

オチてはいないんですが。(謎
sti は誰が とか ううむ (割り込みの禁止関連) などというエントリにおいて相当無謀な_根拠を元にしない_キチガイ発信を不憫に思ったひらたさんからの優しいフォローが今さらながらにありがたい。

まず、local_irq_save マクロを以下に再度引用 (include/asm-i386/system.h)

#define local_irq_save(x) \
__asm__ __volatile__("pushfl ; popl %0 ; cli" \
                     :"=g" (x) \
                     : /* no input */ \
                     :"memory")

ちなみに

  • __asm__
  • __volatile__
  • :"memory"

な根拠は保留 (こら

    1. まず pushfl で EFLAGS レジスタをスタックに push
    2. 次に x にスタックから pop した値を格納
    3. その後 cli を発行して EFLAGS レジスタの IF をクリア

IF が 0 (クリアな状態) でマスク可能割り込みへの応答が禁止され、1 (セットされた状態) でマスク可能割り込みに応答する、との事。どこかのドキュメントに可読性な話が出ていましたが、こうした仕様を理解していないと set/clear の意味をとり違えてしまうヤカラが出てきちゃうんでしょうね。(ってわしがそうだったんですが

で、上記処理でポイント高いのが、cli する前の状態を保存している、という部分。

cli発行する前が、すでに割り込み禁止状態になっているかもしれないので、stiしてしまうと、割り込み許可状態になってしまいますね。
ひらたさんから頂いたコメントより引用

という言葉の根拠は上記処理の順番によるんだな、と。ただ、_すでに割り込み禁止状態になっているかもしれない_のはどんな時なんだろうか、という事が気になる。ただ、こうした状態については、今後見ていく内に明らかになっていくのだろうな、とも思う。

蛇足になるかもしれませんが local_irq_restore についても再度フォロー (include/asm-i386/system.h)

#define local_irq_restore(x) \
do { \
    typecheck(unsigned long,x); \
    __asm__ __volatile__("pushl %0 ; popfl" \
                          : /* no output */ \
                          :"g" (x) \
                          :"memory", "cc"); \
} while (0)
  • typecheck もマクロです。local_irq_restore マクロの引数の型が unsigned long でなかった場合、コンパイルエラーとなります。
  • __asm__
  • __volatile__
  • "memory"

に加え

  • "cc" についても根拠保留。TODO 多スギ

処理としては

  1. マクロの引数 x をスタックに push
  2. スタックから pop したナニを EFLAGS レジスタに設定

となります。

インライン・アセンブラが読めるように云々とエントリに入れているんですが、特にアセンブラなんていうナニはハードの仕様書読めてないと駄目ってコトで。そしてワケワカな解をスケジューラに求めてしまったのも、自分ながらに微妙スギだなぁ。

インテルのマニュアルですが下巻はきちんと読んだ方が良さげ。他は根拠を求めるための資料だろな。

そういえば、pushfl とか popfl なんてゆー命令について gas なナニを探したんですが、インターネトには関連情報にヒットせず。アセンブラなアレにも intel® なナニにも pushf + l な l についての情報ナシ。とりあえずコンパイルしてアセンブラなコードやらオブジェクトやらを確認したトコロ、pushf とか popf に翻訳されている模様。

コメントを入れてくれる人とその環境に恵まれている事を感謝しつつ。