From e69717d9e0cd107f461abff85f255be82d7bd69b Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Tue, 3 Sep 2019 18:07:28 +0000 Subject: Big wallclock/stopwatch refactor. It was long overdue. * --enable-clock and --enable-monotonic are gone * tain_sysclock() has been renamed tain_wallclock_read() * tain_wallclock_read() reads from CLOCK_REALTIME (or gettimeofday()) * tain_clockmon[_init]() have been renamed to tain_stopwatch_[read|init]() and now accept a monotonic clock name as an extra argument * tain_now() points to the system (wall) clock by default * tain_now_set_[stopwatch|wallclock]() can be used to switch Now to make a pass on all skarnet.org programs and add a tain_now_set_stopwatch() call everywhere needed... >.> --- doc/flags.html | 30 ------------ doc/libstddjb/tai.html | 124 ++++++++++++++++++++++++------------------------- doc/upgrade.html | 6 +++ 3 files changed, 68 insertions(+), 92 deletions(-) (limited to 'doc') diff --git a/doc/flags.html b/doc/flags.html index c901b1c..b74d344 100644 --- a/doc/flags.html +++ b/doc/flags.html @@ -175,36 +175,6 @@ and settimeofday() interfaces will be used. This is the default, and it's usually safe.

-

--enable-monotonic

- -

- Unless you have an accurate hardware system clock and you set it -on a linear time scale such as TAI-10 instead of UTC (see above), it is -generally a bad idea to trust the system clock for precise time interval -measurements. Single Unix recommends the use of clock_gettime() -with the CLOCK_MONOTONIC option to do such measurements: a stopwatch, not -a wall clock. However: -

- - - -

- If --enable-monotonic is set, then the absolute time given by the -tain_now() call will be computed with CLOCK_MONOTONIC. This -will ensure precise time arithmetic but may drift away from the system -clock. -

- -

- Otherwise, tain_now() will -return a time based on the system clock, and not use CLOCK_MONOTONIC. -This is the default. -

-

--disable-ipv6

diff --git a/doc/libstddjb/tai.html b/doc/libstddjb/tai.html index 8440c78..3826e80 100644 --- a/doc/libstddjb/tai.html +++ b/doc/libstddjb/tai.html @@ -130,12 +130,9 @@ it fails.

int sysclock_get (tain_t *a)
-Reads the current value of the system clock into *a, with -a 1-nanosecond (resp. 1-microsecond ) precision if skalibs has been -configured with (resp. without) the ---enable-clock option. -Returns 1 if it succeeds or 0 (and sets errno) if it -fails. Note that despite being a tain_t, *a +Reads the current value of the system clock (as in CLOCK_REALTIME) into *a. +Returns 1 if it succeeds or 0 (and sets errno) if it fails. +Note that despite being a tain_t, *a does not contain a TAI value - it only contains an internal, Y2038-safe representation of the value of the system clock, which should be either TAI-10 or UTC. You should not use @@ -150,103 +147,106 @@ function directly unless you know exactly what you are doing.

- int tain_sysclock (tain_t *a)
-Reads the current time into *a, as a TAI64N value, -with a 1-nanosecond (resp. 1-microsecond) precision if skalibs -has been configured with (resp. without) the ---enable-clock -option. Returns 1 if it succeeds or 0 (and sets errno) if it -fails. - Here a contains a valid TAI64N stamp, no matter what the + int tain_wallclock_read (tain_t *a)
+Reads the current time into *a, as a TAI64N value. +Returns 1 if it succeeds or 0 (and sets errno) if it fails. +Here a contains a valid TAI64N stamp, no matter what the system clock is set to: arithmetic operations can be performed on it.

int tain_setnow (tain_t const *a)
-Sets the current time to *a, with a 1-nanosecond -(resp. 1-microsecond) precision if skalibs has been configured -with (resp. without) the ---enable-clock -option. Returns 1 if it succeeds or 0 (and sets errno) if it -fails. a must contain a valid TAI64N stamp; proper +Sets the current time to *a. +Returns 1 if it succeeds or 0 (and sets errno) if it fails. +a must contain a valid TAI64N stamp; proper operations will be automatically run to convert that stamp into the right format for the system clock.

+

+ void tain_now_set_wallclock (void)
+Tells skalibs that future invocations of tain_now() +(see below) should use a wall clock, i.e. the system time +as returned by clock_gettime(CLOCK_REALTIME) or +gettimeofday(). This is the default: it is not necessary +to call this function before invoking tain_now() at the +start of a program. +

+

Stopwatch operations

- The following 3 operations are only defined if your system -provides the +The following two operations can only succeed if your system provides the clock_gettime() -primitive with the CLOCK_MONOTONIC option. +primitive with at least one of the CLOCK_MONOTONIC or CLOCK_BOOTTIME clocks. +Otherwise, they will fail with errno set to ENOSYS.

