From: cheloha Date: Sun, 1 Jan 2023 01:19:18 +0000 (+0000) Subject: timeout.9: document new interfaces, miscellaneous rewrites and cleanup X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=86a45bbd35a5de3c03ceb2189012acba73cdae37;p=openbsd timeout.9: document new interfaces, miscellaneous rewrites and cleanup - Document timeout_abs_ts(9). - Add the kclock arguments to timeout_set_flags(9) and TIMEOUT_INITIALIZER_FLAGS(9). - Document KCLOCK_NONE and KCLOCK_UPTIME. - Mention the static initialization macros alongside timeout_set(9) etc.; keep relevant information adjacent. - Mention timeout_add_sec(9) etc. alongside timeout_add(9); keep relevant information adjacent. ... plus many other cleanups, rewrites, and rearrangements. Prompted by mvs@ and many others. With input from jmc@, mvs@, kn@, schwarze@, and probably a few others I have forgotten. v1: https://marc.info/?l=openbsd-tech&m=162449274513068&w=2 v2: https://marc.info/?l=openbsd-tech&m=165851505627764&w=2 v3: https://marc.info/?l=openbsd-tech&m=167250339811308&w=2 ok jmc@ mvs@ schwarze@ --- diff --git a/share/man/man9/timeout.9 b/share/man/man9/timeout.9 index 7cd51f32c05..cbc6eb3ed34 100644 --- a/share/man/man9/timeout.9 +++ b/share/man/man9/timeout.9 @@ -1,6 +1,7 @@ -.\" $OpenBSD: timeout.9,v 1.55 2022/06/22 14:10:49 visa Exp $ +.\" $OpenBSD: timeout.9,v 1.56 2023/01/01 01:19:18 cheloha Exp $ .\" .\" Copyright (c) 2000 Artur Grabowski +.\" Copyright (c) 2021, 2022 Scott Cheloha .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -23,7 +24,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: June 22 2022 $ +.Dd $Mdocdate: January 1 2023 $ .Dt TIMEOUT_SET 9 .Os .Sh NAME @@ -33,9 +34,10 @@ .Nm timeout_add , .Nm timeout_add_sec , .Nm timeout_add_msec , -.Nm timeout_add_nsec , .Nm timeout_add_usec , +.Nm timeout_add_nsec , .Nm timeout_add_tv , +.Nm timeout_abs_ts , .Nm timeout_del , .Nm timeout_del_barrier , .Nm timeout_barrier , @@ -44,281 +46,365 @@ .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 +.Fo timeout_add_usec +.Fa "struct timeout *to" +.Fa "int usecs" +.Fc .Ft int -.Fn timeout_pending "struct timeout *to" +.Fo timeout_add_nsec +.Fa "struct timeout *to" +.Fa "int nsecs" +.Fc .Ft int -.Fn timeout_initialized "struct timeout *to" +.Fo timeout_add_tv +.Fa "struct timeout *to" +.Fa "struct timeval *tv" +.Fc .Ft int -.Fn timeout_triggered "struct timeout *to" +.Fo timeout_abs_ts +.Fa "struct timeout *to" +.Fa "const struct timespec *abs" +.Fc .Ft int -.Fn timeout_add_tv "struct timeout *to" "struct timeval *" +.Fo timeout_del +.Fa "struct timeout *to" +.Fc .Ft int -.Fn timeout_add_sec "struct timeout *to" "int sec" +.Fo timeout_del_barrier +.Fa "struct timeout *to" +.Fc +.Ft void +.Fo timeout_barrier +.Fa "struct timeout *to" +.Fc .Ft int -.Fn timeout_add_msec "struct timeout *to" "int msec" +.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. +subsystem schedules functions 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 +.Vt struct timeout +allocated by the caller. +A timeout must be initialized before it may be used as input to other +functions in the API. +Once initialized, +a timeout does not need to be reinitialized unless its function or argument +must change. .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 at least +.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, -the call will have no effect. +cancels any pending execution of the given timeout. .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 also blocks 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. .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