TIMEOUT(9)

名称
timeout, untimeout, callout_handle_init, callout_init, callout_stop, callout_reset - 明示された時間長の後の関数の実行

書式
<sys/types.h> <sys/systm.h>

    typedef void timeout_t (void *);

struct callout_handle timeout(timeout_t *func, void *arg, int ticks) void callout_handle_init(struct callout_handle *handle)

    struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle)

void untimeout(timeout_t *func, void *arg, struct callout_handle handle) void callout_init(struct callout *c, int mpsafe) int callout_stop(struct callout *c) void callout_reset(struct callout *c, int ticks, timeout_t *func, void *arg)

解説
関数 timeout() は ticks/hz 秒後に実行されるための引数 func によって与えられる関数を呼び出すためのスケジュールを行います。 正ではない値の ticks は沈黙のうちに値 ‘1’ に変換されます。 func は void * の引数を取る関数へのポインタであるべきです。 実行時には、 func は arg をその唯一の引数として受け取ります。 timeout() からの戻り値は、スケージュールされた timeout を取り消す要求のための untimeout() 関数との接続に使用されることが可能な struct callout_handle です。 timeout() の呼び出しは古いスタイルで、新しいコードは callout_* 関数を使用するべきです。

関数 callout_handle_init() はハンドルを初期化するために使用し、untimeout と共に 使用されても副作用無しに戻るようにします。

コールアウトハンドルに CALLOUT_HANDLE_INITIALIZER() の値を割当てることは、 callout_handle_init() と同様の機能を実行し、静的な宣言またはグローバルなコールアウトハンドルで 使用するために提供されています。

関数 untimeout() は、そのハンドルの正当性を確認するために func および arg 引数を使用して、 handle に関連付けられた timeout を取り消します。 そのハンドルが引数 arg を取る関数 func を持つ timeout と一致しない場合には、何も行いません。 handle は untimeout() に渡される前に以前の timeout(), callout_handle_init() の呼び出し、または CALLOUT_HANDLE_INITIALIZER(&handle) の値の割当てによって初期化されなければなりません。 以前に初期化されたハンドルを伴なわない untimeout の呼び出しの振る舞いは 未定義です。 untimeout() の呼び出しは古いスタイルで、新しいコードは callout_* 関数を使用するべきです。

ハンドルがシステムによって再利用されるので、 両方の呼び出しが同じ関数のポインタおよび引数を使用し、2 番目の呼び出しの前に 最初の timeout が終了するか取り消された場合には、1 つの timeout() の実行からのハンドルが別の timeout() の実行のハンドルが一致することができることが (意外ではあるが) 可能です。 timeout の設備は timeout() および untimeout() のための O(1) 実行時間を提供します。 timeout (訳注: および untimeout) は splsoftclock() の状態で softclock() から実行されます。 従って、再入から保護されます。

関数 callout_init(), callout_stop() および callout_reset() は固有のコールアウト構造を割当てることを希望するクライアントのための、 低レベルのルーチンです。

関数 callout_init() はコールアウトを初期化し、そのためそのコールアウトは何の副作用もなしに callout_stop() または callout_reset() に渡されることができます。 mpsafe 引数が 0 の場合には、callout 構造体は “マルチプロセッサセーフ” であるとはみなされません。 すなわち、ジャイアントロックが callout 関数の呼出し前に 獲得され、callout 関数が戻るときに解放されるようにします。

関数 callout_stop() は、そのコールアウトが現在保留中の場合には、コールアウトを取り消します。 コールアウトが保留中の場合には、 callout_stop() は 0 でない値を返します。 コールアウトが既に実行されたか現在実行中の場合には、0 が返されます。

関数 callout_reset() は最初にそのコールアウトを廃止するために callout_stop() を呼び出し、それから新しいコールアウトを timeout() と同じ流儀で確立します。

戻り値
timeout() 関数は untimeout() に渡すことが可能な struct callout_handle を返します。 callout_stop() 関数は呼び出された時にコールアウトが未だ保留の場合には 0 以外を、 そうでない場合には 0 を返します。

バグ
コールアウトを取り消すか、もし取り消しが遅過ぎた場合には コールアウトが本当に完了されていることを保証することは、 この API にはできません。 callout_stop() は 0 を返した時に、コールアウトが開始されていている場合のみを保証します。 コールアウトが完了していることは保証しません。 ドライバのデタッチルーチンから戻る前に実行されるスレッドがないことを 保証したい時に、レース状態を発生させることがあります。

歴史
現在の timeout および untimeout ルーチンは Adam M. Costello および George Varghese の と名付けられた技術レポートで発表された作業に基づいています。また、 FreeBSD への導入のために Justin T. Gibbs によって少し修正されています。 この実装で使用されているデータ構造の元の作業は、 G. Varghese および A. Lauck によって の で発表されました。 現在の実装は、長らく存在していた、挿入および削除の O(n) 実行時間を 提供するが untimeout 操作のためのハンドルを生成または要求しなかった BSD リンクリストのコールアウト機構に、取って代りました。