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関数を呼び出してメッセージを出力します。

ハードウェア割り込みを有効化する

if(mycpu()->ncli == 0 && mycpu()->intena)
   sti();

cpu構造体のncliメンバの値が0の場合→pushcli関数の呼び出しがネストしていない場合、かつ、cpu構造体のintenaメンバの値が0ではない場合→pushcli関数を呼び出す前のEFLFGSレジスタのbit9(IF:インターラプトエネーブルフラグ)の値が1だった場合→pushcli関数を呼び出す前にハードウェア割り込みが許可されていた場合は、sti関数を呼び出して割り込みを有効化します。