svn commit: r277213 - in head: share/man/man9 sys/kern sys/ofed/include/linux sys/sys

Adrian Chadd adrian at freebsd.org
Mon Jan 19 21:59:58 UTC 2015


Hi,

Would you please check what the results of this are with CPU specific
callwheels?

I'm doing some 10+ gig traffic testing on -HEAD with RSS enabled (on
ixgbe) and with this setup, the per-CPU TCP callwheel stuff is
enabled. But all the callwheels are now back on clock(0) and so is the
lock contention. :(

Thanks,



-adrian


On 15 January 2015 at 07:32, Hans Petter Selasky <hselasky at freebsd.org> wrote:
> Author: hselasky
> Date: Thu Jan 15 15:32:30 2015
> New Revision: 277213
> URL: https://svnweb.freebsd.org/changeset/base/277213
>
> Log:
>   Major callout subsystem cleanup and rewrite:
>   - Close a migration race where callout_reset() failed to set the
>     CALLOUT_ACTIVE flag.
>   - Callout callback functions are now allowed to be protected by
>     spinlocks.
>   - Switching the callout CPU number cannot always be done on a
>     per-callout basis. See the updated timeout(9) manual page for more
>     information.
>   - The timeout(9) manual page has been updated to reflect how all the
>     functions inside the callout API are working. The manual page has
>     been made function oriented to make it easier to deduce how each of
>     the functions making up the callout API are working without having
>     to first read the whole manual page. Group all functions into a
>     handful of sections which should give a quick top-level overview
>     when the different functions should be used.
>   - The CALLOUT_SHAREDLOCK flag and its functionality has been removed
>     to reduce the complexity in the callout code and to avoid problems
>     about atomically stopping callouts via callout_stop(). If someone
>     needs it, it can be re-added. From my quick grep there are no
>     CALLOUT_SHAREDLOCK clients in the kernel.
>   - A new callout API function named "callout_drain_async()" has been
>     added. See the updated timeout(9) manual page for a complete
>     description.
>   - Update the callout clients in the "kern/" folder to use the callout
>     API properly, like cv_timedwait(). Previously there was some custom
>     sleepqueue code in the callout subsystem, which has been removed,
>     because we now allow callouts to be protected by spinlocks. This
>     allows us to tear down the callout like done with regular mutexes,
>     and a "td_slpmutex" has been added to "struct thread" to atomically
>     teardown the "td_slpcallout". Further the "TDF_TIMOFAIL" and
>     "SWT_SLEEPQTIMO" states can now be completely removed. Currently
>     they are marked as available and will be cleaned up in a follow up
>     commit.
>   - Bump the __FreeBSD_version to indicate kernel modules need
>     recompilation.
>   - There has been several reports that this patch "seems to squash a
>     serious bug leading to a callout timeout and panic".
>
>   Kernel build testing: all architectures were built
>   MFC after:            2 weeks
>   Differential Revision:        https://reviews.freebsd.org/D1438
>   Sponsored by:         Mellanox Technologies
>   Reviewed by:          jhb, adrian, sbruno and emaste
>
> Modified:
>   head/share/man/man9/Makefile
>   head/share/man/man9/timeout.9
>   head/sys/kern/init_main.c
>   head/sys/kern/kern_condvar.c
>   head/sys/kern/kern_lock.c
>   head/sys/kern/kern_switch.c
>   head/sys/kern/kern_synch.c
>   head/sys/kern/kern_thread.c
>   head/sys/kern/kern_timeout.c
>   head/sys/kern/subr_sleepqueue.c
>   head/sys/ofed/include/linux/completion.h
>   head/sys/sys/_callout.h
>   head/sys/sys/callout.h
>   head/sys/sys/param.h
>   head/sys/sys/proc.h
>
> Modified: head/share/man/man9/Makefile
> ==============================================================================
> --- head/share/man/man9/Makefile        Thu Jan 15 14:47:48 2015        (r277212)
> +++ head/share/man/man9/Makefile        Thu Jan 15 15:32:30 2015        (r277213)
> @@ -1570,6 +1570,7 @@ MLINKS+=timeout.9 callout.9 \
>         timeout.9 callout_active.9 \
>         timeout.9 callout_deactivate.9 \
>         timeout.9 callout_drain.9 \
> +       timeout.9 callout_drain_async.9 \
>         timeout.9 callout_handle_init.9 \
>         timeout.9 callout_init.9 \
>         timeout.9 callout_init_mtx.9 \
>
> Modified: head/share/man/man9/timeout.9
> ==============================================================================
> --- head/share/man/man9/timeout.9       Thu Jan 15 14:47:48 2015        (r277212)
> +++ head/share/man/man9/timeout.9       Thu Jan 15 15:32:30 2015        (r277213)
> @@ -29,13 +29,14 @@
>  .\"
>  .\" $FreeBSD$
>  .\"
> -.Dd October 8, 2014
> +.Dd January 14, 2015
>  .Dt TIMEOUT 9
>  .Os
>  .Sh NAME
>  .Nm callout_active ,
>  .Nm callout_deactivate ,
>  .Nm callout_drain ,
> +.Nm callout_drain_async ,
>  .Nm callout_handle_init ,
>  .Nm callout_init ,
>  .Nm callout_init_mtx ,
> @@ -63,279 +64,232 @@
>  .In sys/systm.h
>  .Bd -literal
>  typedef void timeout_t (void *);
> +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_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
> -.Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg"
> -.Ft int
> -.Fn callout_reset_curcpu "struct callout *c" "int ticks" "timeout_t *func" \
> -"void *arg"
> -.Ft int
> -.Fn callout_reset_on "struct callout *c" "int ticks" "timeout_t *func" \
> -"void *arg" "int cpu"
> -.Ft int
> -.Fn callout_reset_sbt "struct callout *c" "sbintime_t sbt" \
> -"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
> -.Ft int
> -.Fn callout_reset_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
> -"sbintime_t pr" "timeout_t *func" "void *arg" "int flags"
> -.Ft int
> -.Fn callout_reset_sbt_on "struct callout *c" "sbintime_t sbt" \
> -"sbintime_t pr" "timeout_t *func" "void *arg" "int cpu" "int flags"
> -.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
> -.Fn callout_schedule_sbt "struct callout *c" "sbintime_t sbt" \
> -"sbintime_t pr" "int flags"
> -.Ft int
> -.Fn callout_schedule_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
> -"sbintime_t pr" "int flags"
> -.Ft int
> -.Fn callout_schedule_sbt_on "struct callout *c" "sbintime_t sbt" \
> -"sbintime_t pr" "int cpu" "int flags"
> -.Ft int
> -.Fn callout_stop "struct callout *c"
> -.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
> +time in the future in a single-shot fashion.
> +Consumers of this API are required to allocate a
>  .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.
> +structure for each pending function invocation.
> +The
> +.Pq struct callout
> +structure stores the full state about any pending function call and
> +should be drained by a call to
> +.Fn callout_drain
> +or
> +.Fn callout_drain_async
> +before freeing.
> +.Sh INITIALISATION
> +.Ft void
> +.Fn callout_handle_init "struct callout_handle *handle"
> +This function is deprecated and is used to prepare a
> +.Pq struct callout_handle
> +structure before it can be used the first time.
> +If this function is called on a pending timeout, the pending timeout
> +cannot be cancelled and the
> +.Fn untimeout
> +function will return as if there was no timeout pending.
>  .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.
> +.Fn CALLOUT_HANDLE_INITIALIZER "&handle"
> +This macro is deprecated and can be used instead of
> +.Fn callout_handle_init
> +to assign the default state to the
> +.Pq struct callout_handle
> +structure when declaring static timeouts.
>  .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.
> +.Ft void
> +.Fn callout_init "struct callout *c" "int mpsafe"
> +This function prepares a
> +.Pq struct callout
> +structure before it can be used.
> +This function should not be used when the callout is pending a timeout.
>  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.
> +argument is non-zero, the callback function will be running unlocked.
> +Else the Giant mutex will be locked before calling the callback function.
>  .Pp
> +.Ft void
> +.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags"
> +This function prepares a
> +.Pq struct callout
> +structure before it can be used.
> +This function should not be used when the callout is pending a timeout.
>  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 mtx
> +argument should be non-zero and should specify a pointer to a valid
> +spinlock type of mutex or a valid regular non-sleepable mutex which
> +the callback subsystem should lock before calling the callback
> +function.
> +Valid
>  .Fa flags
> -may be specified for
> -.Fn callout_init_mtx ,
> -.Fn callout_init_rm ,
> -or
> -.Fn callout_init_rw :
> +are:
>  .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 .
> +It is assumed that the callout function has released the specified
> +mutex before returning.
> +Else the callout subsystem will release the specified mutex after the
> +callout function has returned.
>  .El
>  .Pp
> -The function
> -.Fn callout_stop
> -cancels a callout
> -.Fa c
> -if it is currently pending.
> -If the callout is pending, then
> -.Fn callout_stop
> -returns a non-zero value.
> -If the callout is not set,
> -has already been serviced,
> -or is currently being serviced,
> -then zero will be returned.
> -If the callout has an associated lock,
> -then that lock must be held when this function is called.
> -.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 non-zero value 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.
> +.Ft void
> +.Fn callout_init_rm "struct callout *c" "struct rmlock *rm" "int flags"
> +This function is the same like the
> +.Fn callout_init_mtx
> +function except it accepts a read-mostly type of lock.
> +The read-mostly lock must not be initialised with the
> +.Dv RM_SLEEPABLE
> +flag.
>  .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
> +.Ft void
> +.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags"
> +This function is the same like the
> +.Fn callout_init_mtx
> +function except it accepts a reader-writer type of lock.
> +.Sh SCHEDULING CALLOUTS
> +.Ft struct callout_handle
> +.Fn timeout "timeout_t *func" "void *arg" "int ticks"
> +This function is deprecated and 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 .
> -.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 func
> +argument should be a valid pointer to a function that takes a single
> +.Fa void *
> +argument.
> +Upon invocation, the
> +.Fa func
> +function will receive
> +.Fa arg
> +as its only argument.
> +The Giant lock is locked when the
> +.Fa arg
> +function is invoked and should not be unlocked by this function.
> +The returned value from
> +.Fn timeout
> +is a
> +.Ft struct callout_handle
> +structure which can be used in conjunction with the
> +.Fn untimeout
> +function to request that a scheduled timeout be cancelled.
> +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.
> +Please ensure that the function and argument pointers are unique when using this function.
> +.Pp
> +.Ft int
> +.Fn callout_reset "struct callout *c" "int ticks" "callout_func_t *func" "void *arg"
> +This function is used to schedule or re-schedule a callout.
> +This function at first stops the callout given by the
> +.Fa c
> +argument, if any.
> +Then it will start the callout given by the
> +.Fa c
> +argument.
> +The relative time until the timeout callback happens is given by the
> +.Fa ticks
> +argument.
> +The number of ticks in a second is defined by
> +.Dv hz
> +and can vary from system to system.
> +This function returns a non-zero value if the given callout was pending and
> +the callback function was prevented from being called.
> +Else a value of zero is returned.
> +If a lock is associated with the callout given by the
> +.Fa c
> +argument and it is exclusivly locked when this function is called this
> +function will always ensure that previous callback function, if any,
> +is never reached.
> +In other words the callout will be atomically restarted.
> +Else there is no such guarantee.
> +The callback function is given by the
> +.Fa func
> +argument and its function argument is given by the
> +.Fa arg
> +argument.
> +.Pp
> +.Ft int
> +.Fn callout_reset_curcpu "struct callout *c" "int ticks" "callout_func_t *func" \
> +"void *arg"
> +This function works the same like the
> +.Fn callout_reset
> +function except the callback function given by the
> +.Fa func
> +argument will be executed on the same CPU which called this function.
> +A change in the CPU selection can happen if the callout has a lock
> +associated with it and is locked when this function is called.
> +A change in the CPU selection cannot happen if this function is
> +re-scheduled inside a callout function.
> +Else the callback function given by the
> +.Fa func
> +argument will be executed on the same CPU like previously done.
> +.Pp
> +.Ft int
> +.Fn callout_reset_on "struct callout *c" "int ticks" "callout_func_t *func" \
> +"void *arg" "int cpu"
> +This function works the same like the
> +.Fn callout_reset
> +function except the callback function given by the
> +.Fa func
> +argument will be executed on the CPU given by the
> +.Fa cpu
> +argument.
> +A change in the CPU selection can happen if the callout has a lock
> +associated with it and is locked when this function is called.
> +A change in the CPU selection cannot happen if this function is
> +re-scheduled inside a callout function.
> +Else the callback function given by the
> +.Fa func
> +argument will be executed on the same CPU like previously done.
> +.Pp
> +.Ft int
> +.Fn callout_reset_sbt "struct callout *c" "sbintime_t sbt" \
> +"sbintime_t pr" "callout_func_t *func" "void *arg" "int flags"
> +This function works the same like the
> +.Fn callout_reset
> +function except the relative or absolute time after which the timeout
> +callback should happen is given by the
>  .Fa sbt
> -and extends for the amount of time specified in
> -.Fa pr .
> -If
> +argument and extends for the amount of time specified in the
> +.Fa pr
> +argument.
> +This function is used when you need high precision timeouts.
> +If the
>  .Fa sbt
> -specifies a time in the past,
> +argument 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
> +The
>  .Fa flags
> -may be specified to adjust the interpretation of
> +argument may be non-zero to adjust the interpretation of the
>  .Fa sbt
> -and
> -.Fa pr :
> +and the
> +.Fa pr
> +arguments:
>  .Bl -tag -width ".Dv C_DIRECT_EXEC"
>  .It Dv C_ABSOLUTE
>  Handle the
>  .Fa sbt
>  argument as an absolute time since boot.
> -By default,
> +By default, the
>  .Fa sbt
> -is treated as a relative amount of time,
> +argument is treated like a relative amount of time,
>  similar to
>  .Fa ticks .
>  .It Dv C_DIRECT_EXEC
> @@ -347,7 +301,7 @@ Callout functions run in this context ma
>  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.
> +divided by acceptable time deviation: 1 -- 1/2, 2 -- 1/4 and so on.
>  Note that the larger of
>  .Fa pr
>  or this value is used as the length of the time window.
> @@ -360,65 +314,215 @@ Align the timeouts to
>  calls if possible.
>  .El
>  .Pp
> -The
> -.Fn callout_reset
> -functions accept a
> +.Ft int
> +.Fn callout_reset_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
> +"sbintime_t pr" "callout_func_t *func" "void *arg" "int flags"
> +This function works the same like the
> +.Fn callout_reset_sbt
> +function except the callback function given by the
>  .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 will be executed on the same CPU which called this function.
> +A change in the CPU selection can happen if the callout has a lock
> +associated with it and is locked when this function is called.
> +A change in the CPU selection cannot happen if this function is
> +re-scheduled inside a callout function.
> +Else the callback function given by the
> +.Fa func
> +argument will be executed on the same CPU like previously done.
> +.Pp
> +.Ft int
> +.Fn callout_reset_sbt_on "struct callout *c" "sbintime_t sbt" \
> +"sbintime_t pr" "callout_func_t *func" "void *arg" "int cpu" "int flags"
> +This function works the same like the
> +.Fn callout_reset_sbt
> +function except the callback function given by the
> +.Fa func
> +argument will be executed on the CPU given by the
> +.Fa cpu
>  argument.
> -Upon invocation,
> +A change in the CPU selection can happen if the callout has a lock
> +associated with it and is locked when this function is called.
> +A change in the CPU selection cannot happen if this function is
> +re-scheduled inside a callout function.
> +Else the callback function given by the
>  .Fa func
> -will receive
> -.Fa arg
> -as its only argument.
> -The
> -.Fn callout_schedule
> -functions reuse the
> +argument will be executed on the same CPU like previously done.
> +.Pp
> +.Ft int
> +.Fn callout_schedule "struct callout *c" "int ticks"
> +This function works the same like the
> +.Fn callout_reset
> +function except it re-uses the callback function and the callback argument
> +already stored in the
> +.Pq struct callout
> +structure.
> +.Pp
> +.Ft int
> +.Fn callout_schedule_curcpu "struct callout *c" "int ticks"
> +This function works the same like the
> +.Fn callout_reset_curcpu
> +function except it re-uses the callback function and the callback argument
> +already stored in the
> +.Pq struct callout
> +structure.
> +.Pp
> +.Ft int
> +.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu"
> +This function works the same like the
> +.Fn callout_reset_on
> +function except it re-uses the callback function and the callback argument
> +already stored in the
> +.Pq struct callout
> +structure.
> +.Pp
> +.Ft int
> +.Fn callout_schedule_sbt "struct callout *c" "sbintime_t sbt" \
> +"sbintime_t pr" "int flags"
> +This function works the same like the
> +.Fn callout_reset_sbt
> +function except it re-uses the callback function and the callback argument
> +already stored in the
> +.Pq struct callout
> +structure.
> +.Pp
> +.Ft int
> +.Fn callout_schedule_sbt_curcpu "struct callout *c" "sbintime_t sbt" \
> +"sbintime_t pr" "int flags"
> +This function works the same like the
> +.Fn callout_reset_sbt_curcpu
> +function except it re-uses the callback function and the callback argument
> +already stored in the
> +.Pq struct callout
> +structure.
> +.Pp
> +.Ft int
> +.Fn callout_schedule_sbt_on "struct callout *c" "sbintime_t sbt" \
> +"sbintime_t pr" "int cpu" "int flags"
> +This function works the same like the
> +.Fn callout_reset_sbt_on
> +function except it re-uses the callback function and the callback argument
> +already stored in the
> +.Pq struct callout
> +structure.
> +.Sh CHECKING THE STATE OF CALLOUTS
> +.Ft int
> +.Fn callout_pending "struct callout *c"
> +This function returns non-zero if the callout pointed to by the
> +.Fa c
> +argument is pending for callback.
> +Else this function returns zero.
> +This function returns zero when inside the callout function if the
> +callout is not re-scheduled.
> +.Pp
> +.Ft int
> +.Fn callout_active "struct callout *c"
> +This function is deprecated and returns non-zero if the callout
> +pointed to by the
> +.Fa c
> +argument was scheduled in the past.
> +Else this function returns zero.
> +This function also returns zero after the
> +.Fn callout_deactivate
> +or the
> +.Fn callout_stop
> +or the
> +.Fn callout_drain
> +or the
> +.Fn callout_drain_async
> +function is called on the same callout as given by the
> +.Fa c
> +argument.
> +.Pp
> +.Ft void
> +.Fn callout_deactivate "struct callout *c"
> +This function is deprecated and ensures that subsequent calls to the
> +.Fn callout_activate
> +function returns zero until the callout is scheduled again.
> +.Sh STOPPING CALLOUTS
> +.Ft void
> +.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle"
> +This function is deprecated and cancels the timeout associated with the
> +.Fa handle
> +argument using the function pointed to by the
>  .Fa func
> -and
> +argument and having the
>  .Fa arg
> -arguments from the previous callout.
> -Note that one of the
> -.Fn callout_reset
> -functions must always be called to initialize
> +arguments to validate the handle.
> +If the handle does not correspond to a timeout with
> +the function
>  .Fa func
> -and
> +taking the argument
>  .Fa arg
> -before one of the
> -.Fn callout_schedule
> -functions can be used.
> +no action is taken. The
> +.Fa handle
> +must be initialised 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 uninitialised handle
> +is undefined.
>  .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.
> +.Ft int
> +.Fn callout_stop "struct callout *c"
> +This function is used to stop a timeout function invocation associated with the callout pointed to by the
> +.Fa c
> +argument, in a non-blocking fashion.
> +This function can be called multiple times in a row with no side effects, even if the callout is already stopped. This function however should not be called before the callout has been initialised.
> +This function returns a non-zero value if the given callout was pending and
> +the callback function was prevented from being called.
> +Else a value of zero is returned.
> +If a lock is associated with the callout given by the
> +.Fa c
> +argument and it is exclusivly locked when this function is called, the
> +.Fn callout_stop
> +function will always ensure that the callback function is never reached.
> +In other words the callout will be atomically stopped.
> +Else there is no such guarantee.
> +.Sh DRAINING CALLOUTS
> +.Ft int
> +.Fn callout_drain "struct callout *c"
> +This function works the same like the
> +.Fn callout_stop
> +function except it ensures that all callback functions have returned and there are no more references to the callout pointed to by the
> +.Fa c
> +argument inside the callout subsystem before it returns.
> +Also this function ensures that the lock, if any, associated with the
> +callout is no longer being used.
> +When this function returns, it is safe to free the callout structure pointed to by the
> +.Fa c
> +argument.
>  .Pp
> +.Ft int
> +.Fn callout_drain_async "struct callout *c" "callout_func_t *fn" "void *arg"
> +This function is non-blocking and works the same like the
> +.Fn callout_stop
> +function except if it returns non-zero it means the callback function pointed to by the
> +.Fa fn
> +argument will be called back with the
> +.Fa arg
> +argument when all references to the callout pointed to by the
> +.Fa c
> +argument are gone.
> +If this function returns zero, it is safe to free the callout structure pointed to by the
> +.Fa c
> +argument right away.
> +.Sh CALLOUT FUNCTION RESTRICTIONS
> +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.
> +.Sh CALLOUT SUBSYSTEM INTERNALS
> +The callout subsystem has its own set of spinlocks to protect its internal state.
> +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.
>  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
> @@ -427,50 +531,7 @@ Softclock threads for CPUs other than ze
>  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.
> -.Ss "Avoiding Race Conditions"
> +.Sh "AVOIDING RACE CONDITIONS"
>  The callout subsystem invokes callout functions from its own thread
>  context.
>  Without some kind of synchronization,
> @@ -487,7 +548,7 @@ 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
> +Callouts can be associated with a specific lock when they are initialised
>  by
>  .Fn callout_init_mtx ,
>  .Fn callout_init_rm ,
> @@ -508,7 +569,7 @@ or
>  .Fn callout_schedule
>  functions to provide this safety.
>  .Pp
> -A callout initialized via
> +A callout initialised via
>  .Fn callout_init
>  with
>  .Fa mpsafe
> @@ -531,9 +592,8 @@ 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.
> +not yet executed, then a return value of zero indicates that the
> +callout function is about to be called.
>  For example:
>  .Bd -literal -offset indent
>  if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) {
> @@ -589,16 +649,14 @@ The callout function should first check
>  .Em pending
>  flag and return without action if
>  .Fn callout_pending
> -returns
> -.Dv TRUE .
> +returns non-zero.
>  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.
> +returns zero 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
> @@ -668,129 +726,13 @@ a callout should always be drained prior
>  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
> +The
>  .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 non-zero if the callout was pending before the new
> -function invocation was scheduled.
> -.Pp
> -The
> -.Fn callout_stop
> -and
> -.Fn callout_drain
> -functions return non-zero if the callout was still pending when it was
> -called or zero otherwise.
> -The
> -.Fn timeout
> -function returns a
> -.Ft struct callout_handle
> -that can be passed to
> -.Fn untimeout .
> +functions are a legacy API that will be removed in a future release.
> +New code should not use these routines.
>
> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
>


More information about the svn-src-head mailing list