spinlock.c void popcli(void)
トップページ
jupiteroak.hatenablog.com
spinlock.c
https://github.com/mit-pdos/xv6-public/blob/master/spinlock.c#L116
void popcli(void) { if(readeflags()&FL_IF) panic("popcli - interruptible"); if(--mycpu()->ncli < 0) panic("popcli"); if(mycpu()->ncli == 0 && mycpu()->intena) sti(); }
popcli関数は、クリティカルセクションのネストに対応しながら、割り込みを許可します。
処理の内容
ハードウェア割り込みが無効化されていることを確認する
if(readeflags()&FL_IF) panic("popcli - interruptible");
readeflags関数を呼び出して取得したEFLFGSレジスタの値をFL_IF(#define FL_IF 0x0000 0200)を使ってマスク処理することにより、EFLFGSレジスタのIF(bit9 インターラプトエネーブルフラグ)の値を取り出しています。
readeflags()&FL_IFが真の場合→IFの値が1の場合→ハードウェア割り込みを有効化している場合は、panic関数を呼び出してメッセージを出力します。
readeflags()&FL_IFが偽の場合→IFの値が0の場合→ハードウェア割り込みを無効化している場合は、次の処理へ進みます。
ハードウェア割り込みを禁止した回数を減らす
if(--mycpu()->ncli < 0) panic("popcli");
mycpu関数を呼び出して、mycpu関数を現在実行しているプロセッサ(スレッド)に対応しているcpu構造体を取得します。
cpu構造体のncliメンバには、puchi関数の呼び出し回数(ネストの深さ)が記録されています。
ncliメンバを前置ディクリメントし(ncliメンバの値を評価前に1減らす)、その結果が0より小さい場合は、panic関数を呼び出してメッセージを出力します。