On Thu, Jun 24, 2021 at 06:51:07AM +0100, Jason McIntyre wrote:
> On Wed, Jun 23, 2021 at 06:57:00PM -0500, Scott Cheloha wrote:
> > Hi,
> > 
> > I want to document kclock timeouts so others can use them.
> 
> morning. reads fine, except one issue:
> 
> [...]
> 
> > +.Bl -tag -width kclock
> > +.It Fa kclock
> > +The timeout is scheduled against the given
> > +.Fa kclock,
> 
> you need a space between kclock and the comma

Huh, I'm a little surprised -Tlint doesn't flag that.

Fixed.

Are there any other mdoc(7)-type stylistic anachronisms we can fix up?

Index: share/man/man9/timeout.9
===================================================================
RCS file: /cvs/src/share/man/man9/timeout.9,v
retrieving revision 1.53
diff -u -p -r1.53 timeout.9
--- share/man/man9/timeout.9    11 May 2021 13:29:25 -0000      1.53
+++ share/man/man9/timeout.9    24 Jun 2021 22:37:38 -0000
@@ -44,7 +44,7 @@
 .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
@@ -55,12 +55,13 @@
 .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"
 .Ft int
-.Fn timeout_add "struct timeout *to" "int ticks"
+.Fn timeout_add "struct timeout *to" "int nticks"
 .Ft int
 .Fn timeout_del "struct timeout *to"
 .Ft int
@@ -83,174 +84,218 @@
 .Fn timeout_add_usec "struct timeout *to" "int usec"
 .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"
+.Ft int
+.Fn timeout_in_nsec "struct timeout *to" "uint64_t nsecs"
+.Ft int
+.Fn timeout_at_ts "struct timeout *to" "const struct timespec *abs"
+.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 timeout structure
+.Pq hereafter, a Qo timeout Qc .
+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 executed,
+the timeout will call the function
 .Fa fn
-argument with a
-.Fa void *
-argument given in the
+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 first 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
+function is equivalent 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
+The interfaces available for scheduling a timeout vary with the timeout's
+.Fa kclock .
+.Pp
+.Dv KCLOCK_NONE
+timeouts may be scheduled with the function
+.Fn timeout_add ,
+which arms
 .Fa to
-timeout in at least
-.Fa ticks Ns /hz
+for execution after
+.Fa nticks
+.Xr hardclock 9
+ticks have elapsed
+.Pq see Xr hz 9 for details .
+In practice,
+.Fa nticks
+ticks will usually elapse in slightly less than
+.Fa nticks Ns /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
+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_add_tv .
+These wrapper functions convert their inputs to a count of ticks before
+calling
+.Fn timeout_add
+to schedule the given timeout.
+.Pp
+.Dv KCLOCK_UPTIME
+timeouts may be scheduled with
+.Fn timeout_in_nsec ,
+which arms
 .Fa to
-argument must be already initialized by
-.Fn timeout_set ,
-.Fn timeout_set_flags ,
+to execute after at least
+.Fa nsecs
+nanoseconds have elapsed,
+or with
+.Fn timeout_at_ts ,
+which arms
+.Fa to
+to execute at or after the absolute time
+.Fa abs
+has elapsed on the system uptime clock.
+.Pp
+Once scheduled,
+a timeout may not be reinitialized with
+.Fn timeout_set
 or
-.Fn timeout_set_proc
-and may not be used in calls to
-.Fn timeout_set ,
-.Fn timeout_set_flags ,
+.Fn timeout_set_flags
+until it has executed or been cancelled with
+.Fn timeout_del
 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.
+.Fn timeout_del_barrier .
+.Pp
+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
+cancels any pending execution of
 .Fa to .
-If the timeout has already executed or has never been added
+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 timeout
+.Fa to
+has completed.
 .Pp
+The
 .Fn timeout_barrier
-ensures that any current execution of the timeout in the argument
+function blocks until any current execution of the timeout
 .Fa to
-has completed before returning.
+has completed.
 .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 is executed or 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 underlying
+.Fa to
+has been zeroed.
 .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.
+can be called during autoconf,
+from process context,
+or from interrupt context.
 .Pp
 .Fn timeout_add ,
 .Fn timeout_add_sec ,
@@ -258,54 +303,53 @@ context.
 .Fn timeout_add_nsec ,
 .Fn timeout_add_usec ,
 .Fn timeout_add_tv ,
+.Fn timeout_in_nsec ,
+.Fn timeout_at_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
+can be called during autoconf,
+from process context,
+or from any interrupt context at or below
 .Dv IPL_CLOCK .
 .Pp
