Page MenuHomeFreeBSD

D22602.diff
No OneTemporary

D22602.diff

Index: head/ObsoleteFiles.inc
===================================================================
--- head/ObsoleteFiles.inc
+++ head/ObsoleteFiles.inc
@@ -36,6 +36,9 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20191213: remove timeout(9)
+OLD_FILES+=usr/share/man/man9/timeout.9.gz
+OLD_FILES+=usr/share/man/man9/untimeout.9.gz
# 20191128: Removal of trm(4)
OLD_FILES+=usr/share/man/man4/trm.4.gz
# 20191121: Removal of sio(4)
Index: head/share/man/man9/Makefile
===================================================================
--- head/share/man/man9/Makefile
+++ head/share/man/man9/Makefile
@@ -56,6 +56,7 @@
BUS_SETUP_INTR.9 \
bus_space.9 \
byteorder.9 \
+ callout.9 \
casuword.9 \
cd.9 \
cnv.9 \
@@ -315,7 +316,6 @@
tcp_functions.9 \
thread_exit.9 \
time.9 \
- timeout.9 \
tvtohz.9 \
ucred.9 \
uidinfo.9 \
@@ -766,6 +766,30 @@
byteorder.9 le64dec.9 \
byteorder.9 le64enc.9 \
byteorder.9 le64toh.9
+MLINKS+=callout.9 callout_active.9 \
+ callout.9 callout_async_drain.9 \
+ callout.9 callout_deactivate.9 \
+ callout.9 callout_drain.9 \
+ callout.9 callout_handle_init.9 \
+ callout.9 callout_init.9 \
+ callout.9 callout_init_mtx.9 \
+ callout.9 callout_init_rm.9 \
+ callout.9 callout_init_rw.9 \
+ callout.9 callout_pending.9 \
+ callout.9 callout_reset.9 \
+ callout.9 callout_reset_curcpu.9 \
+ callout.9 callout_reset_on.9 \
+ callout.9 callout_reset_sbt.9 \
+ callout.9 callout_reset_sbt_curcpu.9 \
+ callout.9 callout_reset_sbt_on.9 \
+ callout.9 callout_schedule.9 \
+ callout.9 callout_schedule_curcpu.9 \
+ callout.9 callout_schedule_on.9 \
+ callout.9 callout_schedule_sbt.9 \
+ callout.9 callout_schedule_sbt_curcpu.9 \
+ callout.9 callout_schedule_sbt_on.9 \
+ callout.9 callout_stop.9 \
+ callout.9 callout_when.9
MLINKS+=cnv.9 cnvlist.9 \
cnv.9 cnvlist_free_binary.9 \
cnv.9 cnvlist_free_bool.9 \
@@ -2097,32 +2121,6 @@
MLINKS+=time.9 boottime.9 \
time.9 time_second.9 \
time.9 time_uptime.9
-MLINKS+=timeout.9 callout.9 \
- timeout.9 callout_active.9 \
- timeout.9 callout_async_drain.9 \
- timeout.9 callout_deactivate.9 \
- timeout.9 callout_drain.9 \
- timeout.9 callout_handle_init.9 \
- timeout.9 callout_init.9 \
- timeout.9 callout_init_mtx.9 \
- timeout.9 callout_init_rm.9 \
- timeout.9 callout_init_rw.9 \
- timeout.9 callout_pending.9 \
- timeout.9 callout_reset.9 \
- timeout.9 callout_reset_curcpu.9 \
- timeout.9 callout_reset_on.9 \
- timeout.9 callout_reset_sbt.9 \
- timeout.9 callout_reset_sbt_curcpu.9 \
- timeout.9 callout_reset_sbt_on.9 \
- timeout.9 callout_schedule.9 \
- timeout.9 callout_schedule_curcpu.9 \
- timeout.9 callout_schedule_on.9 \
- timeout.9 callout_schedule_sbt.9 \
- timeout.9 callout_schedule_sbt_curcpu.9 \
- timeout.9 callout_schedule_sbt_on.9 \
- timeout.9 callout_stop.9 \
- timeout.9 callout_when.9 \
- timeout.9 untimeout.9
MLINKS+=ucred.9 crcopy.9 \
ucred.9 crcopysafe.9 \
ucred.9 crdup.9 \
Index: head/share/man/man9/callout.9
===================================================================
--- head/share/man/man9/callout.9
+++ head/share/man/man9/callout.9
@@ -0,0 +1,922 @@
+.\" $NetBSD: timeout.9,v 1.2 1996/06/23 22:32:34 pk Exp $
+.\"
+.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Paul Kranenburg.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 13, 2019
+.Dt CALLOUT 9
+.Os
+.Sh NAME
+.Nm callout_active ,
+.Nm callout_deactivate ,
+.Nm callout_async_drain ,
+.Nm callout_drain ,
+.Nm callout_handle_init ,
+.Nm callout_init ,
+.Nm callout_init_mtx ,
+.Nm callout_init_rm ,
+.Nm callout_init_rw ,
+.Nm callout_pending ,
+.Nm callout_reset ,
+.Nm callout_reset_curcpu ,
+.Nm callout_reset_on ,
+.Nm callout_reset_sbt ,
+.Nm callout_reset_sbt_curcpu ,
+.Nm callout_reset_sbt_on ,
+.Nm callout_schedule ,
+.Nm callout_schedule_curcpu ,
+.Nm callout_schedule_on ,
+.Nm callout_schedule_sbt ,
+.Nm callout_schedule_sbt_curcpu ,
+.Nm callout_schedule_sbt_on ,
+.Nm callout_stop ,
+.Nm callout_when
+.Nd execute a function after a specified length of time
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/callout.h
+.Bd -literal
+typedef void callout_func_t (void *);
+.Ed
+.Ft int
+.Fn callout_active "struct callout *c"
+.Ft void
+.Fn callout_deactivate "struct callout *c"
+.Ft int
+.Fn callout_async_drain "struct callout *c" "callout_func_t *drain"
+.Ft int
+.Fn callout_drain "struct callout *c"
+.Ft void
+.Fn callout_handle_init "struct callout_handle *handle"
+.Bd -literal
+struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
+.Ed
+.Ft void
+.Fn callout_init "struct callout *c" "int mpsafe"
+.Ft void
+.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags"
+.Ft void
+.Fn callout_init_rm "struct callout *c" "struct rmlock *rm" "int flags"
+.Ft void
+.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags"
+.Ft int
+.Fn callout_pending "struct callout *c"
+.Ft int
+.Fo callout_reset
+.Fa "struct callout *c"
+.Fa "int ticks"
+.Fa "callout_func_t *func"
+.Fa "void *arg"
+.Fc
+.Ft int
+.Fo callout_reset_curcpu
+.Fa "struct callout *c"
+.Fa "int ticks"
+.Fa "callout_func_t *func"
+.Fa "void *arg"
+.Fc
+.Ft int
+.Fo callout_reset_on
+.Fa "struct callout *c"
+.Fa "int ticks"
+.Fa "callout_func_t *func"
+.Fa "void *arg"
+.Fa "int cpu"
+.Fc
+.Ft int
+.Fo callout_reset_sbt
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "callout_func_t *func"
+.Fa "void *arg"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_reset_sbt_curcpu
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "callout_func_t *func"
+.Fa "void *arg"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_reset_sbt_on
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "callout_func_t *func"
+.Fa "void *arg"
+.Fa "int cpu"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fn callout_schedule "struct callout *c" "int ticks"
+.Ft int
+.Fn callout_schedule_curcpu "struct callout *c" "int ticks"
+.Ft int
+.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
+.Ft int
+.Fo callout_schedule_sbt
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_schedule_sbt_curcpu
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fo callout_schedule_sbt_on
+.Fa "struct callout *c"
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t pr"
+.Fa "int cpu"
+.Fa "int flags"
+.Fc
+.Ft int
+.Fn callout_stop "struct callout *c"
+.Ft sbintime_t
+.Fo callout_when
+.Fa "sbintime_t sbt"
+.Fa "sbintime_t precision"
+.Fa "int flags"
+.Fa "sbintime_t *sbt_res"
+.Fa "sbintime_t *precision_res"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm callout
+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
+.Pq 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.
+.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.
+.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.
+.Pp
+Each callout structure must be initialized by
+.Fn callout_init ,
+.Fn callout_init_mtx ,
+.Fn callout_init_rm ,
+or
+.Fn callout_init_rw
+before it is passed to any of the other callout functions.
+The
+.Fn callout_init
+function initializes a callout structure in
+.Fa c
+that is not associated with a specific lock.
+If the
+.Fa mpsafe
+argument is zero,
+the callout structure is not considered to be
+.Dq multi-processor safe ;
+and the Giant lock will be acquired before calling the callout function
+and released when the callout function returns.
+.Pp
+The
+.Fn callout_init_mtx ,
+.Fn callout_init_rm ,
+and
+.Fn callout_init_rw
+functions initialize a callout structure in
+.Fa c
+that is associated with a specific lock.
+The lock is specified by the
+.Fa mtx ,
+.Fa rm ,
+or
+.Fa rw
+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.
+.Pp
+Only regular mutexes may be used with
+.Fn callout_init_mtx ;
+spin mutexes are not supported.
+A sleepable read-mostly lock
+.Po
+one initialized with the
+.Dv RM_SLEEPABLE
+flag
+.Pc
+may not be used with
+.Fn callout_init_rm .
+Similarly, other sleepable lock types such as
+.Xr sx 9
+and
+.Xr lockmgr 9
+cannot be used with callouts because sleeping is not permitted in
+the callout subsystem.
+.Pp
+These
+.Fa flags
+may be specified for
+.Fn callout_init_mtx ,
+.Fn callout_init_rm ,
+or
+.Fn callout_init_rw :
+.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED"
+.It Dv CALLOUT_RETURNUNLOCKED
+The callout function will release the associated lock itself,
+so the callout subsystem should not attempt to unlock it
+after the callout function returns.
+.It Dv CALLOUT_SHAREDLOCK
+The lock is only acquired in read mode when running the callout handler.
+This flag is ignored by
+.Fn callout_init_mtx .
+.El
+.Pp
+The function
+.Fn callout_stop
+cancels a callout
+.Fa c
+if it is currently pending.
+If the callout is pending and successfully stopped, then
+.Fn callout_stop
+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
+.Fn callout_stop
+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.
+.Pp
+The function
+.Fn callout_async_drain
+is identical to
+.Fn callout_stop
+with one difference.
+When
+.Fn callout_async_drain
+returns zero it will arrange for the function
+.Fa drain
+to be called using the same argument given to the
+.Fn callout_reset
+function.
+.Fn callout_async_drain
+If the callout has an associated lock,
+then that lock must be held when this function is called.
+Note that when stopping multiple callouts that use the same lock it is possible
+to get multiple return's of zero and multiple calls to the
+.Fa drain
+function, depending upon which CPU's the callouts are running.
+The
+.Fa drain
+function itself is called from the context of the completing callout
+i.e. softclock or hardclock, just like a callout itself.
+.Pp
+The function
+.Fn callout_drain
+is identical to
+.Fn callout_stop
+except that it will wait for the callout
+.Fa c
+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
+.Fn callout_drain
+returns.
+However, the callout subsystem does guarantee that the callout will be
+fully stopped before
+.Fn callout_drain
+returns.
+.Pp
+The
+.Fn callout_reset
+and
+.Fn callout_schedule
+function families schedule a future function invocation for callout
+.Fa c .
+If
+.Fa c
+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.
+.Pp
+The time at which the callout function will be invoked is determined by
+either the
+.Fa ticks
+argument or the
+.Fa sbt ,
+.Fa pr ,
+and
+.Fa flags
+arguments.
+When
+.Fa ticks
+is used,
+the callout is scheduled to execute after
+.Fa ticks Ns No /hz
+seconds.
+Non-positive values of
+.Fa ticks
+are silently converted to the value
+.Sq 1 .
+.Pp
+The
+.Fa sbt ,
+.Fa pr ,
+and
+.Fa flags
+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
+.Fa sbt
+and extends for the amount of time specified in
+.Fa pr .
+If
+.Fa sbt
+specifies a time in the past,
+the window is adjusted to start at the current time.
+A non-zero value for
+.Fa pr
+allows the callout subsystem to coalesce callouts scheduled close to each
+other into fewer timer interrupts,
+reducing processing overhead and power consumption.
+These
+.Fa flags
+may be specified to adjust the interpretation of
+.Fa sbt
+and
+.Fa pr :
+.Bl -tag -width ".Dv C_DIRECT_EXEC"
+.It Dv C_ABSOLUTE
+Handle the
+.Fa sbt
+argument as an absolute time since boot.
+By default,
+.Fa sbt
+is treated as a relative amount of time,
+similar to
+.Fa ticks .
+.It Dv C_DIRECT_EXEC
+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.
+.It Fn C_PREL
+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
+.Fa pr
+or this value is used as the length of the time window.
+Smaller values
+.Pq which result in larger time intervals
+allow the callout subsystem to aggregate more events in one timer interrupt.
+.It Dv C_PRECALC
+The
+.Fa sbt
+argument specifies the absolute time at which the callout should be run,
+and the
+.Fa pr
+argument specifies the requested precision, which will not be
+adjusted during the scheduling process.
+The
+.Fa sbt
+and
+.Fa pr
+values should be calculated by an earlier call to
+.Fn callout_when
+which uses the user-supplied
+.Fa sbt ,
+.Fa pr ,
+and
+.Fa flags
+values.
+.It Dv C_HARDCLOCK
+Align the timeouts to
+.Fn hardclock
+calls if possible.
+.El
+.Pp
+The
+.Fn callout_reset
+functions accept a
+.Fa func
+argument which identifies the function to be called when the time expires.
+It must be a pointer to a function that takes a single
+.Fa void *
+argument.
+Upon invocation,
+.Fa func
+will receive
+.Fa arg
+as its only argument.
+The
+.Fn callout_schedule
+functions reuse the
+.Fa func
+and
+.Fa arg
+arguments from the previous callout.
+Note that one of the
+.Fn callout_reset
+functions must always be called to initialize
+.Fa func
+and
+.Fa arg
+before one of the
+.Fn callout_schedule
+functions can be used.
+.Pp
+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
+.Fn callout_reset_on ,
+.Fn callout_reset_sbt_on ,
+.Fn callout_schedule_on
+and
+.Fn callout_schedule_sbt_on
+functions assign the callout to CPU
+.Fa cpu .
+The
+.Fn callout_reset_curcpu ,
+.Fn callout_reset_sbt_curpu ,
+.Fn callout_schedule_curcpu
+and
+.Fn callout_schedule_sbt_curcpu
+functions assign the callout to the current CPU.
+The
+.Fn callout_reset ,
+.Fn callout_reset_sbt ,
+.Fn callout_schedule
+and
+.Fn callout_schedule_sbt
+functions schedule the callout to execute in the softclock thread of the CPU
+to which it is currently assigned.
+.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
+.Va kern.pin_default_swi
+loader tunable to a non-zero value.
+Softclock threads for CPUs other than zero can be pinned to their
+respective CPUs by setting the
+.Va kern.pin_pcpu_swi
+loader tunable to a non-zero value.
+.Pp
+The macros
+.Fn callout_pending ,
+.Fn callout_active
+and
+.Fn callout_deactivate
+provide access to the current state of the callout.
+The
+.Fn callout_pending
+macro checks whether a callout is
+.Em pending ;
+a callout is considered
+.Em pending
+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,
+.Fn callout_pending
+will return
+.Dv FALSE
+even though the callout function may not have finished
+.Pq or even begun
+executing.
+The
+.Fn callout_active
+macro checks whether a callout is marked as
+.Em active ,
+and the
+.Fn callout_deactivate
+macro clears the callout's
+.Em active
+flag.
+The callout subsystem marks a callout as
+.Em active
+when a timeout is set and it clears the
+.Em active
+flag in
+.Fn callout_stop
+and
+.Fn callout_drain ,
+but it
+.Em does not
+clear it when a callout expires normally via the execution of the
+callout function.
+.Pp
+The
+.Fn callout_when
+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
+.Fa sbt ,
+precision
+.Fa precision ,
+and additional adjustments requested by the
+.Fa flags
+argument.
+Flags accepted by the
+.Fn callout_when
+function are the same as flags for the
+.Fn callout_reset
+function.
+The resulting time is assigned to the variable pointed to by the
+.Fa sbt_res
+argument, and the resulting precision is assigned to
+.Fa *precision_res .
+When passing the results to
+.Fa callout_reset ,
+add the
+.Va C_PRECALC
+flag to
+.Fa flags ,
+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
+.Fn callout_reset
+call is racy.
+.Ss "Avoiding Race Conditions"
+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.
+.Pp
+There are three main techniques for addressing these
+synchronization concerns.
+The first approach is preferred as it is the simplest:
+.Bl -enum -offset indent
+.It
+Callouts can be associated with a specific lock when they are initialized
+by
+.Fn callout_init_mtx ,
+.Fn callout_init_rm ,
+or
+.Fn callout_init_rw .
+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
+.Fn callout_stop
+or one of the
+.Fn callout_reset
+or
+.Fn callout_schedule
+functions to provide this safety.
+.Pp
+A callout initialized via
+.Fn callout_init
+with
+.Fa mpsafe
+set to zero is implicitly associated with the
+.Va Giant
+mutex.
+If
+.Va Giant
+is held when cancelling or rescheduling the callout,
+then its use will prevent races with the callout function.
+.It
+The return value from
+.Fn callout_stop
+.Po
+or the
+.Fn callout_reset
+and
+.Fn callout_schedule
+function families
+.Pc
+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
+.Dv FALSE
+indicates that the callout function is about to be called.
+For example:
+.Bd -literal -offset indent
+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
+ */
+ }
+}
+.Ed
+.It
+The
+.Fn callout_pending ,
+.Fn callout_active
+and
+.Fn callout_deactivate
+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
+.Em active
+and
+.Em pending .
+When the timeout time arrives, the callout subsystem begins processing
+the callout by first clearing the
+.Em pending
+flag.
+It then invokes the callout function without changing the
+.Em active
+flag, and does not clear the
+.Em active
+flag even after the callout function returns.
+The mechanism described here requires the callout function itself to
+clear the
+.Em active
+flag using the
+.Fn callout_deactivate
+macro.
+The
+.Fn callout_stop
+and
+.Fn callout_drain
+functions always clear both the
+.Em active
+and
+.Em pending
+flags before returning.
+.Pp
+The callout function should first check the
+.Em pending
+flag and return without action if
+.Fn callout_pending
+returns
+.Dv TRUE .
+This indicates that the callout was rescheduled using
+.Fn callout_reset
+just before the callout function was invoked.
+If
+.Fn callout_active
+returns
+.Dv FALSE
+then the callout function should also return without action.
+This indicates that the callout has been stopped.
+Finally, the callout function should call
+.Fn callout_deactivate
+to clear the
+.Em active
+flag.
+For example:
+.Bd -literal -offset indent
+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 */
+.Ed
+.Pp
+Together with appropriate synchronization, such as the mutex used above,
+this approach permits the
+.Fn callout_stop
+and
+.Fn callout_reset
+functions to be used at any time without races.
+For example:
+.Bd -literal -offset indent
+mtx_lock(&sc->sc_mtx);
+callout_stop(&sc->sc_callout);
+/* The callout is effectively stopped now. */
+.Ed
+.Pp
+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
+.Fn callout_deactivate
+call.
+.Pp
+The above technique additionally ensures that the
+.Em active
+flag always reflects whether the callout is effectively enabled or
+disabled.
+If
+.Fn callout_active
+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.
+.El
+.Pp
+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
+.Fn callout_drain
+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.
+.Sh RETURN VALUES
+The
+.Fn callout_active
+macro returns the state of a callout's
+.Em active
+flag.
+.Pp
+The
+.Fn callout_pending
+macro returns the state of a callout's
+.Em pending
+flag.
+.Pp
+The
+.Fn callout_reset
+and
+.Fn callout_schedule
+function families return a value of one if the callout was pending before the new
+function invocation was scheduled.
+.Pp
+The
+.Fn callout_stop
+and
+.Fn callout_drain
+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.
+.Sh HISTORY
+.Fx
+initially used the long standing
+.Bx
+linked list
+callout mechanism which offered O(n) insertion and removal running time
+but did not generate or require handles for untimeout operations.
+.Pp
+.Fx 3.0
+introduced a new set of timeout and untimeout routines from
+.Nx
+based on the work of
+.An Adam M. Costello
+and
+.An George Varghese ,
+published in a technical report entitled
+.%T "Redesigning the BSD Callout and Timer Facilities"
+and modified for inclusion in
+.Fx
+by
+.An Justin T. Gibbs .
+The original work on the data structures used in that implementation
+was published by
+.An G. Varghese
+and
+.An A. Lauck
+in the paper
+.%T "Hashed and Hierarchical Timing Wheels: Data Structures for the Efficient Implementation of a Timer Facility"
+in the
+.%B "Proceedings of the 11th ACM Annual Symposium on Operating Systems Principles" .
+.Pp
+.Fx 3.3
+introduced the first implementations of
+.Fn callout_init ,
+.Fn callout_reset ,
+and
+.Fn callout_stop
+which permitted callers to allocate dedicated storage for callouts.
+This ensured that a callout would always fire unlike
+.Fn timeout
+which would silently fail if it was unable to allocate a callout.
+.Pp
+.Fx 5.0
+permitted callout handlers to be tagged as MPSAFE via
+.Fn callout_init .
+.Pp
+.Fx 5.3
+introduced
+.Fn callout_drain .
+.Pp
+.Fx 6.0
+introduced
+.Fn callout_init_mtx .
+.Pp
+.Fx 8.0
+introduced per-CPU callout wheels,
+.Fn callout_init_rw ,
+and
+.Fn callout_schedule .
+.Pp
+.Fx 9.0
+changed the underlying timer interrupts used to drive callouts to prefer
+one-shot event timers instead of a periodic timer interrupt.
+.Pp
+.Fx 10.0
+switched the callout wheel to support tickless operation.
+These changes introduced
+.Vt sbintime_t
+and the
+.Fn callout_reset_sbt*
+family of functions.
+.Fx 10.0 also added
+.Dv C_DIRECT_EXEC
+and
+.Fn callout_init_rm .
+.Pp
+.Fx 10.2
+introduced the
+.Fn callout_schedule_sbt*
+family of functions.
+.Pp
+.Fx 11.0
+introduced
+.Fn callout_async_drain .
+.Fx 11.1
+introduced
+.Fn callout_when .
+.Fx 13.0
+removed
+.Vt timeout_t ,
+.Fn timeout ,
+and
+.Fn untimeout .
Index: head/share/man/man9/timeout.9
===================================================================
--- head/share/man/man9/timeout.9
+++ head/share/man/man9/timeout.9
@@ -1,961 +0,0 @@
-.\" $NetBSD: timeout.9,v 1.2 1996/06/23 22:32:34 pk Exp $
-.\"
-.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
-.\" All rights reserved.
-.\"
-.\" This code is derived from software contributed to The NetBSD Foundation
-.\" by Paul Kranenburg.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
-.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-.\" POSSIBILITY OF SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd December 10, 2019
-.Dt TIMEOUT 9
-.Os
-.Sh NAME
-.Nm callout_active ,
-.Nm callout_deactivate ,
-.Nm callout_async_drain ,
-.Nm callout_drain ,
-.Nm callout_handle_init ,
-.Nm callout_init ,
-.Nm callout_init_mtx ,
-.Nm callout_init_rm ,
-.Nm callout_init_rw ,
-.Nm callout_pending ,
-.Nm callout_reset ,
-.Nm callout_reset_curcpu ,
-.Nm callout_reset_on ,
-.Nm callout_reset_sbt ,
-.Nm callout_reset_sbt_curcpu ,
-.Nm callout_reset_sbt_on ,
-.Nm callout_schedule ,
-.Nm callout_schedule_curcpu ,
-.Nm callout_schedule_on ,
-.Nm callout_schedule_sbt ,
-.Nm callout_schedule_sbt_curcpu ,
-.Nm callout_schedule_sbt_on ,
-.Nm callout_stop ,
-.Nm callout_when ,
-.Nm timeout ,
-.Nm untimeout
-.Nd execute a function after a specified length of time
-.Sh SYNOPSIS
-.In sys/types.h
-.In sys/callout.h
-.In sys/systm.h
-.Bd -literal
-typedef void callout_func_t (void *);
-typedef void timeout_t (void *);
-.Ed
-.Ft int
-.Fn callout_active "struct callout *c"
-.Ft void
-.Fn callout_deactivate "struct callout *c"
-.Ft int
-.Fn callout_async_drain "struct callout *c" "callout_func_t *drain"
-.Ft int
-.Fn callout_drain "struct callout *c"
-.Ft void
-.Fn callout_handle_init "struct callout_handle *handle"
-.Bd -literal
-struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle);
-.Ed
-.Ft void
-.Fn callout_init "struct callout *c" "int mpsafe"
-.Ft void
-.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags"
-.Ft void
-.Fn callout_init_rm "struct callout *c" "struct rmlock *rm" "int flags"
-.Ft void
-.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags"
-.Ft int
-.Fn callout_pending "struct callout *c"
-.Ft int
-.Fo callout_reset
-.Fa "struct callout *c"
-.Fa "int ticks"
-.Fa "callout_func_t *func"
-.Fa "void *arg"
-.Fc
-.Ft int
-.Fo callout_reset_curcpu
-.Fa "struct callout *c"
-.Fa "int ticks"
-.Fa "callout_func_t *func"
-.Fa "void *arg"
-.Fc
-.Ft int
-.Fo callout_reset_on
-.Fa "struct callout *c"
-.Fa "int ticks"
-.Fa "callout_func_t *func"
-.Fa "void *arg"
-.Fa "int cpu"
-.Fc
-.Ft int
-.Fo callout_reset_sbt
-.Fa "struct callout *c"
-.Fa "sbintime_t sbt"
-.Fa "sbintime_t pr"
-.Fa "callout_func_t *func"
-.Fa "void *arg"
-.Fa "int flags"
-.Fc
-.Ft int
-.Fo callout_reset_sbt_curcpu
-.Fa "struct callout *c"
-.Fa "sbintime_t sbt"
-.Fa "sbintime_t pr"
-.Fa "callout_func_t *func"
-.Fa "void *arg"
-.Fa "int flags"
-.Fc
-.Ft int
-.Fo callout_reset_sbt_on
-.Fa "struct callout *c"
-.Fa "sbintime_t sbt"
-.Fa "sbintime_t pr"
-.Fa "callout_func_t *func"
-.Fa "void *arg"
-.Fa "int cpu"
-.Fa "int flags"
-.Fc
-.Ft int
-.Fn callout_schedule "struct callout *c" "int ticks"
-.Ft int
-.Fn callout_schedule_curcpu "struct callout *c" "int ticks"
-.Ft int
-.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
-.Ft int
-.Fo callout_schedule_sbt
-.Fa "struct callout *c"
-.Fa "sbintime_t sbt"
-.Fa "sbintime_t pr"
-.Fa "int flags"
-.Fc
-.Ft int
-.Fo callout_schedule_sbt_curcpu
-.Fa "struct callout *c"
-.Fa "sbintime_t sbt"
-.Fa "sbintime_t pr"
-.Fa "int flags"
-.Fc
-.Ft int
-.Fo callout_schedule_sbt_on
-.Fa "struct callout *c"
-.Fa "sbintime_t sbt"
-.Fa "sbintime_t pr"
-.Fa "int cpu"
-.Fa "int flags"
-.Fc
-.Ft int
-.Fn callout_stop "struct callout *c"
-.Ft sbintime_t
-.Fo callout_when
-.Fa "sbintime_t sbt"
-.Fa "sbintime_t precision"
-.Fa "int flags"
-.Fa "sbintime_t *sbt_res"
-.Fa "sbintime_t *precision_res"
-.Fc
-.Ft struct callout_handle
-.Fn timeout "timeout_t *func" "void *arg" "int ticks"
-.Ft void
-.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle"
-.Sh DESCRIPTION
-The
-.Nm callout
-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
-.Pq 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.
-.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.
-.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.
-.Pp
-Each callout structure must be initialized by
-.Fn callout_init ,
-.Fn callout_init_mtx ,
-.Fn callout_init_rm ,
-or
-.Fn callout_init_rw
-before it is passed to any of the other callout functions.
-The
-.Fn callout_init
-function initializes a callout structure in
-.Fa c
-that is not associated with a specific lock.
-If the
-.Fa mpsafe
-argument is zero,
-the callout structure is not considered to be
-.Dq multi-processor safe ;
-and the Giant lock will be acquired before calling the callout function
-and released when the callout function returns.
-.Pp
-The
-.Fn callout_init_mtx ,
-.Fn callout_init_rm ,
-and
-.Fn callout_init_rw
-functions initialize a callout structure in
-.Fa c
-that is associated with a specific lock.
-The lock is specified by the
-.Fa mtx ,
-.Fa rm ,
-or
-.Fa rw
-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.
-.Pp
-Only regular mutexes may be used with
-.Fn callout_init_mtx ;
-spin mutexes are not supported.
-A sleepable read-mostly lock
-.Po
-one initialized with the
-.Dv RM_SLEEPABLE
-flag
-.Pc
-may not be used with
-.Fn callout_init_rm .
-Similarly, other sleepable lock types such as
-.Xr sx 9
-and
-.Xr lockmgr 9
-cannot be used with callouts because sleeping is not permitted in
-the callout subsystem.
-.Pp
-These
-.Fa flags
-may be specified for
-.Fn callout_init_mtx ,
-.Fn callout_init_rm ,
-or
-.Fn callout_init_rw :
-.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED"
-.It Dv CALLOUT_RETURNUNLOCKED
-The callout function will release the associated lock itself,
-so the callout subsystem should not attempt to unlock it
-after the callout function returns.
-.It Dv CALLOUT_SHAREDLOCK
-The lock is only acquired in read mode when running the callout handler.
-This flag is ignored by
-.Fn callout_init_mtx .
-.El
-.Pp
-The function
-.Fn callout_stop
-cancels a callout
-.Fa c
-if it is currently pending.
-If the callout is pending and successfully stopped, then
-.Fn callout_stop
-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
-.Fn callout_stop
-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.
-.Pp
-The function
-.Fn callout_async_drain
-is identical to
-.Fn callout_stop
-with one difference.
-When
-.Fn callout_async_drain
-returns zero it will arrange for the function
-.Fa drain
-to be called using the same argument given to the
-.Fn callout_reset
-function.
-.Fn callout_async_drain
-If the callout has an associated lock,
-then that lock must be held when this function is called.
-Note that when stopping multiple callouts that use the same lock it is possible
-to get multiple return's of zero and multiple calls to the
-.Fa drain
-function, depending upon which CPU's the callouts are running.
-The
-.Fa drain
-function itself is called from the context of the completing callout
-i.e. softclock or hardclock, just like a callout itself.
-.Pp
-The function
-.Fn callout_drain
-is identical to
-.Fn callout_stop
-except that it will wait for the callout
-.Fa c
-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
-.Fn callout_drain
-returns.
-However, the callout subsystem does guarantee that the callout will be
-fully stopped before
-.Fn callout_drain
-returns.
-.Pp
-The
-.Fn callout_reset
-and
-.Fn callout_schedule
-function families schedule a future function invocation for callout
-.Fa c .
-If
-.Fa c
-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.
-.Pp
-The time at which the callout function will be invoked is determined by
-either the
-.Fa ticks
-argument or the
-.Fa sbt ,
-.Fa pr ,
-and
-.Fa flags
-arguments.
-When
-.Fa ticks
-is used,
-the callout is scheduled to execute after
-.Fa ticks Ns No /hz
-seconds.
-Non-positive values of
-.Fa ticks
-are silently converted to the value
-.Sq 1 .
-.Pp
-The
-.Fa sbt ,
-.Fa pr ,
-and
-.Fa flags
-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
-.Fa sbt
-and extends for the amount of time specified in
-.Fa pr .
-If
-.Fa sbt
-specifies a time in the past,
-the window is adjusted to start at the current time.
-A non-zero value for
-.Fa pr
-allows the callout subsystem to coalesce callouts scheduled close to each
-other into fewer timer interrupts,
-reducing processing overhead and power consumption.
-These
-.Fa flags
-may be specified to adjust the interpretation of
-.Fa sbt
-and
-.Fa pr :
-.Bl -tag -width ".Dv C_DIRECT_EXEC"
-.It Dv C_ABSOLUTE
-Handle the
-.Fa sbt
-argument as an absolute time since boot.
-By default,
-.Fa sbt
-is treated as a relative amount of time,
-similar to
-.Fa ticks .
-.It Dv C_DIRECT_EXEC
-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.
-.It Fn C_PREL
-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
-.Fa pr
-or this value is used as the length of the time window.
-Smaller values
-.Pq which result in larger time intervals
-allow the callout subsystem to aggregate more events in one timer interrupt.
-.It Dv C_PRECALC
-The
-.Fa sbt
-argument specifies the absolute time at which the callout should be run,
-and the
-.Fa pr
-argument specifies the requested precision, which will not be
-adjusted during the scheduling process.
-The
-.Fa sbt
-and
-.Fa pr
-values should be calculated by an earlier call to
-.Fn callout_when
-which uses the user-supplied
-.Fa sbt ,
-.Fa pr ,
-and
-.Fa flags
-values.
-.It Dv C_HARDCLOCK
-Align the timeouts to
-.Fn hardclock
-calls if possible.
-.El
-.Pp
-The
-.Fn callout_reset
-functions accept a
-.Fa func
-argument which identifies the function to be called when the time expires.
-It must be a pointer to a function that takes a single
-.Fa void *
-argument.
-Upon invocation,
-.Fa func
-will receive
-.Fa arg
-as its only argument.
-The
-.Fn callout_schedule
-functions reuse the
-.Fa func
-and
-.Fa arg
-arguments from the previous callout.
-Note that one of the
-.Fn callout_reset
-functions must always be called to initialize
-.Fa func
-and
-.Fa arg
-before one of the
-.Fn callout_schedule
-functions can be used.
-.Pp
-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
-.Fn callout_reset_on ,
-.Fn callout_reset_sbt_on ,
-.Fn callout_schedule_on
-and
-.Fn callout_schedule_sbt_on
-functions assign the callout to CPU
-.Fa cpu .
-The
-.Fn callout_reset_curcpu ,
-.Fn callout_reset_sbt_curpu ,
-.Fn callout_schedule_curcpu
-and
-.Fn callout_schedule_sbt_curcpu
-functions assign the callout to the current CPU.
-The
-.Fn callout_reset ,
-.Fn callout_reset_sbt ,
-.Fn callout_schedule
-and
-.Fn callout_schedule_sbt
-functions schedule the callout to execute in the softclock thread of the CPU
-to which it is currently assigned.
-.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
-.Va kern.pin_default_swi
-loader tunable to a non-zero value.
-Softclock threads for CPUs other than zero can be pinned to their
-respective CPUs by setting the
-.Va kern.pin_pcpu_swi
-loader tunable to a non-zero value.
-.Pp
-The macros
-.Fn callout_pending ,
-.Fn callout_active
-and
-.Fn callout_deactivate
-provide access to the current state of the callout.
-The
-.Fn callout_pending
-macro checks whether a callout is
-.Em pending ;
-a callout is considered
-.Em pending
-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,
-.Fn callout_pending
-will return
-.Dv FALSE
-even though the callout function may not have finished
-.Pq or even begun
-executing.
-The
-.Fn callout_active
-macro checks whether a callout is marked as
-.Em active ,
-and the
-.Fn callout_deactivate
-macro clears the callout's
-.Em active
-flag.
-The callout subsystem marks a callout as
-.Em active
-when a timeout is set and it clears the
-.Em active
-flag in
-.Fn callout_stop
-and
-.Fn callout_drain ,
-but it
-.Em does not
-clear it when a callout expires normally via the execution of the
-callout function.
-.Pp
-The
-.Fn callout_when
-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
-.Fa sbt ,
-precision
-.Fa precision ,
-and additional adjustments requested by the
-.Fa flags
-argument.
-Flags accepted by the
-.Fn callout_when
-function are the same as flags for the
-.Fn callout_reset
-function.
-The resulting time is assigned to the variable pointed to by the
-.Fa sbt_res
-argument, and the resulting precision is assigned to
-.Fa *precision_res .
-When passing the results to
-.Fa callout_reset ,
-add the
-.Va C_PRECALC
-flag to
-.Fa flags ,
-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
-.Fn callout_reset
-call is racy.
-.Ss "Avoiding Race Conditions"
-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.
-.Pp
-There are three main techniques for addressing these
-synchronization concerns.
-The first approach is preferred as it is the simplest:
-.Bl -enum -offset indent
-.It
-Callouts can be associated with a specific lock when they are initialized
-by
-.Fn callout_init_mtx ,
-.Fn callout_init_rm ,
-or
-.Fn callout_init_rw .
-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
-.Fn callout_stop
-or one of the
-.Fn callout_reset
-or
-.Fn callout_schedule
-functions to provide this safety.
-.Pp
-A callout initialized via
-.Fn callout_init
-with
-.Fa mpsafe
-set to zero is implicitly associated with the
-.Va Giant
-mutex.
-If
-.Va Giant
-is held when cancelling or rescheduling the callout,
-then its use will prevent races with the callout function.
-.It
-The return value from
-.Fn callout_stop
-.Po
-or the
-.Fn callout_reset
-and
-.Fn callout_schedule
-function families
-.Pc
-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
-.Dv FALSE
-indicates that the callout function is about to be called.
-For example:
-.Bd -literal -offset indent
-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
- */
- }
-}
-.Ed
-.It
-The
-.Fn callout_pending ,
-.Fn callout_active
-and
-.Fn callout_deactivate
-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
-.Em active
-and
-.Em pending .
-When the timeout time arrives, the callout subsystem begins processing
-the callout by first clearing the
-.Em pending
-flag.
-It then invokes the callout function without changing the
-.Em active
-flag, and does not clear the
-.Em active
-flag even after the callout function returns.
-The mechanism described here requires the callout function itself to
-clear the
-.Em active
-flag using the
-.Fn callout_deactivate
-macro.
-The
-.Fn callout_stop
-and
-.Fn callout_drain
-functions always clear both the
-.Em active
-and
-.Em pending
-flags before returning.
-.Pp
-The callout function should first check the
-.Em pending
-flag and return without action if
-.Fn callout_pending
-returns
-.Dv TRUE .
-This indicates that the callout was rescheduled using
-.Fn callout_reset
-just before the callout function was invoked.
-If
-.Fn callout_active
-returns
-.Dv FALSE
-then the callout function should also return without action.
-This indicates that the callout has been stopped.
-Finally, the callout function should call
-.Fn callout_deactivate
-to clear the
-.Em active
-flag.
-For example:
-.Bd -literal -offset indent
-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 */
-.Ed
-.Pp
-Together with appropriate synchronization, such as the mutex used above,
-this approach permits the
-.Fn callout_stop
-and
-.Fn callout_reset
-functions to be used at any time without races.
-For example:
-.Bd -literal -offset indent
-mtx_lock(&sc->sc_mtx);
-callout_stop(&sc->sc_callout);
-/* The callout is effectively stopped now. */
-.Ed
-.Pp
-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
-.Fn callout_deactivate
-call.
-.Pp
-The above technique additionally ensures that the
-.Em active
-flag always reflects whether the callout is effectively enabled or
-disabled.
-If
-.Fn callout_active
-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.
-.El
-.Pp
-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
-.Fn callout_drain
-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.
-.Sh LEGACY API
-.Bf Sy
-The functions below are a legacy API that will be removed in a future release.
-New code should not use these routines.
-.Ef
-.Pp
-The function
-.Fn timeout
-schedules a call to the function given by the argument
-.Fa func
-to take place after
-.Fa ticks Ns No /hz
-seconds.
-Non-positive values of
-.Fa ticks
-are silently converted to the value
-.Sq 1 .
-.Fa func
-should be a pointer to a function that takes a
-.Fa void *
-argument.
-Upon invocation,
-.Fa func
-will receive
-.Fa arg
-as its only argument.
-The return value from
-.Fn timeout
-is a
-.Ft struct callout_handle
-which can be used in conjunction with the
-.Fn untimeout
-function to request that a scheduled timeout be canceled.
-.Pp
-The function
-.Fn callout_handle_init
-can be used to initialize a handle to a state which will cause
-any calls to
-.Fn untimeout
-with that handle to return with no side
-effects.
-.Pp
-Assigning a callout handle the value of
-.Fn CALLOUT_HANDLE_INITIALIZER
-performs the same function as
-.Fn callout_handle_init
-and is provided for use on statically declared or global callout handles.
-.Pp
-The function
-.Fn untimeout
-cancels the timeout associated with
-.Fa handle
-using the
-.Fa func
-and
-.Fa arg
-arguments to validate the handle.
-If the handle does not correspond to a timeout with
-the function
-.Fa func
-taking the argument
-.Fa arg
-no action is taken.
-.Fa handle
-must be initialized by a previous call to
-.Fn timeout ,
-.Fn callout_handle_init ,
-or assigned the value of
-.Fn CALLOUT_HANDLE_INITIALIZER "&handle"
-before being passed to
-.Fn untimeout .
-The behavior of calling
-.Fn untimeout
-with an uninitialized handle
-is undefined.
-.Pp
-As handles are recycled by the system, it is possible (although unlikely)
-that a handle from one invocation of
-.Fn timeout
-may match the handle of another invocation of
-.Fn timeout
-if both calls used the same function pointer and argument, and the first
-timeout is expired or canceled before the second call.
-The timeout facility offers O(1) running time for
-.Fn timeout
-and
-.Fn untimeout .
-Timeouts are executed from
-.Fn softclock
-with the
-.Va Giant
-lock held.
-Thus they are protected from re-entrancy.
-.Sh RETURN VALUES
-The
-.Fn callout_active
-macro returns the state of a callout's
-.Em active
-flag.
-.Pp
-The
-.Fn callout_pending
-macro returns the state of a callout's
-.Em pending
-flag.
-.Pp
-The
-.Fn callout_reset
-and
-.Fn callout_schedule
-function families return a value of one if the callout was pending before the new
-function invocation was scheduled.
-.Pp
-The
-.Fn callout_stop
-and
-.Fn callout_drain
-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.
-The
-.Fn timeout
-function returns a
-.Ft struct callout_handle
-that can be passed to
-.Fn untimeout .
-.Sh HISTORY
-The current timeout and untimeout routines are based on the work of
-.An Adam M. Costello
-and
-.An George Varghese ,
-published in a technical report entitled
-.%T "Redesigning the BSD Callout and Timer Facilities"
-and modified slightly for inclusion in
-.Fx
-by
-.An Justin T. Gibbs .
-The original work on the data structures used in this implementation
-was published by
-.An G. Varghese
-and
-.An A. Lauck
-in the paper
-.%T "Hashed and Hierarchical Timing Wheels: Data Structures for the Efficient Implementation of a Timer Facility"
-in the
-.%B "Proceedings of the 11th ACM Annual Symposium on Operating Systems Principles" .
-The current implementation replaces the long standing
-.Bx
-linked list
-callout mechanism which offered O(n) insertion and removal running time
-but did not generate or require handles for untimeout operations.
Index: head/sys/kern/kern_intr.c
===================================================================
--- head/sys/kern/kern_intr.c
+++ head/sys/kern/kern_intr.c
@@ -84,7 +84,6 @@
uintptr_t event;
};
-struct intr_event *clk_intr_event;
struct intr_event *tty_intr_event;
void *vm_ih;
struct proc *intrproc;
Index: head/sys/kern/kern_timeout.c
===================================================================
--- head/sys/kern/kern_timeout.c
+++ head/sys/kern/kern_timeout.c
@@ -167,10 +167,8 @@
struct mtx_padalign cc_lock;
struct cc_exec cc_exec_entity[2];
struct callout *cc_next;
- struct callout *cc_callout;
struct callout_list *cc_callwheel;
struct callout_tailq cc_expireq;
- struct callout_slist cc_callfree;
sbintime_t cc_firstevent;
sbintime_t cc_lastscan;
void *cc_cookie;
@@ -210,7 +208,7 @@
#define CC_UNLOCK(cc) mtx_unlock_spin(&(cc)->cc_lock)
#define CC_LOCK_ASSERT(cc) mtx_assert(&(cc)->cc_lock, MA_OWNED)
-static int __read_mostly timeout_cpu;
+static int __read_mostly cc_default_cpu;
static void callout_cpu_init(struct callout_cpu *cc, int cpu);
static void softclock_call_cc(struct callout *c, struct callout_cpu *cc,
@@ -279,6 +277,7 @@
callout_callwheel_init(void *dummy)
{
struct callout_cpu *cc;
+ int cpu;
/*
* Calculate the size of the callout wheel and the preallocated
@@ -304,16 +303,14 @@
TUNABLE_INT_FETCH("kern.pin_pcpu_swi", &pin_pcpu_swi);
/*
- * Only BSP handles timeout(9) and receives a preallocation.
- *
- * XXX: Once all timeout(9) consumers are converted this can
- * be removed.
+ * Initialize callout wheels. The software interrupt threads
+ * are created later.
*/
- timeout_cpu = PCPU_GET(cpuid);
- cc = CC_CPU(timeout_cpu);
- cc->cc_callout = malloc(ncallout * sizeof(struct callout),
- M_CALLOUT, M_WAITOK);
- callout_cpu_init(cc, timeout_cpu);
+ cc_default_cpu = PCPU_GET(cpuid);
+ CPU_FOREACH(cpu) {
+ cc = CC_CPU(cpu);
+ callout_cpu_init(cc, cpu);
+ }
}
SYSINIT(callwheel_init, SI_SUB_CPU, SI_ORDER_ANY, callout_callwheel_init, NULL);
@@ -323,11 +320,9 @@
static void
callout_cpu_init(struct callout_cpu *cc, int cpu)
{
- struct callout *c;
int i;
mtx_init(&cc->cc_lock, "callout", NULL, MTX_SPIN | MTX_RECURSE);
- SLIST_INIT(&cc->cc_callfree);
cc->cc_inited = 1;
cc->cc_callwheel = malloc_domainset(sizeof(struct callout_list) *
callwheelsize, M_CALLOUT,
@@ -342,14 +337,6 @@
snprintf(cc->cc_ktr_event_name, sizeof(cc->cc_ktr_event_name),
"callwheel cpu %d", cpu);
#endif
- if (cc->cc_callout == NULL) /* Only BSP handles timeout(9) */
- return;
- for (i = 0; i < ncallout; i++) {
- c = &cc->cc_callout[i];
- callout_init(c, 0);
- c->c_iflags = CALLOUT_LOCAL_ALLOC;
- SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle);
- }
}
#ifdef SMP
@@ -383,50 +370,35 @@
#endif
/*
- * Start standard softclock thread.
+ * Start softclock threads.
*/
static void
start_softclock(void *dummy)
{
struct callout_cpu *cc;
char name[MAXCOMLEN];
-#ifdef SMP
int cpu;
+ bool pin_swi;
struct intr_event *ie;
-#endif
- cc = CC_CPU(timeout_cpu);
- snprintf(name, sizeof(name), "clock (%d)", timeout_cpu);
- if (swi_add(&clk_intr_event, name, softclock, cc, SWI_CLOCK,
- INTR_MPSAFE, &cc->cc_cookie))
- panic("died while creating standard software ithreads");
- if (pin_default_swi &&
- (intr_event_bind(clk_intr_event, timeout_cpu) != 0)) {
- printf("%s: timeout clock couldn't be pinned to cpu %d\n",
- __func__,
- timeout_cpu);
- }
-
-#ifdef SMP
CPU_FOREACH(cpu) {
- if (cpu == timeout_cpu)
- continue;
cc = CC_CPU(cpu);
- cc->cc_callout = NULL; /* Only BSP handles timeout(9). */
- callout_cpu_init(cc, cpu);
snprintf(name, sizeof(name), "clock (%d)", cpu);
ie = NULL;
if (swi_add(&ie, name, softclock, cc, SWI_CLOCK,
INTR_MPSAFE, &cc->cc_cookie))
panic("died while creating standard software ithreads");
- if (pin_pcpu_swi && (intr_event_bind(ie, cpu) != 0)) {
- printf("%s: per-cpu clock couldn't be pinned to "
- "cpu %d\n",
+ if (cpu == cc_default_cpu)
+ pin_swi = pin_default_swi;
+ else
+ pin_swi = pin_pcpu_swi;
+ if (pin_swi && (intr_event_bind(ie, cpu) != 0)) {
+ printf("%s: %s clock couldn't be pinned to cpu %d\n",
__func__,
+ cpu == cc_default_cpu ? "default" : "per-cpu",
cpu);
}
}
-#endif
}
SYSINIT(start_softclock, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softclock, NULL);
@@ -639,16 +611,6 @@
}
static void
-callout_cc_del(struct callout *c, struct callout_cpu *cc)
-{
-
- if ((c->c_iflags & CALLOUT_LOCAL_ALLOC) == 0)
- return;
- c->c_func = NULL;
- SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle);
-}
-
-static void
softclock_call_cc(struct callout *c, struct callout_cpu *cc,
#ifdef CALLOUT_PROFILING
int *mpcalls, int *lockcalls, int *gcalls,
@@ -692,10 +654,7 @@
c_func = c->c_func;
c_arg = c->c_arg;
c_iflags = c->c_iflags;
- if (c->c_iflags & CALLOUT_LOCAL_ALLOC)
- c->c_iflags = CALLOUT_LOCAL_ALLOC;
- else
- c->c_iflags &= ~CALLOUT_PENDING;
+ c->c_iflags &= ~CALLOUT_PENDING;
cc_exec_curr(cc, direct) = c;
cc_exec_last_func(cc, direct) = c_func;
@@ -795,8 +754,6 @@
wakeup(&cc_exec_waiting(cc, direct));
CC_LOCK(cc);
} else if (cc_cce_migrating(cc, direct)) {
- KASSERT((c_iflags & CALLOUT_LOCAL_ALLOC) == 0,
- ("Migrating legacy callout %p", c));
#ifdef SMP
/*
* If the callout was scheduled for
@@ -819,7 +776,6 @@
CTR3(KTR_CALLOUT,
"deferred cancelled %p func %p arg %p",
c, new_func, new_arg);
- callout_cc_del(c, cc);
return;
}
c->c_iflags &= ~CALLOUT_DFRMIGRATION;
@@ -834,19 +790,6 @@
panic("migration should not happen");
#endif
}
- /*
- * If the current callout is locally allocated (from
- * timeout(9)) then put it on the freelist.
- *
- * Note: we need to check the cached copy of c_iflags because
- * if it was not local, then it's not safe to deref the
- * callout pointer.
- */
- KASSERT((c_iflags & CALLOUT_LOCAL_ALLOC) == 0 ||
- c->c_iflags == CALLOUT_LOCAL_ALLOC,
- ("corrupted callout"));
- if (c_iflags & CALLOUT_LOCAL_ALLOC)
- callout_cc_del(c, cc);
}
/*
@@ -896,70 +839,7 @@
CC_UNLOCK(cc);
}
-/*
- * timeout --
- * Execute a function after a specified length of time.
- *
- * untimeout --
- * Cancel previous timeout function call.
- *
- * callout_handle_init --
- * Initialize a handle so that using it with untimeout is benign.
- *
- * See AT&T BCI Driver Reference Manual for specification. This
- * implementation differs from that one in that although an
- * identification value is returned from timeout, the original
- * arguments to timeout as well as the identifier are used to
- * identify entries for untimeout.
- */
-struct callout_handle
-timeout(timeout_t *ftn, void *arg, int to_ticks)
-{
- struct callout_cpu *cc;
- struct callout *new;
- struct callout_handle handle;
-
- cc = CC_CPU(timeout_cpu);
- CC_LOCK(cc);
- /* Fill in the next free callout structure. */
- new = SLIST_FIRST(&cc->cc_callfree);
- if (new == NULL)
- /* XXX Attempt to malloc first */
- panic("timeout table full");
- SLIST_REMOVE_HEAD(&cc->cc_callfree, c_links.sle);
- callout_reset(new, to_ticks, ftn, arg);
- handle.callout = new;
- CC_UNLOCK(cc);
-
- return (handle);
-}
-
void
-untimeout(timeout_t *ftn, void *arg, struct callout_handle handle)
-{
- struct callout_cpu *cc;
-
- /*
- * Check for a handle that was initialized
- * by callout_handle_init, but never used
- * for a real timeout.
- */
- if (handle.callout == NULL)
- return;
-
- cc = callout_lock(handle.callout);
- if (handle.callout->c_func == ftn && handle.callout->c_arg == arg)
- callout_stop(handle.callout);
- CC_UNLOCK(cc);
-}
-
-void
-callout_handle_init(struct callout_handle *handle)
-{
- handle->callout = NULL;
-}
-
-void
callout_when(sbintime_t sbt, sbintime_t precision, int flags,
sbintime_t *res, sbintime_t *prec_res)
{
@@ -1060,12 +940,9 @@
("%s: direct callout %p has lock", __func__, c));
cc = callout_lock(c);
/*
- * Don't allow migration of pre-allocated callouts lest they
- * become unbalanced or handle the case where the user does
- * not care.
+ * Don't allow migration if the user does not care.
*/
- if ((c->c_iflags & CALLOUT_LOCAL_ALLOC) ||
- ignore_cpu) {
+ if (ignore_cpu) {
cpu = c->c_cpu;
}
@@ -1435,7 +1312,6 @@
TAILQ_REMOVE(&cc->cc_expireq, c, c_links.tqe);
}
}
- callout_cc_del(c, cc);
CC_UNLOCK(cc);
return (cancelled);
}
@@ -1451,7 +1327,7 @@
c->c_lock = &Giant.lock_object;
c->c_iflags = 0;
}
- c->c_cpu = timeout_cpu;
+ c->c_cpu = cc_default_cpu;
}
void
@@ -1467,7 +1343,7 @@
(LC_SPINLOCK | LC_SLEEPABLE)), ("%s: invalid lock class",
__func__));
c->c_iflags = flags & (CALLOUT_RETURNUNLOCKED | CALLOUT_SHAREDLOCK);
- c->c_cpu = timeout_cpu;
+ c->c_cpu = cc_default_cpu;
}
#ifdef APM_FIXUP_CALLTODO
@@ -1559,9 +1435,7 @@
sbintime_t maxpr, maxt, medpr, medt, now, spr, st, t;
int ct[64], cpr[64], ccpbk[32];
int error, val, i, count, tcum, pcum, maxc, c, medc;
-#ifdef SMP
int cpu;
-#endif
val = 0;
error = sysctl_handle_int(oidp, &val, 0, req);
@@ -1573,12 +1447,8 @@
bzero(ct, sizeof(ct));
bzero(cpr, sizeof(cpr));
now = sbinuptime();
-#ifdef SMP
CPU_FOREACH(cpu) {
cc = CC_CPU(cpu);
-#else
- cc = CC_CPU(timeout_cpu);
-#endif
CC_LOCK(cc);
for (i = 0; i < callwheelsize; i++) {
sc = &cc->cc_callwheel[i];
@@ -1603,9 +1473,7 @@
count += c;
}
CC_UNLOCK(cc);
-#ifdef SMP
}
-#endif
for (i = 0, tcum = 0; i < 64 && tcum < count / 2; i++)
tcum += ct[i];
Index: head/sys/netgraph/ng_base.c
===================================================================
--- head/sys/netgraph/ng_base.c
+++ head/sys/netgraph/ng_base.c
@@ -3801,7 +3801,7 @@
return (0);
}
-/* A special modified version of untimeout() */
+/* A special modified version of callout_stop() */
int
ng_uncallout(struct callout *c, node_p node)
{
Index: head/sys/sys/interrupt.h
===================================================================
--- head/sys/sys/interrupt.h
+++ head/sys/sys/interrupt.h
@@ -151,7 +151,6 @@
struct proc;
extern struct intr_event *tty_intr_event;
-extern struct intr_event *clk_intr_event;
extern void *vm_ih;
/* Counts and names for statistics (defined in MD code). */
Index: head/sys/sys/param.h
===================================================================
--- head/sys/sys/param.h
+++ head/sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300066 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300067 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
Index: head/sys/sys/systm.h
===================================================================
--- head/sys/sys/systm.h
+++ head/sys/sys/systm.h
@@ -466,15 +466,6 @@
void kern_reboot(int) __dead2;
void shutdown_nice(int);
-/* Timeouts */
-typedef void timeout_t(void *); /* timeout function type */
-#define CALLOUT_HANDLE_INITIALIZER(handle) \
- { NULL }
-
-void callout_handle_init(struct callout_handle *);
-struct callout_handle timeout(timeout_t *, void *, int);
-void untimeout(timeout_t *, void *, struct callout_handle);
-
/* Stubs for obsolete functions that used to be for interrupt management */
static __inline intrmask_t splbio(void) { return 0; }
static __inline intrmask_t splcam(void) { return 0; }

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 21, 1:20 PM (21 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14762026
Default Alt Text
D22602.diff (65 KB)

Event Timeline