]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
hwclock: Improve set error in the face of jitter
authorEric Badger <ebadger@purestorage.com>
Wed, 3 Jan 2024 21:11:43 +0000 (13:11 -0800)
committerEric Badger <ebadger@purestorage.com>
Wed, 3 Jan 2024 21:41:53 +0000 (13:41 -0800)
set_hardware_clock_exact() spins in a loop, trying to exit when we are
`delay` seconds from an integer time on the system clock. However, there
might be jitter which causes an exit a little bit later than ideal.

The prior code could cause a relatively small error in loop exit time to
produce a relatively large error in the RTC.

For example, suppose upon exit from the loop, we have:

    sethwtime=1704239206
    refsystime=1704239206.000000
    nowsystime=1704239206.500372
    delay=0.5

In this case, the error is very small: 0.000372. However, we will
compute:

    newhwtime = 1704239206 + ceil(0.500371 - 0.5) = 1704239207

And in slightly less than `delay` seconds, the system clock will be
1704239207 while the RTC will be approximately 1704239208, about 1
second of error.

We are better off rounding in this case. The RTC will be behind the
system clock, but only very slightly:

    newhwtime = 1704239206 + round(0.500371 - 0.5) = 1704239206

I find passing `--ul-debug 0xffff` readily produces the original issue.

Signed-off-by: Eric Badger <ebadger@purestorage.com>
sys-utils/hwclock.c

index 35c73df1367249b3159a64aeaea37b56aca91835..7002708af21379048677d1df064f8c5b0ae0ec56 100644 (file)
@@ -624,7 +624,7 @@ set_hardware_clock_exact(const struct hwclock_control *ctl,
        }
 
        newhwtime = sethwtime
-                   + ceil(time_diff(nowsystime, refsystime)
+                   + round(time_diff(nowsystime, refsystime)
                            - delay /* don't count this */);
        if (ctl->verbose)
                printf(_("%"PRId64".%06"PRId64" is close enough to %"PRId64".%06"PRId64" (%.6f < %.6f)\n"