EN JA
SPL(9)
SPL(9) FreeBSD Kernel Developer's Manual SPL(9)

名称

splbio, splclock, splhigh, splimp, splnet, splsoftclock, splsofttty, splstatclock, spltty, splvm, spl0, splx割り込み優先度の操作

書式

#include < sys/types.h>
#include < sys/systm.h>

intrmask_t
splbio( void);

intrmask_t
splclock( void);

intrmask_t
splhigh( void);

intrmask_t
splimp( void);

intrmask_t
splnet( void);

intrmask_t
splsoftclock( void);

intrmask_t
splsofttty( void);

intrmask_t
splstatclock( void);

intrmask_t
spltty( void);

void
spl0( void);

void
splx( intrmask_t ipl);

解説

この API は推奨されていません。データ構造を保護するためには、代わりに mutex を使用します。詳細情報は mutex(9) を参照してください。現在、この API は、完全に NOP です。 FreeBSD 5.0 より前のカーネルのバージョンからコードを変換するとき、利用者が、spl が行ったコードロックを理解できるように、このマニュアルページは、歴史的な振る舞いを文書化しています。また、このマニュアルページの例は、時代遅れであり、 FreeBSD 5.0 より新しい文書化されたものとして見るべきではありません。

spl() 関数ファミリは CPU の割り込み優先度の“レベル”を設定します。これはブロックされた優先度レベルの割り込みハンドラの実行を抑制します。割り込みハンドラによって調査あるいは修正されたであろうデータ領域を調査あるいは修正するドライバの“synchronous”部分 (ユーザプロセスを代表して実行される部分) で使用されます。

通常それぞれの割り込みを使用するドライバは、 config ファイルのキーワードによって 1 つの割り込み優先度グループに割り当てられます。例えば、

device foo0 at isa? port 0x0815 irq 12 tty

は、割り込み 12 を“tty”優先度グループに割り当てます。システムは自動的に xxx グループの割り込みを優先度が splxxx() 以上の時に呼ばれるように準備します。

splx() 関数は割り込み優先度レベルを絶対的な数値に設定します。これは別の割り込みレベル関数が返した値をローカルの変数に保存して、後で元の優先度レベルに戻すために splx() を使用する事を意図しています。

spl0() 関数は全ての割り込みハンドラをブロックしない値に優先度を減少させます。ただし、AST (非同期システムトラップ) はシステムがユーザモードに戻るまでの間はブロックされます。

いろいろなデバイスドライバの割り込み優先度グループの伝統的な割り当ては、おおよそ次のように分類できます。

splnet()
ネットワークインタフェースドライバのソフトウェア部分。
splimp()
全てのネットワークインタフェースドライバ。
splbio()
全ての バッファ入出力 (つまりディスクなど) のドライバ。
spltty()
基本的にはネットワーク以外の通信デバイスですが、事実上はネットワークとディスク以外の全てのドライバ。

戻り値

splx() および spl0() 以外の全ての関数は、操作前の優先度の値を返します。

使用例

以下は、標準的な使用例です。

struct foo_softc { 
 ... 
 int flags; 
#define FOO_ASLEEP 1 
#define FOO_READY 2 
 
} foo_softc[NFOO]; 
 
int 
foowrite(...) 
{ 
 struct foo_softc *sc; 
 int s, error; 
 
 ... 
 s = spltty(); 
 if (!(sc->flags & FOO_READY)) { 
  /* 準備ができていません、待機しなければなりません */ 
  sc->flags |= FOO_ASLEEP; 
  error = tsleep(sc, PZERO, "foordy", 0); 
  sc->flags &= ~FOO_ASLEEP; 
 } 
 sc->flags &= ~FOO_READY; 
 splx(s); 
 
 ... 
} 
 
void 
foointr(...) 
{ 
 struct foo_softc *sc; 
 
 ... 
 sc->flags |= FOO_READY; 
 if (sc->flags & FOO_ASLEEP) 
  /* 誰かが我々を待っています、起こしてください */ 
  wakeup(sc); 
 ... 
} 

割り込みハンドラは、 絶対に 優先度レベルを減少させるべきではない、ということに注意してください。自動的に、自分のレベルの割り込み優先度に増加させられます。すなわち、同じグループの全ての割り込みはブロックされます。

歴史

割り込み優先度レベルは早期のバージョンの UNIX で登場しました。伝統的には名前ではなく数字が使われていて、そのレベルまでの全てを含んで (優先度 5 はレベル 5 までの全てをブロックします) いた事が知られています。これは FreeBSD にはあてはまりません。伝統的な名前‘ level’はいまだに文字‘ l’としてそれぞれの関数や変数の名前に反映されています。しかし、実際にはもはやレベルではなく、むしろ異なった (部分的に含まれた) 関数群がシステムのある期間ブロックされます。歴史的な番号による方法は単純で順番通りの割り込み優先度レベルグループであるとみなす事ができます。

2 つ以上のプロセッサの規模のロックする基本関数を支持して FreeBSD 5.0 は、 spl を完全に排除しました。

作者

このマニュアルページは Jörg Wunsch によって書かれました。
July 21, 1996 FreeBSD