diff options
Diffstat (limited to 'static/freebsd/man9/callout.9 3.html')
| -rw-r--r-- | static/freebsd/man9/callout.9 3.html | 614 |
1 files changed, 0 insertions, 614 deletions
diff --git a/static/freebsd/man9/callout.9 3.html b/static/freebsd/man9/callout.9 3.html deleted file mode 100644 index e2951509..00000000 --- a/static/freebsd/man9/callout.9 3.html +++ /dev/null @@ -1,614 +0,0 @@ -<table class="head"> - <tr> - <td class="head-ltitle">CALLOUT(9)</td> - <td class="head-vol">Kernel Developer's Manual</td> - <td class="head-rtitle">CALLOUT(9)</td> - </tr> -</table> -<div class="manual-text"> -<section class="Sh"> -<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1> -<p class="Pp"><code class="Nm">callout_active</code>, - <code class="Nm">callout_deactivate</code>, - <code class="Nm">callout_drain</code>, <code class="Nm">callout_init</code>, - <code class="Nm">callout_init_mtx</code>, - <code class="Nm">callout_init_rm</code>, - <code class="Nm">callout_init_rw</code>, - <code class="Nm">callout_pending</code>, - <code class="Nm">callout_reset</code>, - <code class="Nm">callout_reset_curcpu</code>, - <code class="Nm">callout_reset_on</code>, - <code class="Nm">callout_reset_sbt</code>, - <code class="Nm">callout_reset_sbt_curcpu</code>, - <code class="Nm">callout_reset_sbt_on</code>, - <code class="Nm">callout_schedule</code>, - <code class="Nm">callout_schedule_curcpu</code>, - <code class="Nm">callout_schedule_on</code>, - <code class="Nm">callout_schedule_sbt</code>, - <code class="Nm">callout_schedule_sbt_curcpu</code>, - <code class="Nm">callout_schedule_sbt_on</code>, - <code class="Nm">callout_stop</code>, <code class="Nm">callout_when</code> - — <span class="Nd">execute a function after a specified length of - time</span></p> -</section> -<section class="Sh"> -<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1> -<p class="Pp"><code class="In">#include - <<a class="In">sys/types.h</a>></code> - <br/> - <code class="In">#include <<a class="In">sys/callout.h</a>></code></p> -<div class="Bd Pp Li"> -<pre>typedef void callout_func_t (void *);</pre> -</div> -<br/> -<var class="Ft">int</var> -<br/> -<code class="Fn">callout_active</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>); -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">callout_deactivate</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_drain</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">callout_init</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>, <var class="Fa" style="white-space: nowrap;">int - mpsafe</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">callout_init_mtx</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>, <var class="Fa" style="white-space: nowrap;">struct mtx - *mtx</var>, <var class="Fa" style="white-space: nowrap;">int - flags</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">callout_init_rm</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>, <var class="Fa" style="white-space: nowrap;">struct rmlock - *rm</var>, <var class="Fa" style="white-space: nowrap;">int - flags</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">callout_init_rw</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>, <var class="Fa" style="white-space: nowrap;">struct rwlock - *rw</var>, <var class="Fa" style="white-space: nowrap;">int - flags</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_pending</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_reset</code>(<var class="Fa">struct callout *c</var>, - <var class="Fa">int ticks</var>, <var class="Fa">callout_func_t *func</var>, - <var class="Fa">void *arg</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_reset_curcpu</code>(<var class="Fa">struct callout - *c</var>, <var class="Fa">int ticks</var>, <var class="Fa">callout_func_t - *func</var>, <var class="Fa">void *arg</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_reset_on</code>(<var class="Fa">struct callout - *c</var>, <var class="Fa">int ticks</var>, <var class="Fa">callout_func_t - *func</var>, <var class="Fa">void *arg</var>, <var class="Fa">int - cpu</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_reset_sbt</code>(<var class="Fa">struct callout - *c</var>, <var class="Fa">sbintime_t sbt</var>, <var class="Fa">sbintime_t - pr</var>, <var class="Fa">callout_func_t *func</var>, <var class="Fa">void - *arg</var>, <var class="Fa">int flags</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_reset_sbt_curcpu</code>(<var class="Fa">struct - callout *c</var>, <var class="Fa">sbintime_t sbt</var>, - <var class="Fa">sbintime_t pr</var>, <var class="Fa">callout_func_t - *func</var>, <var class="Fa">void *arg</var>, <var class="Fa">int - flags</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_reset_sbt_on</code>(<var class="Fa">struct callout - *c</var>, <var class="Fa">sbintime_t sbt</var>, <var class="Fa">sbintime_t - pr</var>, <var class="Fa">callout_func_t *func</var>, <var class="Fa">void - *arg</var>, <var class="Fa">int cpu</var>, <var class="Fa">int - flags</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_schedule</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>, <var class="Fa" style="white-space: nowrap;">int - ticks</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_schedule_curcpu</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>, <var class="Fa" style="white-space: nowrap;">int - ticks</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_schedule_on</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>, <var class="Fa" style="white-space: nowrap;">int - ticks</var>, <var class="Fa" style="white-space: nowrap;">int - cpu</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_schedule_sbt</code>(<var class="Fa">struct callout - *c</var>, <var class="Fa">sbintime_t sbt</var>, <var class="Fa">sbintime_t - pr</var>, <var class="Fa">int flags</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_schedule_sbt_curcpu</code>(<var class="Fa">struct - callout *c</var>, <var class="Fa">sbintime_t sbt</var>, - <var class="Fa">sbintime_t pr</var>, <var class="Fa">int flags</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_schedule_sbt_on</code>(<var class="Fa">struct callout - *c</var>, <var class="Fa">sbintime_t sbt</var>, <var class="Fa">sbintime_t - pr</var>, <var class="Fa">int cpu</var>, <var class="Fa">int - flags</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">callout_stop</code>(<var class="Fa" style="white-space: nowrap;">struct - callout *c</var>);</p> -<p class="Pp"><var class="Ft">sbintime_t</var> - <br/> - <code class="Fn">callout_when</code>(<var class="Fa">sbintime_t sbt</var>, - <var class="Fa">sbintime_t precision</var>, <var class="Fa">int flags</var>, - <var class="Fa">sbintime_t *sbt_res</var>, <var class="Fa">sbintime_t - *precision_res</var>);</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1> -<p class="Pp">The <code class="Nm">callout</code> API is used to schedule a call - to an arbitrary function at a specific time in the future. Consumers of this - API are required to allocate a callout structure (struct callout) for each - pending function invocation. This structure stores state about the pending - function invocation including the function to be called and the time at - which the function should be invoked. Pending function calls can be - cancelled or rescheduled to a different time. In addition, a callout - structure may be reused to schedule a new function call after a scheduled - call is completed.</p> -<p class="Pp">Callouts only provide a single-shot mode. If a consumer requires a - periodic timer, it must explicitly reschedule each function call. This is - normally done by rescheduling the subsequent call within the called - function.</p> -<p class="Pp">Callout functions must not sleep. They may not acquire sleepable - locks, wait on condition variables, perform blocking allocation requests, or - invoke any other action that might sleep.</p> -<p class="Pp" id="callout_init">Each callout structure must be initialized by - <a class="permalink" href="#callout_init"><code class="Fn">callout_init</code></a>(), - <code class="Fn">callout_init_mtx</code>(), - <code class="Fn">callout_init_rm</code>(), or - <code class="Fn">callout_init_rw</code>() before it is passed to any of the - other callout functions. The <code class="Fn">callout_init</code>() function - initializes a callout structure in <var class="Fa">c</var> that is not - associated with a specific lock. If the <var class="Fa">mpsafe</var> - argument is zero, the callout structure is not considered to be - “multi-processor safe”; and the Giant lock will be acquired - before calling the callout function and released when the callout function - returns.</p> -<p class="Pp" id="callout_init_mtx">The - <a class="permalink" href="#callout_init_mtx"><code class="Fn">callout_init_mtx</code></a>(), - <code class="Fn">callout_init_rm</code>(), and - <a class="permalink" href="#callout_init_rw"><code class="Fn" id="callout_init_rw">callout_init_rw</code></a>() - functions initialize a callout structure in <var class="Fa">c</var> that is - associated with a specific lock. The lock is specified by the - <var class="Fa">mtx</var>, <var class="Fa">rm</var>, or - <var class="Fa">rw</var> parameter. The associated lock must be held while - stopping or rescheduling the callout. The callout subsystem acquires the - associated lock before calling the callout function and releases it after - the function returns. If the callout was cancelled while the callout - subsystem waited for the associated lock, the callout function is not - called, and the associated lock is released. This ensures that stopping or - rescheduling the callout will abort any previously scheduled invocation.</p> -<p class="Pp" id="callout_init_rm">A sleepable read-mostly lock (one initialized - with the <code class="Dv">RM_SLEEPABLE</code> flag) may not be used with - <a class="permalink" href="#callout_init_rm"><code class="Fn">callout_init_rm</code></a>(). - Similarly, other sleepable lock types such as <a class="Xr">sx(9)</a> and - <a class="Xr">lockmgr(9)</a> cannot be used with callouts because sleeping - is not permitted in the callout subsystem.</p> -<p class="Pp" id="callout_init_mtx~2">These <var class="Fa">flags</var> may be - specified for - <a class="permalink" href="#callout_init_mtx~2"><code class="Fn">callout_init_mtx</code></a>(), - <code class="Fn">callout_init_rm</code>(), or - <a class="permalink" href="#callout_init_rw~2"><code class="Fn" id="callout_init_rw~2">callout_init_rw</code></a>():</p> -<dl class="Bl-tag"> - <dt id="CALLOUT_RETURNUNLOCKED"><a class="permalink" href="#CALLOUT_RETURNUNLOCKED"><code class="Dv">CALLOUT_RETURNUNLOCKED</code></a></dt> - <dd>The callout function will release the associated lock itself, so the - callout subsystem should not attempt to unlock it after the callout - function returns.</dd> - <dt id="CALLOUT_SHAREDLOCK"><a class="permalink" href="#CALLOUT_SHAREDLOCK"><code class="Dv">CALLOUT_SHAREDLOCK</code></a></dt> - <dd>The lock is only acquired in read mode when running the callout handler. - This flag is ignored by <code class="Fn">callout_init_mtx</code>().</dd> -</dl> -<p class="Pp" id="callout_stop">The function - <a class="permalink" href="#callout_stop"><code class="Fn">callout_stop</code></a>() - cancels a callout <var class="Fa">c</var> if it is currently pending. If the - callout is pending and successfully stopped, then - <code class="Fn">callout_stop</code>() returns a value of one. If the - callout is not set, or has already been serviced, then negative one is - returned. If the callout is currently being serviced and cannot be stopped, - then zero will be returned. If the callout is currently being serviced and - cannot be stopped, and at the same time a next invocation of the same - callout is also scheduled, then <code class="Fn">callout_stop</code>() - unschedules the next run and returns zero. If the callout has an associated - lock, then that lock must be held when this function is called.</p> -<p class="Pp" id="callout_drain">The function - <a class="permalink" href="#callout_drain"><code class="Fn">callout_drain</code></a>() - is identical to <code class="Fn">callout_stop</code>() except that it will - wait for the callout <var class="Fa">c</var> to complete if it is already in - progress. This function MUST NOT be called while holding any locks on which - the callout might block, or deadlock will result. Note that if the callout - subsystem has already begun processing this callout, then the callout - function may be invoked before <code class="Fn">callout_drain</code>() - returns. However, the callout subsystem does guarantee that the callout will - be fully stopped before <code class="Fn">callout_drain</code>() returns.</p> -<p class="Pp" id="callout_reset">The - <a class="permalink" href="#callout_reset"><code class="Fn">callout_reset</code></a>() - and - <a class="permalink" href="#callout_schedule"><code class="Fn" id="callout_schedule">callout_schedule</code></a>() - function families schedule a future function invocation for callout - <var class="Fa">c</var>. If <var class="Fa">c</var> already has a pending - callout, it is cancelled before the new invocation is scheduled. These - functions return a value of one if a pending callout was cancelled and zero - if there was no pending callout. If the callout has an associated lock, then - that lock must be held when any of these functions are called.</p> -<p class="Pp">The time at which the callout function will be invoked is - determined by either the <var class="Fa">ticks</var> argument or the - <var class="Fa">sbt</var>, <var class="Fa">pr</var>, and - <var class="Fa">flags</var> arguments. When <var class="Fa">ticks</var> is - used, the callout is scheduled to execute after - <var class="Fa">ticks</var><span class="No">/hz</span> seconds. Non-positive - values of <var class="Fa">ticks</var> are silently converted to the value - ‘1’.</p> -<p class="Pp">The <var class="Fa">sbt</var>, <var class="Fa">pr</var>, and - <var class="Fa">flags</var> arguments provide more control over the - scheduled time including support for higher resolution times, specifying the - precision of the scheduled time, and setting an absolute deadline instead of - a relative timeout. The callout is scheduled to execute in a time window - which begins at the time specified in <var class="Fa">sbt</var> and extends - for the amount of time specified in <var class="Fa">pr</var>. If - <var class="Fa">sbt</var> specifies a time in the past, the window is - adjusted to start at the current time. A non-zero value for - <var class="Fa">pr</var> allows the callout subsystem to coalesce callouts - scheduled close to each other into fewer timer interrupts, reducing - processing overhead and power consumption. These <var class="Fa">flags</var> - may be specified to adjust the interpretation of <var class="Fa">sbt</var> - and <var class="Fa">pr</var>:</p> -<dl class="Bl-tag"> - <dt id="C_ABSOLUTE"><a class="permalink" href="#C_ABSOLUTE"><code class="Dv">C_ABSOLUTE</code></a></dt> - <dd>Handle the <var class="Fa">sbt</var> argument as an absolute time since - boot. By default, <var class="Fa">sbt</var> is treated as a relative - amount of time, similar to <var class="Fa">ticks</var>.</dd> - <dt id="C_DIRECT_EXEC"><a class="permalink" href="#C_DIRECT_EXEC"><code class="Dv">C_DIRECT_EXEC</code></a></dt> - <dd>Run the handler directly from hardware interrupt context instead of from - the softclock thread. This reduces latency and overhead, but puts more - constraints on the callout function. Callout functions run in this context - may use only spin mutexes for locking and should be as small as possible - because they run with absolute priority.</dd> - <dt id="C_PREL"><a class="permalink" href="#C_PREL"><code class="Fn">C_PREL</code></a>()</dt> - <dd>Specifies relative event time precision as binary logarithm of time - interval divided by acceptable time deviation: 1 -- 1/2, 2 -- 1/4, etc. - Note that the larger of <var class="Fa">pr</var> or this value is used as - the length of the time window. Smaller values (which result in larger time - intervals) allow the callout subsystem to aggregate more events in one - timer interrupt.</dd> - <dt id="C_PRECALC"><a class="permalink" href="#C_PRECALC"><code class="Dv">C_PRECALC</code></a></dt> - <dd>The <var class="Fa">sbt</var> argument specifies the absolute time at - which the callout should be run, and the <var class="Fa">pr</var> argument - specifies the requested precision, which will not be adjusted during the - scheduling process. The <var class="Fa">sbt</var> and - <var class="Fa">pr</var> values should be calculated by an earlier call to - <code class="Fn">callout_when</code>() which uses the user-supplied - <var class="Fa">sbt</var>, <var class="Fa">pr</var>, and - <var class="Fa">flags</var> values.</dd> - <dt id="C_HARDCLOCK"><a class="permalink" href="#C_HARDCLOCK"><code class="Dv">C_HARDCLOCK</code></a></dt> - <dd>Align the timeouts to - <a class="permalink" href="#hardclock"><code class="Fn" id="hardclock">hardclock</code></a>() - calls if possible.</dd> -</dl> -<p class="Pp" id="callout_reset~2">The - <a class="permalink" href="#callout_reset~2"><code class="Fn">callout_reset</code></a>() - functions accept a <var class="Fa">func</var> argument which identifies the - function to be called when the time expires. It must be a pointer to a - function that takes a single <var class="Fa">void *</var> argument. Upon - invocation, <var class="Fa">func</var> will receive - <var class="Fa">arg</var> as its only argument. The - <a class="permalink" href="#callout_schedule~2"><code class="Fn" id="callout_schedule~2">callout_schedule</code></a>() - functions reuse the <var class="Fa">func</var> and <var class="Fa">arg</var> - arguments from the previous callout. Note that one of the - <code class="Fn">callout_reset</code>() functions must always be called to - initialize <var class="Fa">func</var> and <var class="Fa">arg</var> before - one of the <code class="Fn">callout_schedule</code>() functions can be - used.</p> -<p class="Pp" id="callout_reset_on">The callout subsystem provides a softclock - thread for each CPU in the system. Callouts are assigned to a single CPU and - are executed by the softclock thread for that CPU. Initially, callouts are - assigned to CPU 0. The - <a class="permalink" href="#callout_reset_on"><code class="Fn">callout_reset_on</code></a>(), - <a class="permalink" href="#callout_reset_sbt_on"><code class="Fn" id="callout_reset_sbt_on">callout_reset_sbt_on</code></a>(), - <a class="permalink" href="#callout_schedule_on"><code class="Fn" id="callout_schedule_on">callout_schedule_on</code></a>() - and - <a class="permalink" href="#callout_schedule_sbt_on"><code class="Fn" id="callout_schedule_sbt_on">callout_schedule_sbt_on</code></a>() - functions assign the callout to CPU <var class="Fa">cpu</var>. The - <a class="permalink" href="#callout_reset_curcpu"><code class="Fn" id="callout_reset_curcpu">callout_reset_curcpu</code></a>(), - <a class="permalink" href="#callout_reset_sbt_curpu"><code class="Fn" id="callout_reset_sbt_curpu">callout_reset_sbt_curpu</code></a>(), - <a class="permalink" href="#callout_schedule_curcpu"><code class="Fn" id="callout_schedule_curcpu">callout_schedule_curcpu</code></a>() - and - <a class="permalink" href="#callout_schedule_sbt_curcpu"><code class="Fn" id="callout_schedule_sbt_curcpu">callout_schedule_sbt_curcpu</code></a>() - functions assign the callout to the current CPU. The - <code class="Fn">callout_reset</code>(), - <a class="permalink" href="#callout_reset_sbt"><code class="Fn" id="callout_reset_sbt">callout_reset_sbt</code></a>(), - <code class="Fn">callout_schedule</code>() and - <a class="permalink" href="#callout_schedule_sbt"><code class="Fn" id="callout_schedule_sbt">callout_schedule_sbt</code></a>() - functions schedule the callout to execute in the softclock thread of the CPU - to which it is currently assigned.</p> -<p class="Pp">Softclock threads are not pinned to their respective CPUs by - default. The softclock thread for CPU 0 can be pinned to CPU 0 by setting - the <var class="Va">kern.pin_default_swi</var> loader tunable to a non-zero - value. Softclock threads for CPUs other than zero can be pinned to their - respective CPUs by setting the <var class="Va">kern.pin_pcpu_swi</var> - loader tunable to a non-zero value.</p> -<p class="Pp" id="callout_pending">The macros - <a class="permalink" href="#callout_pending"><code class="Fn">callout_pending</code></a>(), - <code class="Fn">callout_active</code>() and - <code class="Fn">callout_deactivate</code>() provide access to the current - state of the callout. The <code class="Fn">callout_pending</code>() macro - checks whether a callout is <i class="Em">pending</i>; a callout is - considered <i class="Em">pending</i> when a timeout has been set but the - time has not yet arrived. Note that once the timeout time arrives and the - callout subsystem starts to process this callout, - <code class="Fn">callout_pending</code>() will return - <code class="Dv">FALSE</code> even though the callout function may not have - finished (or even begun) executing. The - <code class="Fn">callout_active</code>() macro checks whether a callout is - marked as <i class="Em">active</i>, and the - <code class="Fn">callout_deactivate</code>() macro clears the callout's - <i class="Em">active</i> flag. The callout subsystem marks a callout as - <i class="Em">active</i> when a timeout is set and it clears the - <i class="Em">active</i> flag in <code class="Fn">callout_stop</code>() and - <code class="Fn">callout_drain</code>(), but it - <a class="permalink" href="#does"><i class="Em" id="does">does not</i></a> - clear it when a callout expires normally via the execution of the callout - function.</p> -<p class="Pp" id="callout_when">The - <a class="permalink" href="#callout_when"><code class="Fn">callout_when</code></a>() - function may be used to pre-calculate the absolute time at which the timeout - should be run and the precision of the scheduled run time according to the - required time <var class="Fa">sbt</var>, precision - <var class="Fa">precision</var>, and additional adjustments requested by the - <var class="Fa">flags</var> argument. Flags accepted by the - <code class="Fn">callout_when</code>() function are the same as flags for - the <code class="Fn">callout_reset</code>() function. The resulting time is - assigned to the variable pointed to by the <var class="Fa">sbt_res</var> - argument, and the resulting precision is assigned to - <var class="Fa">*precision_res</var>. When passing the results to - <var class="Fa">callout_reset</var>, add the <var class="Va">C_PRECALC</var> - flag to <var class="Fa">flags</var>, to avoid incorrect re-adjustment. The - function is intended for situations where precise time of the callout run - should be known in advance, since trying to read this time from the callout - structure itself after a <code class="Fn">callout_reset</code>() call is - racy.</p> -<section class="Ss"> -<h2 class="Ss" id="Avoiding_Race_Conditions"><a class="permalink" href="#Avoiding_Race_Conditions">Avoiding - Race Conditions</a></h2> -<p class="Pp">The callout subsystem invokes callout functions from its own - thread context. Without some kind of synchronization, it is possible that a - callout function will be invoked concurrently with an attempt to stop or - reset the callout by another thread. In particular, since callout functions - typically acquire a lock as their first action, the callout function may - have already been invoked, but is blocked waiting for that lock at the time - that another thread tries to reset or stop the callout.</p> -<p class="Pp">There are three main techniques for addressing these - synchronization concerns. The first approach is preferred as it is the - simplest:</p> -<ol class="Bl-enum Bd-indent"> - <li id="callout_init_mtx~3">Callouts can be associated with a specific lock - when they are initialized by - <a class="permalink" href="#callout_init_mtx~3"><code class="Fn">callout_init_mtx</code></a>(), - <code class="Fn">callout_init_rm</code>(), or - <a class="permalink" href="#callout_init_rw~3"><code class="Fn" id="callout_init_rw~3">callout_init_rw</code></a>(). - When a callout is associated with a lock, the callout subsystem acquires - the lock before the callout function is invoked. This allows the callout - subsystem to transparently handle races between callout cancellation, - scheduling, and execution. Note that the associated lock must be acquired - before calling <code class="Fn">callout_stop</code>() or one of the - <code class="Fn">callout_reset</code>() or - <code class="Fn">callout_schedule</code>() functions to provide this - safety. - <p class="Pp" id="callout_init~2">A callout initialized via - <a class="permalink" href="#callout_init~2"><code class="Fn">callout_init</code></a>() - with <var class="Fa">mpsafe</var> set to zero is implicitly associated - with the <var class="Va">Giant</var> mutex. If - <var class="Va">Giant</var> is held when cancelling or rescheduling the - callout, then its use will prevent races with the callout function.</p> - </li> - <li>The return value from <code class="Fn">callout_stop</code>() (or the - <code class="Fn">callout_reset</code>() and - <code class="Fn">callout_schedule</code>() function families) indicates - whether or not the callout was removed. If it is known that the callout - was set and the callout function has not yet executed, then a return value - of <code class="Dv">FALSE</code> indicates that the callout function is - about to be called. For example: - <div class="Bd Pp Bd-indent Li"> - <pre>if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) { - if (callout_stop(&sc->sc_callout)) { - sc->sc_flags &= ~SCFLG_CALLOUT_RUNNING; - /* successfully stopped */ - } else { - /* - * callout has expired and callout - * function is about to be executed - */ - } -}</pre> - </div> - </li> - <li>The <code class="Fn">callout_pending</code>(), - <code class="Fn">callout_active</code>() and - <code class="Fn">callout_deactivate</code>() macros can be used together - to work around the race conditions. When a callout's timeout is set, the - callout subsystem marks the callout as both <i class="Em">active</i> and - <i class="Em">pending</i>. When the timeout time arrives, the callout - subsystem begins processing the callout by first clearing the - <i class="Em">pending</i> flag. It then invokes the callout function - without changing the <i class="Em">active</i> flag, and does not clear the - <i class="Em">active</i> flag even after the callout function returns. The - mechanism described here requires the callout function itself to clear the - <i class="Em">active</i> flag using the - <code class="Fn">callout_deactivate</code>() macro. The - <code class="Fn">callout_stop</code>() and - <code class="Fn">callout_drain</code>() functions always clear both the - <i class="Em">active</i> and <i class="Em">pending</i> flags before - returning. - <p class="Pp" id="callout_pending~2">The callout function should first check - the <i class="Em">pending</i> flag and return without action if - <a class="permalink" href="#callout_pending~2"><code class="Fn">callout_pending</code></a>() - returns <code class="Dv">TRUE</code>. This indicates that the callout - was rescheduled using <code class="Fn">callout_reset</code>() just - before the callout function was invoked. If - <code class="Fn">callout_active</code>() returns - <code class="Dv">FALSE</code> then the callout function should also - return without action. This indicates that the callout has been stopped. - Finally, the callout function should call - <code class="Fn">callout_deactivate</code>() to clear the - <i class="Em">active</i> flag. For example:</p> - <div class="Bd Pp Bd-indent Li"> - <pre>mtx_lock(&sc->sc_mtx); -if (callout_pending(&sc->sc_callout)) { - /* callout was reset */ - mtx_unlock(&sc->sc_mtx); - return; -} -if (!callout_active(&sc->sc_callout)) { - /* callout was stopped */ - mtx_unlock(&sc->sc_mtx); - return; -} -callout_deactivate(&sc->sc_callout); -/* rest of callout function */</pre> - </div> - <p class="Pp" id="callout_stop~2">Together with appropriate synchronization, - such as the mutex used above, this approach permits the - <a class="permalink" href="#callout_stop~2"><code class="Fn">callout_stop</code></a>() - and <code class="Fn">callout_reset</code>() functions to be used at any - time without races. For example:</p> - <div class="Bd Pp Bd-indent Li"> - <pre>mtx_lock(&sc->sc_mtx); -callout_stop(&sc->sc_callout); -/* The callout is effectively stopped now. */</pre> - </div> - <p class="Pp" id="callout_deactivate">If the callout is still pending then - these functions operate normally, but if processing of the callout has - already begun then the tests in the callout function cause it to return - without further action. Synchronization between the callout function and - other code ensures that stopping or resetting the callout will never be - attempted while the callout function is past the - <a class="permalink" href="#callout_deactivate"><code class="Fn">callout_deactivate</code></a>() - call.</p> - <p class="Pp" id="callout_active">The above technique additionally ensures - that the <i class="Em">active</i> flag always reflects whether the - callout is effectively enabled or disabled. If - <a class="permalink" href="#callout_active"><code class="Fn">callout_active</code></a>() - returns false, then the callout is effectively disabled, since even if - the callout subsystem is actually just about to invoke the callout - function, the callout function will return without action.</p> - </li> -</ol> -<p class="Pp" id="callout_drain~2">There is one final race condition that must - be considered when a callout is being stopped for the last time. In this - case it may not be safe to let the callout function itself detect that the - callout was stopped, since it may need to access data objects that have - already been destroyed or recycled. To ensure that the callout is completely - finished, a call to - <a class="permalink" href="#callout_drain~2"><code class="Fn">callout_drain</code></a>() - should be used. In particular, a callout should always be drained prior to - destroying its associated lock or releasing the storage for the callout - structure.</p> -</section> -</section> -<section class="Sh"> -<h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN - VALUES</a></h1> -<p class="Pp">The <code class="Fn">callout_active</code>() macro returns the - state of a callout's <i class="Em">active</i> flag.</p> -<p class="Pp">The <code class="Fn">callout_pending</code>() macro returns the - state of a callout's <i class="Em">pending</i> flag.</p> -<p class="Pp">The <code class="Fn">callout_reset</code>() and - <code class="Fn">callout_schedule</code>() function families return a value - of one if the callout was pending before the new function invocation was - scheduled.</p> -<p class="Pp">The <code class="Fn">callout_stop</code>() and - <code class="Fn">callout_drain</code>() functions return a value of one if - the callout was still pending when it was called, a zero if the callout - could not be stopped and a negative one is it was either not running or has - already completed.</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE - ALSO</a></h1> -<p class="Pp"><a class="Xr">dtrace_callout_execute(4)</a></p> -</section> -<section class="Sh"> -<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1> -<p class="Pp"><span class="Ux">FreeBSD</span> initially used the long standing - <span class="Ux">BSD</span> linked list callout mechanism which offered O(n) - insertion and removal running time but did not generate or require handles - for untimeout operations.</p> -<p class="Pp"><span class="Ux">FreeBSD 3.0</span> introduced a new set of - timeout and untimeout routines from <span class="Ux">NetBSD</span> based on - the work of <span class="An">Adam M. Costello</span> and - <span class="An">George Varghese</span>, published in a technical report - entitled <span class="RsT">Redesigning the BSD Callout and Timer - Facilities</span> and modified for inclusion in - <span class="Ux">FreeBSD</span> by <span class="An">Justin T. Gibbs</span>. - The original work on the data structures used in that implementation was - published by <span class="An">G. Varghese</span> and <span class="An">A. - Lauck</span> in the paper <span class="RsT">Hashed and Hierarchical Timing - Wheels: Data Structures for the Efficient Implementation of a Timer - Facility</span> in the <i class="RsB">Proceedings of the 11th ACM Annual - Symposium on Operating Systems Principles.</i></p> -<p class="Pp"><span class="Ux">FreeBSD 3.3</span> introduced the first - implementations of <code class="Fn">callout_init</code>(), - <code class="Fn">callout_reset</code>(), and - <code class="Fn">callout_stop</code>() which permitted callers to allocate - dedicated storage for callouts. This ensured that a callout would always - fire unlike <code class="Fn">timeout</code>() which would silently fail if - it was unable to allocate a callout.</p> -<p class="Pp"><span class="Ux">FreeBSD 5.0</span> permitted callout handlers to - be tagged as MPSAFE via <code class="Fn">callout_init</code>().</p> -<p class="Pp"><span class="Ux">FreeBSD 5.3</span> introduced - <code class="Fn">callout_drain</code>().</p> -<p class="Pp"><span class="Ux">FreeBSD 6.0</span> introduced - <code class="Fn">callout_init_mtx</code>().</p> -<p class="Pp"><span class="Ux">FreeBSD 8.0</span> introduced per-CPU callout - wheels, <code class="Fn">callout_init_rw</code>(), and - <code class="Fn">callout_schedule</code>().</p> -<p class="Pp"><span class="Ux">FreeBSD 9.0</span> changed the underlying timer - interrupts used to drive callouts to prefer one-shot event timers instead of - a periodic timer interrupt.</p> -<p class="Pp"><span class="Ux">FreeBSD 10.0</span> switched the callout wheel to - support tickless operation. These changes introduced - <var class="Vt">sbintime_t</var> and the - <code class="Fn">callout_reset_sbt*</code>() family of functions. - <span class="Ux">FreeBSD 10.0</span> also added - <code class="Dv">C_DIRECT_EXEC</code> and - <code class="Fn">callout_init_rm</code>().</p> -<p class="Pp"><span class="Ux">FreeBSD 10.2</span> introduced the - <code class="Fn">callout_schedule_sbt*</code>() family of functions.</p> -<p class="Pp"><span class="Ux">FreeBSD 11.0</span> introduced - <code class="Fn">callout_async_drain</code>(). <span class="Ux">FreeBSD - 11.1</span> introduced <code class="Fn">callout_when</code>(). - <span class="Ux">FreeBSD 13.0</span> removed - <var class="Vt">timeout_t</var>, <code class="Fn">timeout</code>(), and - <code class="Fn">untimeout</code>().</p> -</section> -</div> -<table class="foot"> - <tr> - <td class="foot-date">November 4, 2025</td> - <td class="foot-os">FreeBSD 15.0</td> - </tr> -</table> |
