CVSROOT:        /cvs
Module name:    src
Changes by:     [email protected] 2020/10/15 14:03:44

Modified files:
        sys/kern       : kern_timeout.c 
        sys/sys        : timeout.h 

Log message:
timeout(9): basic support for kclock timeouts

A kclock timeout is a timeout that expires at an absolute time on one
of the kernel's clocks.  A timeout's absolute expiration time is kept
in a new member of the timeout struct, to_abstime.  The timeout's
kclock is set at initialization and is kept in another new member of
the timeout struct, to_kclock.

Kclock timeouts are desireable because they have nanosecond
resolution, regardless of the value of hz(9).  The timecounter
subsystem is also inherently NTP-sensitive, so timeouts scheduled
against the subsystem are NTP-sensitive.  These two qualities
guarantee that a kclock timeout will never expire early.

Currently there is support for one kclock, KCLOCK_UPTIME (the uptime
clock).  Support for KCLOCK_RUNTIME (the runtime clock) and KCLOCK_UTC
(the UTC clock) is planned for the future.

Support for these additional kclocks will allow us to implement some
of the POSIX interfaces OpenBSD is missing, e.g. clock_nanosleep() and
timer_create().  We could also use it to provide proper absolute
timeouts for e.g. pthread_mutex_timedlock(3).

Kclock timeouts are initialized with timeout_set_kclock().  They can
be scheduled with either timeout_in_nsec() (relative timeout) or
timeout_at_ts() (absolute timeout).  They are incompatible with
timeout_add(9), timeout_add_sec(9), timeout_add_msec(9),
timeout_add_usec(9), timeout_add_nsec(9), and timeout_add_tv(9).
They can be cancelled with timeout_del(9) or timeout_del_barrier(9).

Documentation for the new interfaces is a work in progress.

For now, tick-based timeouts remain supported alongside kclock
timeouts.  They will remain supported until we are certain we don't
need them anymore.  It is possible we will never remove them.  I would
rather not keep them around forever, but I cannot predict what
difficulties we will encounter while converting tick-based timeouts to
kclock timeouts.  There are a *lot* of timeouts in the kernel.

Kclock timeouts are more costly than tick-based timeouts:

- Calling timeout_in_nsec() incurs a call to nanouptime(9).  Reading
the hardware timecounter is too expensive in some contexts, so care
must be taken when converting existing timeouts.

We may add a flag in the future to cause timeout_in_nsec() to use
getnanouptime(9) instead of nanouptime(9), which is much cheaper.
This may be appropriate for certain classes of timeouts.  tcp/ip
session timeouts come to mind.

- Kclock timeout expirations are kept in a timespec.  Timespec
arithmetic has more overhead than 32-bit tick arithmetic, so
processing kclock timeouts during softclock() is more expensive.
On my machine the overhead for processing a tick-based timeout is
~125 cycles.  The overhead for a kclock timeout is ~500 cycles.

The overhead difference on 32-bit platforms is unknown.  If it
proves too large we may need to use a 64-bit value to store the
expiration time.  More measurement is needed.

Priority targets for conversion are setitimer(2), *sleep_nsec(9), and
the kevent(2) EVFILT_TIMER timers.  Others will follow.

With input from mpi@, visa@, kettenis@, dlg@, guenther@, claudio@,
deraadt@, probably many others.  Older version tested by visa@.
Problems found in older version by bluhm@.  Current version tested by
Yuichiro Naito.

"wait until after unlock" deraadt@, ok kettenis@

Reply via email to