+The
 .Fn timeout_barrier
 and
 .Fn timeout_del_barrier
-can be called from process context.
+functions may only be called from a 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
+given at initialization will be 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
-.Fa fn
-argument to
-.Fn timeout_set_proc
-will be called in a process context.
+flag.
 .Sh RETURN VALUES
 .Fn timeout_add ,
 .Fn timeout_add_sec ,
 .Fn timeout_add_msec ,
 .Fn timeout_add_nsec ,
 .Fn timeout_add_usec ,
-and
 .Fn timeout_add_tv
+.Fn timeout_in_nsec ,
+and
+.Fn timeout_at_ts
 will return 1 if the timeout
 .Fa to
-was added to the timeout schedule or 0 if it was already queued.
+was newly scheduled or 0 if the timeout was already pending.
 .Pp
 .Fn timeout_del
 and
 .Fn timeout_del_barrier
 will 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 0 otherwise.
 .Sh CODE REFERENCES
 These functions are implemented in the file
 .Pa sys/kern/kern_timeout.c .
Index: sys/kern/kern_timeout.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_timeout.c,v
retrieving revision 1.85
diff -u -p -r1.85 kern_timeout.c
--- sys/kern/kern_timeout.c     19 Jun 2021 02:05:33 -0000      1.85
+++ sys/kern/kern_timeout.c     24 Jun 2021 22:37:39 -0000
@@ -252,7 +252,7 @@ timeout_proc_init(void)
        kthread_create_deferred(softclock_create_thread, NULL);
 }
 
