On Thu, Jun 24, 2021 at 05:39:56PM -0500, Scott Cheloha wrote:
> 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.
> 

it did! you must have just missed it somehow.

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

everything else looked ok.
jmc

> 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