Thanks! ok mvs@
> On 31 Dec 2022, at 19:22, Scott Cheloha <[email protected]> wrote:
>
> mvs@ is nudging me to realign the timeout.9 page with the state of the
> kernel.
>
> Here is my rewrite (again).
>
> There are some bits that I want to rework. The opening paragraph is
> especially clickety-clackety.
>
> Still, I think this is an improvement over what's in-tree. And the
> technical content should be complete and accurate, which is the most
> important thing.
>
> ok?
>
> Index: timeout.9
> ===================================================================
> RCS file: /cvs/src/share/man/man9/timeout.9,v
> retrieving revision 1.55
> diff -u -p -r1.55 timeout.9
> --- timeout.9 22 Jun 2022 14:10:49 -0000 1.55
> +++ timeout.9 31 Dec 2022 16:19:27 -0000
> @@ -1,6 +1,7 @@
> .\" $OpenBSD: timeout.9,v 1.55 2022/06/22 14:10:49 visa Exp $
> .\"
> .\" Copyright (c) 2000 Artur Grabowski <[email protected]>
> +.\" Copyright (c) 2021, 2022 Scott Cheloha <[email protected]>
> .\" All rights reserved.
> .\"
> .\" Redistribution and use in source and binary forms, with or without
> @@ -36,6 +37,7 @@
> .Nm timeout_add_nsec ,
> .Nm timeout_add_usec ,
> .Nm timeout_add_tv ,
> +.Nm timeout_abs_ts ,
> .Nm timeout_del ,
> .Nm timeout_del_barrier ,
> .Nm timeout_barrier ,
> @@ -44,281 +46,370 @@
> .Nm timeout_triggered ,
> .Nm TIMEOUT_INITIALIZER ,
> .Nm TIMEOUT_INITIALIZER_FLAGS
> -.Nd execute a function after a specified period of time
> +.Nd execute a function in the future
> .Sh SYNOPSIS
> .In sys/types.h
> .In sys/timeout.h
> .Ft void
> -.Fn timeout_set "struct timeout *to" "void (*fn)(void *)" "void *arg"
> +.Fo timeout_set
> +.Fa "struct timeout *to"
> +.Fa "void (*fn)(void *)"
> +.Fa "void *arg"
> +.Fc
> .Ft void
> .Fo timeout_set_flags
> .Fa "struct timeout *to"
> .Fa "void (*fn)(void *)"
> .Fa "void *arg"
> +.Fa "int kclock"
> .Fa "int flags"
> .Fc
> .Ft void
> -.Fn timeout_set_proc "struct timeout *to" "void (*fn)(void *)" "void *arg"
> +.Fo timeout_set_proc
> +.Fa "struct timeout *to"
> +.Fa "void (*fn)(void *)"
> +.Fa "void *arg"
> +.Fc
> .Ft int
> -.Fn timeout_add "struct timeout *to" "int ticks"
> +.Fo timeout_add
> +.Fa "struct timeout *to"
> +.Fa "int nticks"
> +.Fc
> .Ft int
> -.Fn timeout_del "struct timeout *to"
> +.Fo timeout_add_sec
> +.Fa "struct timeout *to"
> +.Fa "int secs"
> +.Fc
> .Ft int
> -.Fn timeout_del_barrier "struct timeout *to"
> -.Ft void
> -.Fn timeout_barrier "struct timeout *to"
> +.Fo timeout_add_msec
> +.Fa "struct timeout *to"
> +.Fa "int msecs"
> +.Fc
> .Ft int
> -.Fn timeout_pending "struct timeout *to"
> +.Fo timeout_add_usec
> +.Fa "struct timeout *to"
> +.Fa "int usecs"
> +.Fc
> .Ft int
> -.Fn timeout_initialized "struct timeout *to"
> +.Fo timeout_add_nsec
> +.Fa "struct timeout *to"
> +.Fa "int nsecs"
> +.Fc
> .Ft int
> -.Fn timeout_triggered "struct timeout *to"
> +.Fo timeout_add_tv
> +.Fa "struct timeout *to"
> +.Fa "struct timeval *tv"
> +.Fc
> .Ft int
> -.Fn timeout_add_tv "struct timeout *to" "struct timeval *"
> +.Fo timeout_abs_ts
> +.Fa "struct timeout *to"
> +.Fa "const struct timespec *abs"
> +.Fc
> .Ft int
> -.Fn timeout_add_sec "struct timeout *to" "int sec"
> +.Fo timeout_del
> +.Fa "struct timeout *to"
> +.Fc
> .Ft int
> -.Fn timeout_add_msec "struct timeout *to" "int msec"
> +.Fo timeout_del_barrier
> +.Fa "struct timeout *to"
> +.Fc
> +.Ft void
> +.Fo timeout_barrier
> +.Fa "struct timeout *to"
> +.Fc
> +.Ft int
> +.Fo timeout_pending
> +.Fa "struct timeout *to"
> +.Fc
> .Ft int
> -.Fn timeout_add_usec "struct timeout *to" "int usec"
> +.Fo timeout_initialized
> +.Fa "struct timeout *to"
> +.Fc
> .Ft int
> -.Fn timeout_add_nsec "struct timeout *to" "int nsec"
> -.Fn TIMEOUT_INITIALIZER "void (*fn)(void *)" "void *arg"
> -.Fn TIMEOUT_INITIALIZER_FLAGS "void (*fn)(void *)" "void *arg" "int flags"
> +.Fo timeout_triggered
> +.Fa "struct timeout *to"
> +.Fc
> +.Fo TIMEOUT_INITIALIZER
> +.Fa "void (*fn)(void *)"
> +.Fa "void *arg"
> +.Fc
> +.Fo TIMEOUT_INITIALIZER_FLAGS
> +.Fa "void (*fn)(void *)"
> +.Fa "void *arg"
> +.Fa "int kclock"
> +.Fa "int flags"
> +.Fc
> .Sh DESCRIPTION
> The
> .Nm timeout
> -API provides a mechanism to execute a function at a given time.
> -The granularity of the time is limited by the granularity of the
> -.Xr hardclock 9
> -timer which executes
> -.Xr hz 9
> -times a second.
> +API provides a mechanism to schedule a function for asynchronous
> +execution in the future.
> .Pp
> -It is the responsibility of the caller to provide these functions with
> -pre-allocated timeout structures.
> +All state is encapsulated in a caller-allocated
> +.Vt struct timeout
> +.Po
> +hereafter,
> +a
> +.Qq timeout
> +.Pc .
> +A timeout must be initialized before it may be used as input to other
> +functions in the API.
> .Pp
> The
> .Fn timeout_set
> -function prepares the timeout structure
> -.Fa to
> -to be used in future calls to
> -.Fn timeout_add
> -and
> -.Fn timeout_del .
> -The timeout will be prepared to call the function specified by the
> +function initializes the timeout
> +.Fa to .
> +When the timeout is executed,
> +the function
> .Fa fn
> -argument with a
> -.Fa void *
> -argument given in the
> +will be called with
> .Fa arg
> -argument.
> -Once initialized, the
> -.Fa to
> -structure can be used repeatedly in
> -.Fn timeout_add
> -and
> -.Fn timeout_del
> -and does not need to be reinitialized unless
> -the function called and/or its argument must change.
> +as its sole parameter.
> +The timeout is implicitly scheduled against the
> +.Dv KCLOCK_NONE
> +clock and is not configured with any additional flags.
> .Pp
> The
> .Fn timeout_set_flags
> function is similar to
> -.Fn timeout_set
> -but it additionally accepts the bitwise OR of zero or more of the
> -following
> +.Fn timeout_set ,
> +except that it takes two additional parameters:
> +.Bl -tag -width kclock
> +.It Fa kclock
> +The timeout is scheduled against the given
> +.Fa kclock ,
> +which must be one of the following:
> +.Bl -tag -width KCLOCK_UPTIME
> +.It Dv KCLOCK_NONE
> +Low resolution tick-based clock.
> +The granularity of this clock is limited by the
> +.Xr hardclock 9 ,
> +which executes roughly
> +.Xr hz 9
> +times per second.
> +.It Dv KCLOCK_UPTIME
> +The uptime clock.
> +Counts the time elapsed since the system booted.
> +.El
> +.It Fa flags
> +The timeout's behavior may be configured with the bitwise OR of
> +zero or more of the following
> .Fa flags :
> -.Bl -tag -width TIMEOUT_PROC -offset indent
> +.Bl -tag -width TIMEOUT_PROC
> .It Dv TIMEOUT_PROC
> -Runs the timeout in a process context instead of the default
> +Execute the timeout in a process context instead of the default
> .Dv IPL_SOFTCLOCK
> interrupt context.
> .El
> +.El
> .Pp
> The
> .Fn timeout_set_proc
> function is similar to
> +.Fn timeout_set ,
> +except that the given timeout is configured with the
> +.Dv TIMEOUT_PROC
> +flag.
> +.Pp
> +A timeout may also be initialized statically.
> +The
> +.Fn TIMEOUT_INITIALIZER
> +macro is equivalent to the
> .Fn timeout_set
> -but it runs the timeout in a process context instead of the default
> -.Dv IPL_SOFTCLOCK
> -interrupt context.
> +function and the
> +.Fn TIMEOUT_INITIALIZER_FLAGS
> +macro is equivalent to the
> +.Fn timeout_set_flags
> +function.
> .Pp
> -The function
> -.Fn timeout_add
> -schedules the execution of the
> -.Fa to
> -timeout in at least
> -.Fa ticks Ns /hz
> +The interfaces available for scheduling a timeout vary with the
> +.Fa kclock
> +set during initialization.
> +.Pp
> +.Dv KCLOCK_NONE
> +timeouts may be scheduled with the function
> +.Fn timeout_add ,
> +which schedules the given timeout to execute after
> +.Fa nticks
> +.Xr hardclock 9
> +ticks have elapsed.
> +In practice,
> +.Fa nticks
> +ticks will usually elapse in slightly less than
> +.Pq Fa nticks Cm / Dv hz
> seconds.
> Negative values of
> -.Fa ticks
> +.Fa nticks
> are illegal.
> -If the value is
> -.Sq 0
> -it will, in the current implementation, be treated as
> -.Sq 1 ,
> -but in the future it might cause an immediate timeout.
> -The timeout in the
> -.Fa to
> -argument must be already initialized by
> -.Fn timeout_set ,
> -.Fn timeout_set_flags ,
> +If
> +.Fa nticks
> +is zero it will be silently rounded up to one.
> +.Pp
> +For convenience,
> +.Dv KCLOCK_NONE
> +timeouts may also be scheduled with
> +.Fn timeout_add_sec ,
> +.Fn timeout_add_msec ,
> +.Fn timeout_add_usec ,
> +.Fn timeout_add_nsec ,
> or
> -.Fn timeout_set_proc
> -and may not be used in calls to
> +.Fn timeout_add_tv .
> +These wrapper functions convert their input durations to a count of
> +.Xr hardclock 9
> +ticks before calling
> +.Fn timeout_add
> +to schedule the given timeout.
> +.Pp
> +Timeouts for any other
> +.Fa kclock
> +may be scheduled with
> +.Fn timeout_abs_ts ,
> +which schedules the given timeout to execute at or after the absolute time
> +.Fa abs
> +has elapsed on the timeout's
> +.Fa kclock .
> +.Pp
> +Once scheduled,
> +a timeout is said to be
> +.Qq pending .
> +A pending timeout may not be reinitialized with
> .Fn timeout_set ,
> .Fn timeout_set_flags ,
> or
> .Fn timeout_set_proc
> -until it has timed out or been removed with
> -.Fn timeout_del .
> -If the timeout in the
> -.Fa to
> -argument is already scheduled, the old execution time will be
> -replaced by the new one.
> +until it has been executed or it has been cancelled with
> +.Fn timeout_del
> +or
> +.Fn timeout_del_barrier .
> +A pending timeout may be rescheduled without first cancelling it with
> +.Fn timeout_del
> +or
> +.Fn timeout_del_barrier .
> +The new expiration time will quietly supersede the original.
> .Pp
> The function
> .Fn timeout_del
> -will cancel the timeout in the argument
> -.Fa to .
> -If the timeout has already executed or has never been added,
> +cancels any pending execution of the given timeout.
> +If the timeout has already executed or was never scheduled,
> the call will have no effect.
> .Pp
> +The
> .Fn timeout_del_barrier
> -is like
> -.Fn timeout_del
> -but it will wait until any current execution of the timeout has completed.
> +function is similar to
> +.Fn timeout_del ,
> +except that it may block until any current execution of the given timeout
> +has completed.
> .Pp
> +The
> .Fn timeout_barrier
> -ensures that any current execution of the timeout in the argument
> -.Fa to
> -has completed before returning.
> +function blocks until any current execution of the given timeout
> +has completed.
> .Pp
> -The caller of
> +Callers of
> .Fn timeout_barrier
> -or
> +and
> .Fn timeout_del_barrier
> must not hold locks that can block processing in the timeout's context.
> -Otherwise, the system will deadlock.
> +Otherwise,
> +the system will deadlock.
> .Pp
> The
> .Fn timeout_pending
> -macro can be used to check if a timeout is scheduled to run.
> +macro indicates whether the given timeout is scheduled for execution.
> +A timeout's pending status is cleared when it executes or is cancelled.
> .Pp
> The
> .Fn timeout_initialized
> -macro can be used to check if a timeout has been initialized.
> +macro indicates whether the given timeout has been initialized with
> +.Fn timeout_set
> +or
> +.Fn timeout_set_flags .
> +This macro must not be used unless the memory pointed to by
> +.Fa to
> +has been zeroed,
> +or its return value is meaningless.
> .Pp
> The
> .Fn timeout_triggered
> -macro can be used to check if a timeout is running or has been run.
> -The
> -.Fn timeout_add
> -and
> -.Fn timeout_del
> -functions clear the triggered state for that timeout.
> -.Pp
> -When possible, use the
> -.Fn timeout_add_tv ,
> -.Fn timeout_add_sec ,
> -.Fn timeout_add_msec ,
> -.Fn timeout_add_usec ,
> -and
> -.Fn timeout_add_nsec
> -functions instead of
> -.Fn timeout_add .
> -Those functions add a timeout whilst converting the time specified
> -by the respective types.
> -They also defer the timeout handler for at least one tick if called
> -with a positive value.
> -.Pp
> -A timeout declaration can be initialised with the
> -.Fn TIMEOUT_INITIALIZER
> -macro.
> -The timeout will be prepared to call the function specified by the
> -.Fa fn
> -argument with the
> -.Fa void *
> -argument given in
> -.Fa arg .
> -.Pp
> -The
> -.Fn TIMEOUT_INITIALIZER_FLAGS
> -macro is similar to
> -.Fn TIMEOUT_INITIALIZER ,
> -but it accepts additional flags.
> -See the
> -.Fn timeout_set_flags
> -function for details.
> +macro indicates whether the given timeout is executing or has finished
> +executing.
> +Rescheduling or cancelling a timeout clears its triggered status.
> .Sh CONTEXT
> .Fn timeout_set ,
> .Fn timeout_set_flags ,
> -and
> -.Fn timeout_set_proc
> -can be called during autoconf, from process context, or from interrupt
> -context.
> -.Pp
> +.Fn timeout_set_proc ,
> .Fn timeout_add ,
> .Fn timeout_add_sec ,
> .Fn timeout_add_msec ,
> -.Fn timeout_add_nsec ,
> .Fn timeout_add_usec ,
> +.Fn timeout_add_nsec ,
> .Fn timeout_add_tv ,
> +.Fn timeout_abs_ts ,
> .Fn timeout_del ,
> .Fn timeout_pending ,
> .Fn timeout_initialized ,
> +and
> .Fn timeout_triggered
> -can be called during autoconf, from process context, or from any
> -interrupt context at or below
> -.Dv IPL_CLOCK .
> +may be called during autoconf,
> +from process context,
> +or from any interrupt context.
> .Pp
> .Fn timeout_barrier
> and
> .Fn timeout_del_barrier
> -can be called from process context.
> +may only be called from process context.
> .Pp
> -When the timeout runs, the
> +When a timeout is executed,
> +the function
> .Fa fn
> -argument to
> -.Fn timeout_set
> -or
> -.Fn timeout_set_flags
> -will be called in an interrupt context at
> +set during initialization is called from the
> .Dv IPL_SOFTCLOCK
> -or a process context if the
> +interrupt context,
> +or a process context if the timeout was configured with the
> .Dv TIMEOUT_PROC
> -flag was given at initialization.
> -The
> +flag.
> +The function
> .Fa fn
> -argument to
> -.Fn timeout_set_proc
> -will be called in a process context.
> +must not block and must be safe to execute on any CPU in the system.
> +.Pp
> +Currently,
> +all timeouts are executed under the kernel lock.
> .Sh RETURN VALUES
> .Fn timeout_add ,
> .Fn timeout_add_sec ,
> .Fn timeout_add_msec ,
> -.Fn timeout_add_nsec ,
> .Fn timeout_add_usec ,
> +.Fn timeout_add_nsec ,
> +.Fn timeout_add_tv ,
> and
> -.Fn timeout_add_tv
> -will return 1 if the timeout
> +.Fn timeout_abs_ts
> +return 1 if the timeout
> .Fa to
> -was added to the timeout schedule or 0 if it was already queued.
> +is newly scheduled,
> +or zero if the timeout was already pending.
> .Pp
> .Fn timeout_del
> and
> .Fn timeout_del_barrier
> -will return 1 if the timeout
> +return 1 if the timeout
> .Fa to
> -was removed from the pending timeout schedule or 0 if it was not
> -currently queued.
> +was pending,
> +or zero otherwise.
> +.Pp
> +.Fn timeout_pending ,
> +.Fn timeout_initialized ,
> +and
> +.Fn timeout_triggered
> +return non-zero if the corresponding condition is true,
> +or zero otherwise.
> .Sh CODE REFERENCES
> -These functions are implemented in the file
> -.Pa sys/kern/kern_timeout.c .
> +.Pa sys/kern/kern_timeout.c
> .Sh SEE ALSO
> +.Xr hardclock 9 ,
> .Xr hz 9 ,
> +.Xr microtime 9 ,
> .Xr splclock 9 ,
> +.Xr task_add 9 ,
> .Xr tsleep 9 ,
> .Xr tvtohz 9
> .Rs