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

名称

msleep, msleep_sbt, msleep_spin, msleep_spin_sbt, pause, pause_sbt, tsleep, tsleep_sbt, wakeupイベントのウェート (wait)

書式

#include < sys/param.h>
#include < sys/systm.h>
#include < sys/proc.h>

int
msleep( void *chan, struct mtx *mtx, int priority, const char *wmesg, int timo);

int
msleep_sbt( void *chan, struct mtx *mtx, int priority, const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags);

int
msleep_spin( void *chan, struct mtx *mtx, const char *wmesg, int timo);

int
msleep_spin_sbt( void *chan, struct mtx *mtx, const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags);

void
pause( const char *wmesg, int timo);

void
pause_sbt( const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags);

int
tsleep( void *chan, int priority, const char *wmesg, int timo);

int
tsleep_sbt( void *chan, int priority, const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags);

void
wakeup( void *chan);

void
wakeup_one( void *chan);

解説

関数 tsleep(), msleep(), msleep_spin(), pause(), wakeup() と wakeup_one() は、イベントに基づいたスレッドのブロッキングを取り扱います。スレッドが外部のイベントを待たなければならないなら、それは、 tsleep(), msleep(), msleep_spin(), または pause() によってスリープ状態に置かれます。また、スレッドは、ロックの基本的なスリープルーチン mtx_sleep(9), rw_sleep(9) または sx_sleep(9) の 1 つを使用してウェートされます。

パラメータ chan は、スレッドがスリープ状態に置かれているイベントを識別するユニークな任意のアドレスです。単一の chan でスリープしているすべてのスレッドは、 wakeup() によって後で起こされ、スレッドがブロックされているリソースが現在利用可能であることを示すために、割り込みルーチンの中からしばしば呼び出されます。

パラメータ priority は、いくつかのオプションのフラグと同様にスレッドのための新しい優先権を指定します。新しい優先権が 0 でないなら、スレッドは、再開するとき、指定された priority で実行可能とされます。 PZERO は、互換性のためだけであるので、決して使用されるべきではありません。 0 の新しい優先権は、再び実行可能とするとき、スレッドの現在の優先権を使用することを意味します。

priorityPCATCH フラグを含んでいるなら、保留中のシグナルは、スリープを割り込むことが許可され、そうでなければ、保留中のシグナルは、スリープの間無視されます。 PCATCH が設定され、シグナルが保留中になり、現在のシステムコールが再開されるべきであり、可能であるなら、 ERESTART が返され、システムコールが ( EINTR を返えす) シグナルによって割り込まれるべきであるなら、 EINTR が返されます。 PBDRY フラグが PCATCH に加えて指定されるなら、スリープしているスレッドは、 SIGSTOP が保留中になるか、またはスリープしている間にある他の停止動作が起こるとき、停止されません。代わりに、ユーザモードに戻るとき、停止ポイントに到達する時点で停止が起こると仮定して起こされます。フラグは、スリープしているスレッドがリソース、例えば、タイムリな方法で解放されるべきである vnode ロックを所有しているとき、使用されるべきです。

パラメータ wmesg は、 ps(1) のようなツールのためのスリープ状態について説明する文字列です。任意の文字列を表示するためのそれらのプログラムの制限された空間のために、このメッセージは、6 文字より長くなるべきではありません。

パラメータ timo は、スリープのタイムアウトを指定します。 timo が 0 でないなら、スレッドは、多くても timo / hz 秒の間スリープします。タイムアウトの期限が切れるなら、スリープ関数は、 EWOULDBLOCK を返します。

msleep_sbt(), msleep_spin_sbt(), pause_sbt() と tsleep_sbt() 関数は、 timo の代わりに sbt 引数を取ります。それによって、呼び出し側は、 sbintime_t の形式のより高い解像度で相対的または絶対的な起きる (wakeup) 時間を指定することができます。パラメータ pr によって、呼び出し側は、必要とされる絶対的なイベント正確さを指定することができます。パラメータ flags によって、呼び出し側は、追加の callout_reset_sbt() フラグを渡すことができます。

