xref: /freebsd/share/man/man9/callout.9 (revision 6580f5c38dd5b01aeeaed16b370f1a12423437f0)
1.\"	$NetBSD: timeout.9,v 1.2 1996/06/23 22:32:34 pk Exp $
2.\"
3.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
4.\" All rights reserved.
5.\"
6.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by Paul Kranenburg.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
22.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE.
29.\"
30.Dd January 22, 2024
31.Dt CALLOUT 9
32.Os
33.Sh NAME
34.Nm callout_active ,
35.Nm callout_deactivate ,
36.Nm callout_drain ,
37.Nm callout_init ,
38.Nm callout_init_mtx ,
39.Nm callout_init_rm ,
40.Nm callout_init_rw ,
41.Nm callout_pending ,
42.Nm callout_reset ,
43.Nm callout_reset_curcpu ,
44.Nm callout_reset_on ,
45.Nm callout_reset_sbt ,
46.Nm callout_reset_sbt_curcpu ,
47.Nm callout_reset_sbt_on ,
48.Nm callout_schedule ,
49.Nm callout_schedule_curcpu ,
50.Nm callout_schedule_on ,
51.Nm callout_schedule_sbt ,
52.Nm callout_schedule_sbt_curcpu ,
53.Nm callout_schedule_sbt_on ,
54.Nm callout_stop ,
55.Nm callout_when
56.Nd execute a function after a specified length of time
57.Sh SYNOPSIS
58.In sys/types.h
59.In sys/callout.h
60.Bd -literal
61typedef void callout_func_t (void *);
62.Ed
63.Ft int
64.Fn callout_active "struct callout *c"
65.Ft void
66.Fn callout_deactivate "struct callout *c"
67.Ft int
68.Fn callout_drain "struct callout *c"
69.Ft void
70.Fn callout_init "struct callout *c" "int mpsafe"
71.Ft void
72.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags"
73.Ft void
74.Fn callout_init_rm "struct callout *c" "struct rmlock *rm" "int flags"
75.Ft void
76.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags"
77.Ft int
78.Fn callout_pending "struct callout *c"
79.Ft int
80.Fo callout_reset
81.Fa "struct callout *c"
82.Fa "int ticks"
83.Fa "callout_func_t *func"
84.Fa "void *arg"
85.Fc
86.Ft int
87.Fo callout_reset_curcpu
88.Fa "struct callout *c"
89.Fa "int ticks"
90.Fa "callout_func_t *func"
91.Fa "void *arg"
92.Fc
93.Ft int
94.Fo callout_reset_on
95.Fa "struct callout *c"
96.Fa "int ticks"
97.Fa "callout_func_t *func"
98.Fa "void *arg"
99.Fa "int cpu"
100.Fc
101.Ft int
102.Fo callout_reset_sbt
103.Fa "struct callout *c"
104.Fa "sbintime_t sbt"
105.Fa "sbintime_t pr"
106.Fa "callout_func_t *func"
107.Fa "void *arg"
108.Fa "int flags"
109.Fc
110.Ft int
111.Fo callout_reset_sbt_curcpu
112.Fa "struct callout *c"
113.Fa "sbintime_t sbt"
114.Fa "sbintime_t pr"
115.Fa "callout_func_t *func"
116.Fa "void *arg"
117.Fa "int flags"
118.Fc
119.Ft int
120.Fo callout_reset_sbt_on
121.Fa "struct callout *c"
122.Fa "sbintime_t sbt"
123.Fa "sbintime_t pr"
124.Fa "callout_func_t *func"
125.Fa "void *arg"
126.Fa "int cpu"
127.Fa "int flags"
128.Fc
129.Ft int
130.Fn callout_schedule "struct callout *c" "int ticks"
131.Ft int
132.Fn callout_schedule_curcpu "struct callout *c" "int ticks"
133.Ft int
134.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
135.Ft int
136.Fo callout_schedule_sbt
137.Fa "struct callout *c"
138.Fa "sbintime_t sbt"
139.Fa "sbintime_t pr"
140.Fa "int flags"
141.Fc
142.Ft int
143.Fo callout_schedule_sbt_curcpu
144.Fa "struct callout *c"
145.Fa "sbintime_t sbt"
146.Fa "sbintime_t pr"
147.Fa "int flags"
148.Fc
149.Ft int
150.Fo callout_schedule_sbt_on
151.Fa "struct callout *c"
152.Fa "sbintime_t sbt"
153.Fa "sbintime_t pr"
154.Fa "int cpu"
155.Fa "int flags"
156.Fc
157.Ft int
158.Fn callout_stop "struct callout *c"
159.Ft sbintime_t
160.Fo callout_when
161.Fa "sbintime_t sbt"
162.Fa "sbintime_t precision"
163.Fa "int flags"
164.Fa "sbintime_t *sbt_res"
165.Fa "sbintime_t *precision_res"
166.Fc
167.Sh DESCRIPTION
168The
169.Nm callout
170API is used to schedule a call to an arbitrary function at a specific
171time in the future.
172Consumers of this API are required to allocate a callout structure
173.Pq struct callout
174for each pending function invocation.
175This structure stores state about the pending function invocation including
176the function to be called and the time at which the function should be invoked.
177Pending function calls can be cancelled or rescheduled to a different time.
178In addition,
179a callout structure may be reused to schedule a new function call after a
180scheduled call is completed.
181.Pp
182Callouts only provide a single-shot mode.
183If a consumer requires a periodic timer,
184it must explicitly reschedule each function call.
185This is normally done by rescheduling the subsequent call within the called
186function.
187.Pp
188Callout functions must not sleep.
189They may not acquire sleepable locks,
190wait on condition variables,
191perform blocking allocation requests,
192or invoke any other action that might sleep.
193.Pp
194Each callout structure must be initialized by
195.Fn callout_init ,
196.Fn callout_init_mtx ,
197.Fn callout_init_rm ,
198or
199.Fn callout_init_rw
200before it is passed to any of the other callout functions.
201The
202.Fn callout_init
203function initializes a callout structure in
204.Fa c
205that is not associated with a specific lock.
206If the
207.Fa mpsafe
208argument is zero,
209the callout structure is not considered to be
210.Dq multi-processor safe ;
211and the Giant lock will be acquired before calling the callout function
212and released when the callout function returns.
213.Pp
214The
215.Fn callout_init_mtx ,
216.Fn callout_init_rm ,
217and
218.Fn callout_init_rw
219functions initialize a callout structure in
220.Fa c
221that is associated with a specific lock.
222The lock is specified by the
223.Fa mtx ,
224.Fa rm ,
225or
226.Fa rw
227parameter.
228The associated lock must be held while stopping or rescheduling the
229callout.
230The callout subsystem acquires the associated lock before calling the
231callout function and releases it after the function returns.
232If the callout was cancelled while the callout subsystem waited for the
233associated lock,
234the callout function is not called,
235and the associated lock is released.
236This ensures that stopping or rescheduling the callout will abort any
237previously scheduled invocation.
238.Pp
239A sleepable read-mostly lock
240.Po
241one initialized with the
242.Dv RM_SLEEPABLE
243flag
244.Pc
245may not be used with
246.Fn callout_init_rm .
247Similarly, other sleepable lock types such as
248.Xr sx 9
249and
250.Xr lockmgr 9
251cannot be used with callouts because sleeping is not permitted in
252the callout subsystem.
253.Pp
254These
255.Fa flags
256may be specified for
257.Fn callout_init_mtx ,
258.Fn callout_init_rm ,
259or
260.Fn callout_init_rw :
261.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED"
262.It Dv CALLOUT_RETURNUNLOCKED
263The callout function will release the associated lock itself,
264so the callout subsystem should not attempt to unlock it
265after the callout function returns.
266.It Dv CALLOUT_SHAREDLOCK
267The lock is only acquired in read mode when running the callout handler.
268This flag is ignored by
269.Fn callout_init_mtx .
270.El
271.Pp
272The function
273.Fn callout_stop
274cancels a callout
275.Fa c
276if it is currently pending.
277If the callout is pending and successfully stopped, then
278.Fn callout_stop
279returns a value of one.
280If the callout is not set, or
281has already been serviced, then
282negative one is returned.
283If the callout is currently being serviced and cannot be stopped,
284then zero will be returned.
285If the callout is currently being serviced and cannot be stopped, and at the
286same time a next invocation of the same callout is also scheduled, then
287.Fn callout_stop
288unschedules the next run and returns zero.
289If the callout has an associated lock,
290then that lock must be held when this function is called.
291.Pp
292The function
293.Fn callout_drain
294is identical to
295.Fn callout_stop
296except that it will wait for the callout
297.Fa c
298to complete if it is already in progress.
299This function MUST NOT be called while holding any
300locks on which the callout might block, or deadlock will result.
301Note that if the callout subsystem has already begun processing this
302callout, then the callout function may be invoked before
303.Fn callout_drain
304returns.
305However, the callout subsystem does guarantee that the callout will be
306fully stopped before
307.Fn callout_drain
308returns.
309.Pp
310The
311.Fn callout_reset
312and
313.Fn callout_schedule
314function families schedule a future function invocation for callout
315.Fa c .
316If
317.Fa c
318already has a pending callout,
319it is cancelled before the new invocation is scheduled.
320These functions return a value of one if a pending callout was cancelled
321and zero if there was no pending callout.
322If the callout has an associated lock,
323then that lock must be held when any of these functions are called.
324.Pp
325The time at which the callout function will be invoked is determined by
326either the
327.Fa ticks
328argument or the
329.Fa sbt ,
330.Fa pr ,
331and
332.Fa flags
333arguments.
334When
335.Fa ticks
336is used,
337the callout is scheduled to execute after
338.Fa ticks Ns No /hz
339seconds.
340Non-positive values of
341.Fa ticks
342are silently converted to the value
343.Sq 1 .
344.Pp
345The
346.Fa sbt ,
347.Fa pr ,
348and
349.Fa flags
350arguments provide more control over the scheduled time including
351support for higher resolution times,
352specifying the precision of the scheduled time,
353and setting an absolute deadline instead of a relative timeout.
354The callout is scheduled to execute in a time window which begins at
355the time specified in
356.Fa sbt
357and extends for the amount of time specified in
358.Fa pr .
359If
360.Fa sbt
361specifies a time in the past,
362the window is adjusted to start at the current time.
363A non-zero value for
364.Fa pr
365allows the callout subsystem to coalesce callouts scheduled close to each
366other into fewer timer interrupts,
367reducing processing overhead and power consumption.
368These
369.Fa flags
370may be specified to adjust the interpretation of
371.Fa sbt
372and
373.Fa pr :
374.Bl -tag -width ".Dv C_DIRECT_EXEC"
375.It Dv C_ABSOLUTE
376Handle the
377.Fa sbt
378argument as an absolute time since boot.
379By default,
380.Fa sbt
381is treated as a relative amount of time,
382similar to
383.Fa ticks .
384.It Dv C_DIRECT_EXEC
385Run the handler directly from hardware interrupt context instead of from the
386softclock thread.
387This reduces latency and overhead, but puts more constraints on the callout
388function.
389Callout functions run in this context may use only spin mutexes for locking
390and should be as small as possible because they run with absolute priority.
391.It Fn C_PREL
392Specifies relative event time precision as binary logarithm of time interval
393divided by acceptable time deviation: 1 -- 1/2, 2 -- 1/4, etc.
394Note that the larger of
395.Fa pr
396or this value is used as the length of the time window.
397Smaller values
398.Pq which result in larger time intervals
399allow the callout subsystem to aggregate more events in one timer interrupt.
400.It Dv C_PRECALC
401The
402.Fa sbt
403argument specifies the absolute time at which the callout should be run,
404and the
405.Fa pr
406argument specifies the requested precision, which will not be
407adjusted during the scheduling process.
408The
409.Fa sbt
410and
411.Fa pr
412values should be calculated by an earlier call to
413.Fn callout_when
414which uses the user-supplied
415.Fa sbt ,
416.Fa pr ,
417and
418.Fa flags
419values.
420.It Dv C_HARDCLOCK
421Align the timeouts to
422.Fn hardclock
423calls if possible.
424.El
425.Pp
426The
427.Fn callout_reset
428functions accept a
429.Fa func
430argument which identifies the function to be called when the time expires.
431It must be a pointer to a function that takes a single
432.Fa void *
433argument.
434Upon invocation,
435.Fa func
436will receive
437.Fa arg
438as its only argument.
439The
440.Fn callout_schedule
441functions reuse the
442.Fa func
443and
444.Fa arg
445arguments from the previous callout.
446Note that one of the
447.Fn callout_reset
448functions must always be called to initialize
449.Fa func
450and
451.Fa arg
452before one of the
453.Fn callout_schedule
454functions can be used.
455.Pp
456The callout subsystem provides a softclock thread for each CPU in the system.
457Callouts are assigned to a single CPU and are executed by the softclock thread
458for that CPU.
459Initially,
460callouts are assigned to CPU 0.
461The
462.Fn callout_reset_on ,
463.Fn callout_reset_sbt_on ,
464.Fn callout_schedule_on
465and
466.Fn callout_schedule_sbt_on
467functions assign the callout to CPU
468.Fa cpu .
469The
470.Fn callout_reset_curcpu ,
471.Fn callout_reset_sbt_curpu ,
472.Fn callout_schedule_curcpu
473and
474.Fn callout_schedule_sbt_curcpu
475functions assign the callout to the current CPU.
476The
477.Fn callout_reset ,
478.Fn callout_reset_sbt ,
479.Fn callout_schedule
480and
481.Fn callout_schedule_sbt
482functions schedule the callout to execute in the softclock thread of the CPU
483to which it is currently assigned.
484.Pp
485Softclock threads are not pinned to their respective CPUs by default.
486The softclock thread for CPU 0 can be pinned to CPU 0 by setting the
487.Va kern.pin_default_swi
488loader tunable to a non-zero value.
489Softclock threads for CPUs other than zero can be pinned to their
490respective CPUs by setting the
491.Va kern.pin_pcpu_swi
492loader tunable to a non-zero value.
493.Pp
494The macros
495.Fn callout_pending ,
496.Fn callout_active
497and
498.Fn callout_deactivate
499provide access to the current state of the callout.
500The
501.Fn callout_pending
502macro checks whether a callout is
503.Em pending ;
504a callout is considered
505.Em pending
506when a timeout has been set but the time has not yet arrived.
507Note that once the timeout time arrives and the callout subsystem
508starts to process this callout,
509.Fn callout_pending
510will return
511.Dv FALSE
512even though the callout function may not have finished
513.Pq or even begun
514executing.
515The
516.Fn callout_active
517macro checks whether a callout is marked as
518.Em active ,
519and the
520.Fn callout_deactivate
521macro clears the callout's
522.Em active
523flag.
524The callout subsystem marks a callout as
525.Em active
526when a timeout is set and it clears the
527.Em active
528flag in
529.Fn callout_stop
530and
531.Fn callout_drain ,
532but it
533.Em does not
534clear it when a callout expires normally via the execution of the
535callout function.
536.Pp
537The
538.Fn callout_when
539function may be used to pre-calculate the absolute time at which the
540timeout should be run and the precision of the scheduled run time
541according to the required time
542.Fa sbt ,
543precision
544.Fa precision ,
545and additional adjustments requested by the
546.Fa flags
547argument.
548Flags accepted by the
549.Fn callout_when
550function are the same as flags for the
551.Fn callout_reset
552function.
553The resulting time is assigned to the variable pointed to by the
554.Fa sbt_res
555argument, and the resulting precision is assigned to
556.Fa *precision_res .
557When passing the results to
558.Fa callout_reset ,
559add the
560.Va C_PRECALC
561flag to
562.Fa flags ,
563to avoid incorrect re-adjustment.
564The function is intended for situations where precise time of the callout
565run should be known in advance, since
566trying to read this time from the callout structure itself after a
567.Fn callout_reset
568call is racy.
569.Ss "Avoiding Race Conditions"
570The callout subsystem invokes callout functions from its own thread
571context.
572Without some kind of synchronization,
573it is possible that a callout
574function will be invoked concurrently with an attempt to stop or reset
575the callout by another thread.
576In particular, since callout functions typically acquire a lock as
577their first action, the callout function may have already been invoked,
578but is blocked waiting for that lock at the time that another thread
579tries to reset or stop the callout.
580.Pp
581There are three main techniques for addressing these
582synchronization concerns.
583The first approach is preferred as it is the simplest:
584.Bl -enum -offset indent
585.It
586Callouts can be associated with a specific lock when they are initialized
587by
588.Fn callout_init_mtx ,
589.Fn callout_init_rm ,
590or
591.Fn callout_init_rw .
592When a callout is associated with a lock,
593the callout subsystem acquires the lock before the callout function is
594invoked.
595This allows the callout subsystem to transparently handle races between
596callout cancellation,
597scheduling,
598and execution.
599Note that the associated lock must be acquired before calling
600.Fn callout_stop
601or one of the
602.Fn callout_reset
603or
604.Fn callout_schedule
605functions to provide this safety.
606.Pp
607A callout initialized via
608.Fn callout_init
609with
610.Fa mpsafe
611set to zero is implicitly associated with the
612.Va Giant
613mutex.
614If
615.Va Giant
616is held when cancelling or rescheduling the callout,
617then its use will prevent races with the callout function.
618.It
619The return value from
620.Fn callout_stop
621.Po
622or the
623.Fn callout_reset
624and
625.Fn callout_schedule
626function families
627.Pc
628indicates whether or not the callout was removed.
629If it is known that the callout was set and the callout function has
630not yet executed, then a return value of
631.Dv FALSE
632indicates that the callout function is about to be called.
633For example:
634.Bd -literal -offset indent
635if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) {
636	if (callout_stop(&sc->sc_callout)) {
637		sc->sc_flags &= ~SCFLG_CALLOUT_RUNNING;
638		/* successfully stopped */
639	} else {
640		/*
641		 * callout has expired and callout
642		 * function is about to be executed
643		 */
644	}
645}
646.Ed
647.It
648The
649.Fn callout_pending ,
650.Fn callout_active
651and
652.Fn callout_deactivate
653macros can be used together to work around the race conditions.
654When a callout's timeout is set, the callout subsystem marks the
655callout as both
656.Em active
657and
658.Em pending .
659When the timeout time arrives, the callout subsystem begins processing
660the callout by first clearing the
661.Em pending
662flag.
663It then invokes the callout function without changing the
664.Em active
665flag, and does not clear the
666.Em active
667flag even after the callout function returns.
668The mechanism described here requires the callout function itself to
669clear the
670.Em active
671flag using the
672.Fn callout_deactivate
673macro.
674The
675.Fn callout_stop
676and
677.Fn callout_drain
678functions always clear both the
679.Em active
680and
681.Em pending
682flags before returning.
683.Pp
684The callout function should first check the
685.Em pending
686flag and return without action if
687.Fn callout_pending
688returns
689.Dv TRUE .
690This indicates that the callout was rescheduled using
691.Fn callout_reset
692just before the callout function was invoked.
693If
694.Fn callout_active
695returns
696.Dv FALSE
697then the callout function should also return without action.
698This indicates that the callout has been stopped.
699Finally, the callout function should call
700.Fn callout_deactivate
701to clear the
702.Em active
703flag.
704For example:
705.Bd -literal -offset indent
706mtx_lock(&sc->sc_mtx);
707if (callout_pending(&sc->sc_callout)) {
708	/* callout was reset */
709	mtx_unlock(&sc->sc_mtx);
710	return;
711}
712if (!callout_active(&sc->sc_callout)) {
713	/* callout was stopped */
714	mtx_unlock(&sc->sc_mtx);
715	return;
716}
717callout_deactivate(&sc->sc_callout);
718/* rest of callout function */
719.Ed
720.Pp
721Together with appropriate synchronization, such as the mutex used above,
722this approach permits the
723.Fn callout_stop
724and
725.Fn callout_reset
726functions to be used at any time without races.
727For example:
728.Bd -literal -offset indent
729mtx_lock(&sc->sc_mtx);
730callout_stop(&sc->sc_callout);
731/* The callout is effectively stopped now. */
732.Ed
733.Pp
734If the callout is still pending then these functions operate normally,
735but if processing of the callout has already begun then the tests in
736the callout function cause it to return without further action.
737Synchronization between the callout function and other code ensures that
738stopping or resetting the callout will never be attempted while the
739callout function is past the
740.Fn callout_deactivate
741call.
742.Pp
743The above technique additionally ensures that the
744.Em active
745flag always reflects whether the callout is effectively enabled or
746disabled.
747If
748.Fn callout_active
749returns false, then the callout is effectively disabled, since even if
750the callout subsystem is actually just about to invoke the callout
751function, the callout function will return without action.
752.El
753.Pp
754There is one final race condition that must be considered when a
755callout is being stopped for the last time.
756In this case it may not be safe to let the callout function itself
757detect that the callout was stopped, since it may need to access
758data objects that have already been destroyed or recycled.
759To ensure that the callout is completely finished, a call to
760.Fn callout_drain
761should be used.
762In particular,
763a callout should always be drained prior to destroying its associated lock
764or releasing the storage for the callout structure.
765.Sh RETURN VALUES
766The
767.Fn callout_active
768macro returns the state of a callout's
769.Em active
770flag.
771.Pp
772The
773.Fn callout_pending
774macro returns the state of a callout's
775.Em pending
776flag.
777.Pp
778The
779.Fn callout_reset
780and
781.Fn callout_schedule
782function families return a value of one if the callout was pending before the new
783function invocation was scheduled.
784.Pp
785The
786.Fn callout_stop
787and
788.Fn callout_drain
789functions return a value of one if the callout was still pending when it was
790called, a zero if the callout could not be stopped and a negative one is it
791was either not running or has already completed.
792.Sh HISTORY
793.Fx
794initially used the long standing
795.Bx
796linked list
797callout mechanism which offered O(n) insertion and removal running time
798but did not generate or require handles for untimeout operations.
799.Pp
800.Fx 3.0
801introduced a new set of timeout and untimeout routines from
802.Nx
803based on the work of
804.An Adam M. Costello
805and
806.An George Varghese ,
807published in a technical report entitled
808.%T "Redesigning the BSD Callout and Timer Facilities"
809and modified for inclusion in
810.Fx
811by
812.An Justin T. Gibbs .
813The original work on the data structures used in that implementation
814was published by
815.An G. Varghese
816and
817.An A. Lauck
818in the paper
819.%T "Hashed and Hierarchical Timing Wheels: Data Structures for the Efficient Implementation of a Timer Facility"
820in the
821.%B "Proceedings of the 11th ACM Annual Symposium on Operating Systems Principles" .
822.Pp
823.Fx 3.3
824introduced the first implementations of
825.Fn callout_init ,
826.Fn callout_reset ,
827and
828.Fn callout_stop
829which permitted callers to allocate dedicated storage for callouts.
830This ensured that a callout would always fire unlike
831.Fn timeout
832which would silently fail if it was unable to allocate a callout.
833.Pp
834.Fx 5.0
835permitted callout handlers to be tagged as MPSAFE via
836.Fn callout_init .
837.Pp
838.Fx 5.3
839introduced
840.Fn callout_drain .
841.Pp
842.Fx 6.0
843introduced
844.Fn callout_init_mtx .
845.Pp
846.Fx 8.0
847introduced per-CPU callout wheels,
848.Fn callout_init_rw ,
849and
850.Fn callout_schedule .
851.Pp
852.Fx 9.0
853changed the underlying timer interrupts used to drive callouts to prefer
854one-shot event timers instead of a periodic timer interrupt.
855.Pp
856.Fx 10.0
857switched the callout wheel to support tickless operation.
858These changes introduced
859.Vt sbintime_t
860and the
861.Fn callout_reset_sbt*
862family of functions.
863.Fx 10.0 also added
864.Dv C_DIRECT_EXEC
865and
866.Fn callout_init_rm .
867.Pp
868.Fx 10.2
869introduced the
870.Fn callout_schedule_sbt*
871family of functions.
872.Pp
873.Fx 11.0
874introduced
875.Fn callout_async_drain .
876.Fx 11.1
877introduced
878.Fn callout_when .
879.Fx 13.0
880removed
881.Vt timeout_t ,
882.Fn timeout ,
883and
884.Fn untimeout .
885