日本語 man コマンド類 (ja-man-1.1j_5) と日本語 man ドキュメント (ja-man-doc-5.4 (5.4-RELEASE 用) など) をインストールすると、以下のような man コマンド閲覧、キーワード検索が コンソールからできるようになります。
4.11-RELEASE-K, 5.4-RELEASE-K, 5.5-RELEASE-K, 6.0-RELEASE-K から 6.4-RELEASE-K, 7.0-RELEASE-K から 7.4-RELEASE-K, 8.0-RELEASE-K から 8.4-RELEASE-K, 9.0-RELEASE-K から 9.3-RELEASE-K, 10.0-RELEASE-K から 10.3-RELEASE-K, 11.0-RELEASE-K から 11.4-RELEASE-K, 12.0-RELEASE-K, 12.1-RELEASE-K は、 プライベート版 (小金丸が編集してまとめたもの) ですが、 より多くの翻訳したファイルが含まれています。 (5.4-RELEASE-K から 6.4-RELEASE-K, 7.0-RELEASE-K から 7.4-RELEASE-K, 8.0-RELEASE-K から 8.4-RELEASE-K, 9.0-RELEASE-K から 9.3-RELEASE-K, 10.0-RELEASE-K から 10.3-RELEASE-K, 11.0-RELEASE-K から 11.4-RELEASE-K, 12.0-RELEASE-K から 12.4-RELEASE-K, 13.0-RELEASE-K から 13.3-RELEASE-K, 14.0-RELEASE-K から 14.1-RELEASE-K は、全翻訳済み)
13.3-STABLE-K, 15.0-CURRENT-K は現在、作成中で日々更新されています。
Table of Contents
TIMEOUT(9) FreeBSD カーネル開発者マニュアル TIMEOUT(9) 名称 callout_active, callout_deactivate, callout_async_drain, callout_drain, callout_handle_init, callout_init, callout_init_mtx, callout_init_rm, callout_init_rw, callout_pending, callout_reset, callout_reset_curcpu, callout_reset_on, callout_reset_sbt, callout_reset_sbt_curcpu, callout_reset_sbt_on, callout_schedule, callout_schedule_curcpu, callout_schedule_on, callout_schedule_sbt, callout_schedule_sbt_curcpu, callout_schedule_sbt_on, callout_stop, callout_when, timeout, untimeout -- 指定された時間の後に関数を実行する 書式 #include <sys/types.h> #include <sys/callout.h> #include <sys/systm.h> typedef void callout_func_t (void *); typedef void timeout_t (void *); int callout_active(struct callout *c); void callout_deactivate(struct callout *c); int callout_async_drain(struct callout *c, callout_func_t *drain); int callout_drain(struct callout *c); void callout_handle_init(struct callout_handle *handle); struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle); void callout_init(struct callout *c, int mpsafe); void callout_init_mtx(struct callout *c, struct mtx *mtx, int flags); void callout_init_rm(struct callout *c, struct rmlock *rm, int flags); void callout_init_rw(struct callout *c, struct rwlock *rw, int flags); int callout_pending(struct callout *c); int callout_reset(struct callout *c, int ticks, callout_func_t *func, void *arg); int callout_reset_curcpu(struct callout *c, int ticks, callout_func_t *func, void *arg); int callout_reset_on(struct callout *c, int ticks, callout_func_t *func, void *arg, int cpu); int callout_reset_sbt(struct callout *c, sbintime_t sbt, sbintime_t pr, callout_func_t *func, void *arg, int flags); int callout_reset_sbt_curcpu(struct callout *c, sbintime_t sbt, sbintime_t pr, callout_func_t *func, void *arg, int flags); int callout_reset_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t pr, callout_func_t *func, void *arg, int cpu, int flags); int callout_schedule(struct callout *c, int ticks); int callout_schedule_curcpu(struct callout *c, int ticks); int callout_schedule_on(struct callout *c, int ticks, int cpu); int callout_schedule_sbt(struct callout *c, sbintime_t sbt, sbintime_t pr, int flags); int callout_schedule_sbt_curcpu(struct callout *c, sbintime_t sbt, sbintime_t pr, int flags); int callout_schedule_sbt_on(struct callout *c, sbintime_t sbt, sbintime_t pr, int cpu, int flags); int callout_stop(struct callout *c); sbintime_t callout_when(sbintime_t sbt, sbintime_t precision, int flags, sbintime_t *sbt_res, sbintime_t *precision_res); struct callout_handle timeout(timeout_t *func, void *arg, int ticks); void untimeout(timeout_t *func, void *arg, struct callout_handle handle); 解説 callout API は、将来の特定の時間に任意の関数への呼び出しをスケジュールす るために使用されます。この API の消費者は、保留中の関数呼び出しごとにコー ルアウト構造体 (struct callout) を割り付けることを要求されます。この構造 体は、呼び出される関数、と関数が呼び出されるべき時間を含む保留中の関数呼 び出しに関して状態を格納します。保留中の関数呼び出しを取り消すか、または 異なる時間に再スケジュールすることができます。さらに、コールアウト構造 は、スケジュールされた呼び出しが終了した後に、新しい関数呼び出しをスケ ジュールするために再使用できます。 コールアウトは、単発 (single-shot) モードのみを提供しています。消費者が周 期的なタイマを要求するなら、それは、明示的に各関数呼び出しをスケジュール しなければなりません。これは、通常、呼び出される関数内の続く呼び出しをス ケジュールすることによって行われます。 コールアウト関数は、スリープ (sleep) してはなりません。それらは、スリープ 可能なロックを獲得せず、条件変数でウェートせず、割り付け要求のブロックを 実行せず、またはスリープするかもしれない他のアクションを呼び出しません。 各コールアウト構造体は、他のコールアウト関数のいずれかが渡される前に、 callout_init(), callout_init_mtx(), callout_init_rm() または callout_init_rw() によって初期化されなければなりません。callout_init() 関 数は、特定のロックに関連していいない c でコールアウト構造体を初期化しま す。mpsafe 引数が 0 であるなら、コールアウト構造体は、``マルチプロセッサ セーフ'' あると見なされません。そして、Giant ロックは、コールアウト関数を 呼び出す前に獲得され、コールアウト関数が返るとき、解放されます。 callout_init_mtx(), callout_init_rm() と callout_init_rw() 関数は、特定の ロックに関連している c でコールアウト構造体を初期化します。ロックは、mtx, rm または rw パラメータによって指定されます。関連するロックは、コールアウ トを停止するか、または再スケジュールする間に保持されなければなりません。 コールアウトサブシステムは、コールアウト関数を呼び出す前に関連するロック を獲得して、関数が返る後に、それを解放します。コールアウトサブシステムが 関連するロックを待っている間に、コールアウトがキャンセルされたなら、コー ルアウト関数は、呼び出されず、関連するロックは、解放されます。これは、 コールアウトを停止するか、または再スケジュールすことがあらゆる以前にスケ ジュールされた呼び出しを異常終了することを保証します。 通常のミューテックスだけは、callout_init_mtx() と共に使用されます。スピン (spin) ミューテックスは、サポートされません。スリープ可能なほとんど読み込 み (read-mostly) ロック (RM_SLEEPABLE フラグで初期化されるもの) は、 callout_init_rm() と共に使用されません。同様に、sx(9) と lockmgr(9) のよ うな他のスリープ可能なロックタイプは、スリープすることがコールアウトサブ システムで許可されないので、コールアウトと共に使用することはできません。 これらの flags は、callout_init_mtx(), callout_init_rm() または callout_init_rw() のために指定されるます: CALLOUT_RETURNUNLOCKED コールアウト関数は、関連するロックを自体を解放す るので、コールアウトサブシステムは、コールアウト 関数が返った後に、それをアンロックすることを試み るべきではありません。 CALLOUT_SHAREDLOCK ロックは、コールアウトハンドラを実行していると き、読み込みモードでのみ獲得されます。このフラグ は、callout_init_mtx() によって無視されます。 関数 callout_stop() は、それが、現在保留中であるなら、コールアウト c を キャンセルします。コールアウトが保留中で、成功して停止するなら、 callout_stop() は、1 の値を返します。コールアウトが設定されないか、または 既にサービスされていたなら、負の 1 が返されます。コールアウトが現在サービ スされていて、停止することができなかったなら、0 が、返されます。コールア ウトが、現在サービスされていて、停止することができず、同時に、同じコール アウトの次の呼び出しもスケジューリングされているなら、callout_stop() は、 次の実行のスケジュールを解除し、0 を返します。コールアウトに関連するロッ クがあるなら、この関数が呼び出されるとき、そのロックは、保持されなければ なりません。 関数 callout_async_drain() は、1 つの違いがある callout_stop() と同一で す。callout_async_drain() が 0 を返すとき、callout_reset() 関数に与えられ た同じ引数を使用して呼び出されるように関数 drain のために手配します。コー ルアウトに関連したロックがあるなら、そのロックは、この関数が呼び出される とき、保持されなければなりません。同じロックを使用する複数のコールアウト を停止するとき、複数の 0 の返り値を得て、どの CPU のコールアウトが実行し ているかに依存して、drain 関数への複数の呼び出しが可能であることに注意し てください。drain 関数自体は、完了しているコールアウトのコンテキストから 呼び出されます、すなわち、ちょうどコールアウト自体のように、softclock ま たは hardclock。 関数 callout_drain() は、それが既に進行中であるなら、コールアウト c が終 了することを待つことを除いて、callout_stop() と同一です。この関数は、コー ルアウトがブロックされるか、またはデッドロックの結果となるかもしれないあ らゆるロックを保持する間に、呼び出されては「いけません」。コールアウトサ ブシステムが既にこのコールアウトを処理しているなら、コールアウト関数は、 callout_drain() が返る前に、呼び出されるかもしれないことに注意してくださ い。しかしながら、コールアウトサブシステムは、callout_drain() が返る前 に、コールアウトが完全に停止されることを保証します。 callout_reset() と callout_schedule() 関数ファミリは、コールアウト c のた めに将来の関数呼び出しをスケジュールします。c が既に保留中のコールアウト があるなら、新しい呼び出しがスケジュールされる前に、それは、キャンセルさ れます。これらの関数は、保留中のコールアウトがキャンセルされたなら、1 の 値を返し、保留中のコールアウトがなかったなら、0 を返します。コールアウト に関連するロックがあるなら、これらの関数のいずれか呼び出されるとき、その ロックは、保持されなければなりません。 コールアウト関数が呼び出される時間は、ticks 引数または sbt, pr と flags 引数のいずれかによって決定されます。ticks が使用されるとき、コールアウト は、ticks/hz 秒の後に実行をスケジュールされます。ticks の正でない値は、値 `1' に静かに変換されます。 sbt, pr と flags 引数は、より高い解像度の時間のサポート、スケジュールされ る時間の精度を指定し、相対的なタイムアウトの代わりに絶対的なデッドライン を設定することを含んでスケジュールされた時間のいっそうの制御を提供しま す。コールアウトは、sbt で指定された時間に始まり、pr で指定された時間の量 まで延長される時間ウィンドウで実行するようにスケジュールされます。sbt が 過去の時間を指定するなら、ウィンドウは、現在の時間から開始するように調節 されます。pr に対する 0 でない値によって、コールアウトサブシステムは、処 理のオーバヘッドと電力消費量を縮小して、より少ないタイマの割り込みに互い にコールアウトのスケジュールされたクローズを結合できます。これらの flags は、sbt と pr の解釈を調整すために指定されます: C_ABSOLUTE ブート以来の絶対時間として sbt 引数を扱います。デフォルト で、sbt は、ticks に似ている、時間の相対的な量として扱われ ます。 C_DIRECT_EXEC softclock スレッドの代わりにハードウェア割り込みコンテキス トから直接ハンドラを実行します。これは、待ち時間とオーバ ヘッドを縮小しますが、コールアウト関数でより多く制約しま す。このコンテキストで実行されるコールアウト関数は、ロック のためにスピン (spin) ミューテックスだけを使用し、それらが 絶対的な優先度で実行するので、できますだけ小さくするべきで す。 C_PREL 受け付け可能な時間の偏差によって割られた時間の間隔の 2 進 法の対数として相対的なイベント時間の精度を指定します: 1 -- 1/2, 2 -- 1/4, その他。pr またはこの値のより大きなものは、 時間ウィンドウの長さとして使用されることに注意してくださ い。(より大きな時間の間隔の結果となる) より小さな値によっ て、コールアウトサブシステムは、1 つのタイマ割り込みで、よ り多くのイベントを集めることができます。 C_PRECALC sbt 引数は、コールアウトが実行されるべきである絶対的な時間 を指定し、pr 引数は、スケジューリングプロセスの間に調整さ れない、要求された精度を指定します。sbt と pr 値は、ユーザ に供給された sbt, pr と flags 値を使用する callout_when() への前の呼び出しによって計算されるべきです。 C_HARDCLOCK 可能であれば、hardclock() 呼び出しへのタイムアウトを整列し ます。 callout_reset() 関数は、時間の期限が切れるとき、呼び出される関数を識別す る func 引数を受け付けます。それは、単一の void * 引数を取る関数へのポイ ンタでなければなりません。呼び出し時に、func は、そのただ 1 つの引数とし て arg を受け取ります。callout_schedule() 関数は、以前のコールアウトから func と arg 引数を再使用します。callout_reset() 関数の 1 つは、 callout_schedule() 関数の 1 つを使用することができる前に、func と arg を 初期化するために常に呼び出されなければならないことに注意してください。 コールアウトサブシステムは、システムの CPU ごとに softclock スレッドを提 供します。コールアウトは、単一の CPU に割り当てられ、その CPU のための softclock スレッドによって実行されます。最初に、コールアウトは、CPU 0 に 割り当てられます。callout_reset_on(), callout_reset_sbt_on(), callout_schedule_on() と callout_schedule_sbt_on() 関数は、CPU cpu にコー ルアウトを割り当てます。callout_reset_curcpu(), callout_reset_sbt_curpu(), callout_schedule_curcpu() と callout_schedule_sbt_curcpu() 関数は、現在の CPU にコールアウトを割り当て ます。callout_reset(), callout_reset_sbt(), callout_schedule() と callout_schedule_sbt() 関数は、それが現在、割り当てられる CPU の soft clock スレッドで実行するコールアウトをスケジュールします。 softclock スレッドは、デフォルトでそれぞれの CPU に固定されません。0 でな い値に kern.pin_default_swi ローダ調整変数を設定することによって、CPU 0 のための softclock スレッドを CPU 0 に固定することができます。0 でない値 に kern.pin_pcpu_swi ローダ調整変数を設定することによって、0 以外の複数の CPU のための softclock スレッドを、それらのそれぞれの複数の CPU に固定す ることができます。 マクロ callout_pending(), callout_active() と callout_deactivate() は、 コールアウトの現在の状態へのアクセスを提供します。callout_pending() マク ロは、コールアウトが保留中であるかどうかチェックします。コールアウトは、 タイムアウトが設定されているが、時間にまだ到着していないとき、保留中であ ると見なされます。いったんタイムアウト時間に到着し、コールアウトサブシス テムは、このコールアウトを処理し始め、callout_pending() は、たとえコール アウト関数が実行を終了して (または、始められて) いなくても、FALSE を返す ことに注意してください。callout_active() マクロは、コールアウトがアクティ ブ (active) としてマークされるかどうかチェックし、callout_deactivate() マ クロは、コールアウトのアクティブ (active) なフラグをクリアします。コール アウトサブシステムは、タイムアウトが設定されるとき、アクティブとしてコー ルアウトをマークし、callout_stop() と callout_drain() のアクティブフラグ をクリアしますが、通常、コールアウトがコールアウト関数の実行を通して期限 切れになるとき、クリアしません。 callout_when() 関数は、タイムアウトが実行されるべき、絶対的な時間と、要求 された時間 sbt にしたがってスケジューリングされた実行時の精度、精度 precision と flags 引数によって要求された追加の調整をあらかじめ計算するた めに使用されます。callout_when() 関数によって受け付けられたフラグは、 callout_reset() 関数のためのフラグと同じです。結果の時間は、sbt_res 引数 によって指された変数に割り当てられ、結果の精度は、*precision_res に割り当 てられます。callout_reset に結果を渡すとき、間違った再調整を避けるため に、C_PRECALC フラグを flags に追加します。callout_reset() 呼び出しが活発 であった後に、コールアウト構造自体から、この時間を読み込むことを試みてい るので、関数は、コールアウトの実行の精密な時間があらかじめ知られている状 況を対象としています。 競合条件を回避する コールアウトサブシステムは、それ自体のスレッドのコンテキストからコールア ウト関数を呼び出します。ある種類の同期なしで、コールアウト関数は、別のス レッドによってコールアウトを停止するか、またはリセットする試みと同時に、 呼び出される可能性があります。特に、コールアウト関数は、一般的に、それら の最初の動作としてロックを獲得するので、コールアウト関数は、既に呼び出さ れているかもしれませんが、別のスレッドがコールアウトをリセットするか、ま たは停止することを試みる時点で、そのロックを待ってブロックされるかもしれ ません。 これらの同期関連を扱うために 3 つの主要な技術があります。最初のアプローチ は、最も単純にすることが好まれます: 1. コールアウトは、それらが、callout_init_mtx(), callout_init_rm() または callout_init_rw() によって初期化され るとき、特定のロックに関連することができます。コールアウトが ロックに関連しているとき、コールアウトサブシステムは、コールア ウト関数が呼び出される前に、ロックを獲得します。これによって、 コールアウトサブシステムは、コールアウトがスケジュールをキャン セルすることと実行の間の競合を透過的に扱うことができます。 callout_stop() またはこの安全を提供する callout_reset() または callout_schedule() 関数の 1 つを呼び出す前に、関連するロック が、獲得されなければならないことに注意してください。 0 に設定された mpsafe で callout_init() によって初期化された コールアウトは、Giant ミューテックスに暗黙のうちに関連付けられ ます。コールアウトをキャンセルするか、再スケジュールするとき、 Giant が保持されるなら、その使用は、コールアウト関数がある競合 を防ぎます。 2. callout_stop() (または callout_reset() と callout_schedule() 関数ファミリ) からの返り値は、コールアウトが削除されたかどうか を示します。コールアウトが設定され、コールアウト関数がまだ実行 されていないことが知られているなら、FALSE の返り値は、コールア ウト関数が呼び出されよとしていることを示します。例えば: if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) { if (callout_stop(&sc->sc_callout)) { sc->sc_flags &= ~SCFLG_CALLOUT_RUNNING; /* 成功して停止しました */ } else { /* * コールアウトの期限が切れた, * コールアウト関数は, * 実行されようとしている */ } } 3. 競合条件を対処するために callout_pending(), callout_active() と callout_deactivate() マクロを一緒に使用することができます。 コールアウトのタイムアウトが設定されるとき、コールアウトサブシ ステムは、アクティブと保留中の両方としてコールアウトをマークし ます。タイムアウトの時間に到着するとき、コールアウトサブシステ ムは、保留中フラグを最初にクリアすることによってコールアウトを 処理し始めます。次に、アクティブフラグを変更しないで、コールア ウト関数を呼び出し、コールアウト関数が返った後でさえ、アクティ ブフラグをクリアしません。ここで説明されたメカニズムは、 callout_deactivate() マクロを使用して、アクティブフラグをクリ アすることをコールアウト関数自体に要求します。callout_stop() と callout_drain() 関数は、返る前にアクティブと保留中フラグの 両方を常にクリアします。 コールアウト関数は、最初に保留中フラグをチェックし、 callout_pending() が TRUE を返すなら、動作なしで返るべきです。 これは、コールアウト関数が呼び出される直前に、コールアウトが callout_reset() を使用して再スケジュールされたことを示します。 callout_active() が FALSE を返すなら、コールアウト関数は、同様 に動作なしで返るべきです。これは、コールアウトが停止されたこと を示します。最後に、コールアウト関数は、アクティブフラグをクリ アするために callout_deactivate() を呼び出すべきです。例えば: mtx_lock(&sc->sc_mtx); if (callout_pending(&sc->sc_callout)) { /* コールアウトは, リセットされた */ mtx_unlock(&sc->sc_mtx); return; } if (!callout_active(&sc->sc_callout)) { /* コールアウトは, 停止された */ mtx_unlock(&sc->sc_mtx); return; } callout_deactivate(&sc->sc_callout); /* コールアウト関数のリセット */ 上記で使用されるミューテックスのような適切な同期とともに、この アプローチは、競合なしでいつでも使用できるように callout_stop() と callout_reset() 関数に許可します。例えば: mtx_lock(&sc->sc_mtx); callout_stop(&sc->sc_callout); /* コールアウトは, 今, 事実上停止されます. */ コールアウトがまだ保留中であるなら、これらの関数は、正常に動作 しますが、コールアウトの処理が既に始まっているなら、コールアウ ト関数のテストによってさらなる動作なしで返ります。コールアウト 関数と他のコードの間の同期は、コールアウト関数が callout_deactivate() 呼び出している間に、コールアウトを停止す るか、またはリセットすることを決して試みないことを保証します。 さらに、上記のテクニックは、アクティブフラグが、コールアウトを 効果的に有効にするか、または無効にするかどうかを常に反射するこ とを保証します。callout_active() が偽 (false) で返るなら、たと えコールアウトサブシステムが実際にコールアウト関数を呼び出すと ころだとしても、コールアウト関数は、動作なしで返るので、コール アウトは、事実上に無効にされます。 コールアウトが最後に停止されているとき、考慮されなければならない 1 つの最 後の競合条件があります。この場合、既に破壊されたか、または再利用された データオブジェクトをアクセスする必要があるので、コールアウト関数自体は、 コールアウトが停止されたことを検出することは安全ではないかもしれません。 コールアウトが完全に終了されることを保証するために、callout_drain() への 呼び出しが使用されるべきです。特に、コールアウトは、その関連するロックを 破壊するか、コールアウト構造体のための記憶域を解放する前に、常に使い果た されるべきです。 古い API 下記の関数は、将来のリリースで削除される古い API です。新しいコードは、こ れらのルーチンを使用するべきではありません。 関数 timeout() は、ticks/hz 秒の後に起こる引数 func によって与えられた関 数への呼び出しをスケジュールします。ticks の正でない値は、値 `1' に静かに 変換されます。func は、void * 引数を取る関数へのポインタであるべきです。 呼び出し時に、func は、そのただ 1 つの引数として arg を受け取ります。 timeout() からの返り値は、スケジュールされたタイムアウトがキャンセルされ ることを要求する untimeout() 関数と共に使用することができる struct callout_handle です。 関数 callout_handle_init() は、副作用なしで返すためにそのハンドルを付けて untimeout() へのあらゆる呼び出しをもたらす状態へのハンドルを初期化するた めに使用することができます。 コールアウトのハンドルに CALLOUT_HANDLE_INITIALIZER() の値を割り当てるこ とは、callout_handle_init() と同じ機能を実行し、静的に宣言されるか、グ ローバルのコールアウトハンドルで使用するために提供されます。 関数 untimeout() は、ハンドルを有効にするために func と arg 引数を使用し て、handle に関連したタイムアウトをキャンセルします。ハンドルが引数 arg を取る関数 func でタイムアウトに対応しないなら、アクションは、取られませ ん。handle は、untimeout() に渡される前に、timeout(), callout_handle_init() または CALLOUT_HANDLE_INITIALIZER(&handle) の値を割 り当てられる、以前の呼び出しによって初期化されなければなりません。初期化 されていないハンドルを付けて untimeout() を呼び出す振る舞いは、未定義で す。 ハンドルがシステムによって再利用されるように、両方の呼び出しが同じ関数ポ インタと引数を使用し、最初のタイムアウトが、2 番目の呼び出しの前に期限が 切れるか、キャンセルされるなら、(ありそうもありませんが) timeout() の 1 つの呼び出しからのハンドルが timeout() の別の呼び出しのハンドルと一致する 可能性があります。タイムアウト機能は、timeout() と untimeout() のために O(1) の実行時間を提示します。タイムアウトは、保持された Giant ロックで softclock() から実行されます。したがって、それらは、再入可能性から保護さ れます。 戻り値 callout_active() マクロは、コールアウトのアクティブなフラグの状態を返しま す。 callout_pending() マクロは、コールアウトの保留中のフラグの状態を返しま す。 callout_reset() と callout_schedule() 関数ファミリは、コールアウトが新し い関数呼び出しがスケジュールされる前に、保留中であったなら、1 の値を返し ます。 callout_stop() と callout_drain() 関数は、それが呼び出されるとき、コール アウトがまだ保留中だったなら、1 の値が返され、コールアウトが停止すること ができないなら、0 が返され、実行されていないか、または既に完了していたか のいずれかなら、負の 1 が返されます。timeout() 関数は、untimeout() に渡す ことができる struct callout_handle を返します。 歴史 現在の timeout と untimeout ルーチンは、Redesigning the BSD Callout and Timer Facilities と表題がつけられた技術報告書で公表された Adam M. Costello と George Varghese の作業に基づいています、そして Justin T. Gibbs によって FreeBSD の導入のために少し修正されました。この実装で使用さ れるデータ構造の元の作業は、Proceedings of the 11th ACM Annual Symposium on Operating Systems Principles. の論文 Hashed and Hierarchical Timing Wheels: Data Structures for the Efficient Implementation of a Timer Facility で G. Varghese と A. Lauck によって公表されました。現在の実装 は、長く続いている、実行時の O(n) の挿入と削除を提出し、untimeout 操作の ためのハンドルを生成せず、必要としなかった、BSD リンクリストのコールアウ トメカニズムを置き換えました。 FreeBSD 11.4 December 10, 2019 FreeBSD 11.4