msleep(), msleep_spin() を含むスリープ関数のいくつかとロックを行う基本的なスリープルーチンは、追加のロックパラメータを指定します。ロックは、スリープの前に解放され、スリープルーチンが戻る前に、再獲得されます。 priorityPDROP フラグを含んでいるなら、ロックは、戻る前に再獲得されません。ロックは、不可分に状態をチェックすることができ、状態への変化、または関連するウェークアップ (wakeup) を逃さずに現在のスレッドをサスペンドすることができることを保証するために使用されます。さらに、すべてのスリープルーチンは、スレッドがサスペンドされている間に (繰り返されたとしても) Giant mutex (ミューテックス) を完全に落として、関数が戻る前に Giant mutex を再獲得します。 Giant mutex が落されるロックとして指定されることに注意してください。しかしながら、その場合には、 PDROP フラグは、許可されません。

失われたウェークアップ (wakeup) を避けるために、ロックが競合から守るために使用されるべきであるか、またはタイムアウトが、失われたウェークアップ (wakeup) のためにディレー (遅れ) の上限に置くために指定されるべきです。結果として、 tsleep() 関数は、 Giant mutex が保持されているときのみ、0 のタイムアウトで呼び出されるべきです。

msleep() 関数は、 mtx がデフォルト、すなわち、non-spin, mutex、を参照することを必要とします。その使用は、同一の振る舞いを提供する mtx_sleep(9) を支持して非推奨です。

msleep_spin() 関数は、 mtx が、spin mutex を参照することを必要とします。 msleep_spin() 関数は、 priority パラメータを受け付けません、したがって、現在のスレッドの優先権の変更、 PDROP フラグ、または PCATCH フラグを通してシグナルのキャッチは、サポートしません。

pause() 関数は、示されたタイムアウトのための現在のスレッドの実行をサスペンドさせる tsleep() 周りのラッパです。シグナル、または wakeup() または wakeup_one() への呼び出しによって早期にスレッドを起こすことができません。

wakeup_one() 関数は、パラメータ chan でスリープしているキューの中の最初のスレッドを実行可能とします。これは、多くのスレッドが同じアドレスでスリープしていいるとき、ロードを減少させますが、実行可能とされるとき、それらの 1 つだけが、実際に役に立つ作業を行うことができます。

それが動作している方法のために、 wakeup_one() 関数は、関連するスレッドだけが特定の chan アドレスでスリープすることを必要とします。ユニークな chan 値を選択することは、プログラマの責任です。より古い wakeup() 関数は、これを必要としませんでした、しかしながら、 chan 値を共有するスレッドのために決して良い習慣ではありませんでした。 wakeup() から wakeup_one() まで変換するとき、同じ chan でウェートしている他のスレッドがないことを保証するために特別の注意を払ってください。

戻り値

wakeup() と wakeup_one() への呼び出しで起こされるとき、シグナルが保留中 (pending) であり、 PCATCH が指定されるなら、0 以外のエラーコードが返されます。スレッドが wakeup() または wakeup_one() への呼び出しで起こされるなら、 msleep(), msleep_spin(), tsleep() とロックがある基本的なスリープ関数は、0 を返します。そうでなければ、0 以外のエラーコードが返されます。

エラー

msleep(), msleep_spin(), tsleep() とロックがある基本的なスリープ関数は、次の場合に失敗します:
[ EINTR]
PCATCH フラグが指定され、シグナルがキャッチされ、システムコールは、割り込まれるべきです。
[ ERESTART]
PCATCH フラグが指定され、シグナルがキャッチされ、システムコールは、再開されるべきです。
[ EWOULDBLOCK]
0 以外のタイムアウトが指定され、タイムアウトは、期限が切れました。

歴史

関数 sleep() と wakeup() は、 Version 1 AT&T UNIX に存在していました。それらは、たぶん UNIX の前の PDP-7 バージョンも存在していました。それらは、基本的なプロセス同期モデルでした。

tsleep() 関数は、 4.4BSD で登場し、パラメータ wmesgtimo を追加しました。 sleep() 関数は、 FreeBSD 2.2 で削除されました。 wakeup_one() 関数は、 FreeBSD 2.2 で登場しました。 msleep() 関数は、 FreeBSD 5.0 で登場し、 msleep_spin() 関数は、 FreeBSD 6.2 で登場しました。 pause() 関数は、 FreeBSD 7.0 で登場しました。

作者

このマニュアルページは、 Jörg Wunsch <joerg@FreeBSD.org>によって書かれました。
February 19, 2013 FreeBSD