-static inline void
+void
 _timeout_set(struct timeout *to, void (*fn)(void *), void *arg, int kclock,
     int flags)
 {
@@ -269,9 +269,10 @@ timeout_set(struct timeout *new, void (*
 }
 
 void
-timeout_set_flags(struct timeout *to, void (*fn)(void *), void *arg, int flags)
+timeout_set_flags(struct timeout *to, void (*fn)(void *), void *arg, int 
kclock,
+    int flags)
 {
-       _timeout_set(to, fn, arg, KCLOCK_NONE, flags);
+       _timeout_set(to, fn, arg, kclock, flags);
 }
 
 void
@@ -280,13 +281,6 @@ timeout_set_proc(struct timeout *new, vo
        _timeout_set(new, fn, arg, KCLOCK_NONE, TIMEOUT_PROC);
 }
 
-void
-timeout_set_kclock(struct timeout *to, void (*fn)(void *), void *arg,
-    int kclock, int flags)
-{
-       _timeout_set(to, fn, arg, kclock, flags | TIMEOUT_KCLOCK);
-}
-
 int
 timeout_add(struct timeout *new, int to_ticks)
 {
@@ -294,7 +288,6 @@ timeout_add(struct timeout *new, int to_
        int ret = 1;
 
        KASSERT(ISSET(new->to_flags, TIMEOUT_INITIALIZED));
-       KASSERT(!ISSET(new->to_flags, TIMEOUT_KCLOCK));
        KASSERT(new->to_kclock == KCLOCK_NONE);
        KASSERT(to_ticks >= 0);
 
@@ -402,8 +395,8 @@ timeout_at_ts(struct timeout *to, const 
 
        mtx_enter(&timeout_mutex);
 
-       KASSERT(ISSET(to->to_flags, TIMEOUT_INITIALIZED | TIMEOUT_KCLOCK));
-       KASSERT(to->to_kclock != KCLOCK_NONE);
+       KASSERT(ISSET(to->to_flags, TIMEOUT_INITIALIZED));
+       KASSERT(to->to_kclock == KCLOCK_UPTIME);
 
        old_abstime = to->to_abstime;
        to->to_abstime = *abstime;
@@ -497,7 +490,8 @@ timeout_barrier(struct timeout *to)
        procflag = (to->to_flags & TIMEOUT_PROC);
        timeout_sync_order(procflag);
 
-       timeout_set_flags(&barrier, timeout_barrier_timeout, &c, procflag);
+       timeout_set_flags(&barrier, timeout_barrier_timeout, &c, KCLOCK_NONE,
+           procflag);
        barrier.to_process = curproc->p_p;
        cond_init(&c);
 
@@ -535,7 +529,7 @@ timeout_bucket(const struct timeout *to)
        struct timespec diff, shifted_abstime;
        uint32_t level;
 
-       KASSERT(ISSET(to->to_flags, TIMEOUT_KCLOCK));
+       KASSERT(to->to_kclock == KCLOCK_UPTIME);
        KASSERT(timespeccmp(&kc->kc_lastscan, &to->to_abstime, <));
 
        timespecsub(&to->to_abstime, &kc->kc_lastscan, &diff);
@@ -750,7 +744,7 @@ softclock(void *arg)
                CIRCQ_REMOVE(&to->to_list);
                if (to == first_new)
                        new = 1;
-               if (ISSET(to->to_flags, TIMEOUT_KCLOCK))
+               if (to->to_kclock != KCLOCK_NONE)
                        softclock_process_kclock_timeout(to, new);
                else
                        softclock_process_tick_timeout(to, new);
@@ -915,7 +909,7 @@ db_show_timeout(struct timeout *to, stru
        else if (bucket == &timeout_proc)
                where = "thread";
        else {
-               if (ISSET(to->to_flags, TIMEOUT_KCLOCK))
+               if (to->to_kclock != KCLOCK_NONE)
                        wheel = timeout_wheel_kc;
                else
                        wheel = timeout_wheel;
@@ -924,7 +918,7 @@ db_show_timeout(struct timeout *to, stru
                    (bucket - wheel) / WHEELSIZE);
                where = buf;
        }
-       if (ISSET(to->to_flags, TIMEOUT_KCLOCK)) {
+       if (to->to_kclock != KCLOCK_NONE) {
                kc = &timeout_kclock[to->to_kclock];
                timespecsub(&to->to_abstime, &kc->kc_lastscan, &remaining);
                db_printf("%20s  %8s  %7s  0x%0*lx  %s\n",
Index: sys/kern/kern_fork.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.236
diff -u -p -r1.236 kern_fork.c
--- sys/kern/kern_fork.c        19 Jun 2021 02:05:33 -0000      1.236
+++ sys/kern/kern_fork.c        24 Jun 2021 22:37:39 -0000
@@ -201,7 +201,7 @@ process_initialize(struct process *pr, s
        rw_init(&pr->ps_lock, "pslock");
        mtx_init(&pr->ps_mtx, IPL_MPFLOOR);
 
-       timeout_set_kclock(&pr->ps_realit_to, realitexpire, pr,
+       timeout_set_flags(&pr->ps_realit_to, realitexpire, pr,
            KCLOCK_UPTIME, 0);
        timeout_set(&pr->ps_rucheck_to, rucheck, pr);
 }
Index: sys/sys/timeout.h
===================================================================
RCS file: /cvs/src/sys/sys/timeout.h,v
retrieving revision 1.42
diff -u -p -r1.42 timeout.h
--- sys/sys/timeout.h   19 Jun 2021 02:05:33 -0000      1.42
+++ sys/sys/timeout.h   24 Jun 2021 22:37:39 -0000
@@ -54,7 +54,6 @@ struct timeout {
 #define TIMEOUT_ONQUEUE                0x02    /* on any timeout queue */
 #define TIMEOUT_INITIALIZED    0x04    /* initialized */
 #define TIMEOUT_TRIGGERED      0x08    /* running or ran */
-#define TIMEOUT_KCLOCK         0x10    /* clock-based timeout */
 
 struct timeoutstat {
        uint64_t tos_added;             /* timeout_add*(9) calls */
@@ -98,18 +97,14 @@ int timeout_sysctl(void *, size_t *, voi
        .to_kclock = (_kclock)                                          \
 }
 
-#define TIMEOUT_INITIALIZER_KCLOCK(_fn, _arg, _kclock, _flags)         \
-    __TIMEOUT_INITIALIZER((_fn), (_args), (_kclock), (_flags) | TIMEOUT_KCLOCK)
-
-#define TIMEOUT_INITIALIZER_FLAGS(_fn, _arg, _flags)                   \
-    __TIMEOUT_INITIALIZER((_fn), (_args), KCLOCK_NONE, (_flags))
+#define TIMEOUT_INITIALIZER_FLAGS(_fn, _arg, _kclock, _flags)          \
+    __TIMEOUT_INITIALIZER((_fn), (_args), (_kclock), (_flags))
 
 #define TIMEOUT_INITIALIZER(_f, _a)                                    \
     __TIMEOUT_INITIALIZER((_f), (_a), KCLOCK_NONE, 0)
 
 void timeout_set(struct timeout *, void (*)(void *), void *);
-void timeout_set_flags(struct timeout *, void (*)(void *), void *, int);
-void timeout_set_kclock(struct timeout *, void (*)(void *), void *, int, int);
+void timeout_set_flags(struct timeout *, void (*)(void *), void *, int, int);
 void timeout_set_proc(struct timeout *, void (*)(void *), void *);
 
 int timeout_add(struct timeout *, int);

Reply via email to