| 総合手引 | セクション 9 | オプション |
#include <sys/types.h>
#include <sys/systm.h>
spl() 関数ファミリは CPU の割り込み優先度の "レベル" を設定します。 これはブロックされた優先度レベルの割り込みハンドラの実行を抑制します。 割り込みハンドラによって調査あるいは修正されたであろうデータ領域を 調査あるいは修正するドライバの "synchronous" 部分(ユーザプロセスを代表して実行される部分)で使用されます。
通常それぞれの割り込みを使用するドライバは、 config ファイルのキーワードによって 1 つの 割り込み優先度グループに割り当てられます。 例えば、
device foo0 at isa? port 0x0815 irq 12 tty
は、割り込み 12 を "tty" 優先度グループに割り当てます。 システムは自動的に xxx グループの割り込みを優先度が spl xxx amp;() 以上の時に呼ばれるように準備します。
splx() 関数は割り込み優先度レベルを絶対的な数値に設定します。 これは別の割り込みレベル関数が返した値をローカルの変数に保存して、 後で元の優先度レベルに戻すために splx() を使用する事を意図しています。
spl0() 関数は全ての割り込みハンドラをブロックしない値に優先度を減少させます。 ただし、AST(非同期システムトラップ)はシステムが ユーザモードに戻るまでの間はブロックされます。
いろいろなデバイスドライバの割り込み優先度グループの伝統的な割り当ては、 おおよそ次のように分類できます。
| splnet() | |
| ネットワークインタフェースドライバのソフトウェア部分。 | |
| splimp() | |
| 全てのネットワークインタフェースドライバ。 | |
| splbio() | |
| 全ての バッファ入出力 (つまりディスクなど)のドライバ。 | |
| spltty() | |
| 基本的にはネットワーク以外の通信デバイスですが、 事実上はネットワークとディスク以外の全てのドライバ。 | |
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);
...
}
割り込みハンドラは
絶対に
優先度レベルを減少させるべきではない、ということに注意してください。
自動的に、自分のレベルの割り込み優先度に増加させられます。
すなわち、同じグループの全ての割り込みはブロックされます。
| SPL (9) | July 21, 1996 |
| 総合手引 | セクション 9 | オプション |
このマニュアルページサービスについてのご意見は Ben Bullock にお知らせください。 Privacy policy.
| “ | I think Unix and snowflakes are the only two classes of objects in the universe in which no two instances ever match exactly. | ” |
| — Noel Chiappa | ||