- int tain_clockmon_init (tain_t *offset)
-Initializes a stopwatch in *offset. The actual value of + int tain_stopwatch_init (clock_t cl, tain_t *offset)
+Initializes a stopwatch in *offset, using a clock named cl. +Typically, cl is something like CLOCK_MONOTONIC, when it is defined +by the system. The actual value of *offset is meaningless to the user; offset's only -use is to be given as a second parameter to tain_clockmon(). +use is to be given as a second parameter to tain_stopwatch_read(). The function returns 1 if it succeeds or 0 (and sets errno) if it fails.

- What tain_clockmon_init() does is synchronize the "stopwatch -clock" (CLOCK_MONOTONIC) to the system clock. Right after -tain_clockmon_init() has been called, the absolute times given -by tain_clockmon() and tain_sysclock() are similar. Then, -depending on the accuracy of the system clock, a drift may appear; calling -tain_clockmon_init() again resets that drift to zero. + What tain_stopwatch_init() does is synchronize the "stopwatch +clock" to the system clock. Right after tain_stopwatch_init() +has been called, the absolute times given +by tain_stopwatch_read() and tain_wallclock_read() are +the same. Then, depending on the accuracy of the system clock, a drift +may appear; calling tain_stopwatch_init() again resets that drift +to zero.

- int tain_clockmon (tain_t *a, tain_t const *offset)
+ int tain_stopwatch_read (tain_t *a, clock_t cl, tain_t const *offset)
Gives the absolute time, as a TAI64N value, in *a. This absolute time is computed as a linear increase (as measured with -CLOCK_MONOTONIC) since the last time tain_clockmon_init() -was called with parameter offset. tain_clockmon() +the cl clock, which should be a monotonic clock such as +CLOCK_MONOTONIC) since the last time tain_stopwatch_init() +was called with parameter offset. tain_stopwatch_read() guarantees precise time interval measurements; however, the time it -gives can slightly differ from the result of tain_sysclock(). +gives can slightly differ from the result of tain_wallclock_read(). The function returns 1 if it succeeds or 0 (and sets errno) if it fails.

-

All-purpose time reading

-

- int tain_init (void)
-If skalibs has been configured with the ---enable-monotonic option: this -function initializes a process-global stopwatch, that future -tain_now invocations will depend on. -Without the --enable-monotonic option: this -function does nothing. -The function returns 1 if it succeeds or 0 (and sets errno) if it fails. + void tain_now_set_stopwatch (void)
+Tells skalibs that future invocations of tain_now() +(see below) should use a stopwatch, i.e. the system time +as returned by clock_gettime(CLOCK_MONOTONIC) or similar, +if supported by the system. This is useful when it is more important +for a program to compute unchanging time intervals no matter what the +system clock does, than to display absolute time that is in sync with a +human view of time (which is the cause and reason of most system clock +jumps).
+If no monotonic clock is supported by the system, this function does +nothing (and tain_now() will keep using a wall clock).

+

All-purpose time reading

+

int tain_now (tain_t *a)
Writes the current time, as a TAI value, to *a. This is the -function you should use to read time by default. It returns 1 if it succeeds or +function you should use by default. It returns 1 if it succeeds or 0 (and sets errno) if it fails.

- If skalibs has been configured with the ---enable-monotonic option: -tain_now() is computed as a linear increase from the last time -tain_init() was called. (If tain_init() has never -been called before, the first invocation of tain_now() -automatically calls tain_init().) - Without the --enable-monotonic option: -tain_now() is the same as tain_sysclock(). -

- -

- If the above is unclear to you: just use tain_now() -everytime you need to read time, and you will always get a reasonable -approximation of the current time, in a format suited for arithmetic -computations. + tain_now() relies on the concept that there is One True Time Source +for the process, and that is where it reads time from. By default, the +One True Time Source is the system clock (a wall clock), and tain_now() +is actually an alias to tain_wallclock_read(). At the start of a +program, calling tain_now_set_stopwatch() will define a monotonic +clock (if supported by the system) as the One True Time Source, which will +make tain_now() resistant to system clock jumps, but will also +make it unsuitable for timestamping.

Converting to/from libc representations

diff --git a/doc/upgrade.html b/doc/upgrade.html index f56629e..76c1973 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -23,6 +23,12 @@
  • The configure script now emulates autotools-created configure scripts more closely. In particular, it's now possible to declare an out-of-path compiler in CC.
  • +
  • tain_* functions dealing with wall clocks and stopwatches +have been refactored. The --enable-clock and --enable-monotonic +configure switches have been removed. tain_now() can now be told at run +time to use a wall clock (default, or via tain_now_set_wallclock()) or a +stopwatch (via tain_now_set_stopwatch()), instead of it being fixed at +build time.
  • in 2.8.1.0

    -- cgit v1.2.3