LTSLEEP(9) NetBSD Kernel Developer's Manual LTSLEEP(9) 名称 ltsleep, tsleep, wakeup -- プロセスコンテキスト sleep と wakeup 書式 #include int ltsleep(const void *ident, int priority, const char *wmesg, int timo, __volatile struct simplelock *slock); int tsleep(const void *ident, int priority, const char *wmesg, int timo); void wakeup(const void *ident); 解説 これらの関数は自発的な(voluntary)コンテキスト切替え(context switching)を実現します。ltsleep() と tsleep() は、次に挙げる理由 により現在のコンテキストの実行が中断する場合に、カーネルの至ると ころで呼び出されます。 o カレントプロセスが、時間がかかる I/O 処理の結果を待つ必 要がある。 o カレントプロセスが、(メモリ等の)資源を必要としているが、 一時的に利用できない状況にある。 o カレントプロセスが、他のプロセスによってロックされたデー タ構造にアクセスする必要がある。 wakeup() 関数はスリープ中のプロセスに対して、スリープの起因となっ た状況に変化が生じた可能性を伝えるために使用されます。一般に起こ された側のプロセスは -- コンテキストを再取得した時点で -- それが ブロックされている処理を再開するために、起因となる状況がクリアさ れたかどうかを調べます。 ltsleep() 関数は次の引数をとります。 ident カレントプロセスが待たなければならない資源を象徴する ``待機チャンネル(wait channel)'' の識別子です。一般に、 プロセスが競合している資源に関係した、カーネルデータ構 造の仮想アドレスが使用されます。プロセスを再開するため に wakeup() を呼び出すとき、同じ識別子を使用しなければ なりません。ident は NULL であってはいけません。 priority プロセスが起こされて実行可能プロセスのキューに追加され る時に参照される優先度です。この仕組みはカーネルモード で実行中の多数のプロセスの``スループット''を最適化する ために使用されます。priority に PCATCH フラグを OR (論 理和) した場合、プロセスはスリープに入る前後で、シグナ ルを受けたかどうか調べます。priority に PNORELOCK を OR した場合、slock はプロセスが復帰後に再ロックしません。 wmesg スリープの起因となった文字列へのポインタです。カーネル はこの文字列を使用しませんが、(process 構造体の p_wmesg フィールド経由で) ps(1) 等ユーザレベルのユーティリティ から参照可能です。 timo 0 でなければ、プロセスは最大 timo/hz 秒スリープします。 その時間が経過した時点で、wakeup(ident) が実行されておらず、 (PCATCH がセットされていて)シグナルも受けていなければ、 tsleep() は EWOULDBLOCK を返します。 slock NULL でなければ、スケジューラロックが獲得された時、 slock インターロックを一度アンロックします。PNORELOC が セットされていないならば、スリープから復帰した時 slock は再びロックされます。これは wakeup-before-sleep コンディ ションを防ぐための機能です。 tsleep() マクロは以下と同等です。 ltsleep(ident, priority, wmesg, timo, NULL) wakeup() 関数は、識別子 ident を持ってスリープ中の全プロセスに対 して実行可能のマークを付けます。最終的には、各プロセスはカーネル コンテキストで実行を再開し、tsleep() から復帰します。スリープから 復帰したプロセスは、ブロックの起因となった状況を常に再確認すべき です。なぜなら wakeup() の呼び出しは、ただ単にブロック状況が変化 したという通知に過ぎないからです。例えば、2 つ以上のプロセスが排 他的アクセスロック(lock(9) 参照)を待っている場合、ロックが解除さ れた時、次のロック獲得に成功するのは、ただ一つのプロセスだけです。 他のプロセスは、スリープに戻って、次の機会を待たなければなりませ ん。 戻り値 ltsleep() は wakeup() によって起こされた場合は 0 を返します。シグ ナルによって起こされた場合、シグナルが SA_RESTART 属性 (sigaction(2) を参照)を持っているならば ERESTART を、持っていなけ れば EINTR を返します。タイムアウトの場合、EWOULDBLOCK を返します。 関連項目 sigaction(2), hz(9), lock(9) 歴史 sleep/wakeup によるプロセス同期メカニズムは大変古いものです。ごく 初期の Unix で登場しました。tsleep() は 4.4BSD で登場しました。 ltsleep は NetBSD 1.5 で登場しました。 NetBSD 3.1 April 11, 2003 NetBSD 3.1 $Id: tsleep.0,v 1.3 2007/07/12 02:50:00 candy Exp candy $