Messages in this thread | | | Date | Mon, 13 Dec 2021 06:39:43 -0700 | From | "Joel Daniels" <> | Subject | Re: Time keeping while suspended in the presence of persistent clock drift |
| |
Hi Thomas,
On Sat, 11 Dec 2021 14:36 +0100, Thomas Gleixner wrote: > Can you please verify that the problem persists with NTP enabled and > synchronized?
Yes, I just verified that the problem still exists while synchronized to NTP. Specifically, I connected the machine to the internet and launched chrony with:
$ sudo chronyd -d -L 0
using this /etc/chrony.conf:
server time.cloudflare.com iburst driftfile /var/lib/chrony/drift maxslewrate 500 rtcsync
I waited for chrony to stabilize:
$ chronyc tracking && echo && chronyc sources [...] Ref time (UTC) : Sun Dec 12 00:18:00 2021 System time : 0.000099906 seconds slow of NTP time [...] Frequency : 2.096 ppm fast Residual freq : -0.041 ppm Skew : 0.985 ppm [...]
MS Name/IP address Stratum Poll Reach LastRx Last sample ==================================================================== ^* time.cloudflare.com 3 6 377 26 -282us[ -424us]
$ sntp -K/dev/null time.cloudflare.com [...] 2021-12-11 17:18:57.339207 (+0700) +0.001868 +/- 0.012247 [...]
Then I suspended the computer. I woke it 37 hours later and my system clock was ahead by ~6 seconds:
$ sntp -K/dev/null time.cloudflare.com [...] 2021-12-13 06:24:28.425752 (+0700) -5.767757 +/- 3.856178 [...]
Chrony, of course, started to slew away the error and at the current rate my system time will be correct in about 3 hours:
$ chronyc tracking && echo && chronyc sources [...] Ref time (UTC) : Mon Dec 13 13:30:52 2021 System time : 5.597892284 seconds fast of NTP time [...] Frequency : 2.252 ppm fast Residual freq : +0.603 ppm Skew : 4.259 ppm [...]
MS Name/IP address Stratum Poll Reach LastRx Last sample ==================================================================== ^* time.cloudflare.com 3 6 377 15 +80us[ +197us]
This behavior is expected from my reading of the timekeeping_resume function (kernel/time/timekeeping.c). Specifically these lines:
read_persistent_clock64(&ts_new); ... cycle_now = tk_clock_read(&tk->tkr_mono); nsec = clocksource_stop_suspend_timing(clock, cycle_now); if (nsec > 0) { ts_delta = ns_to_timespec64(nsec); inject_sleeptime = true; } else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) { ts_delta = timespec64_sub(ts_new, timekeeping_suspend_time); inject_sleeptime = true; } if (inject_sleeptime) { suspend_timing_needed = false; __timekeeping_inject_sleeptime(tk, &ts_delta); }
The "if" branch does not apply as I have no clock sources flagged as CLOCK_SOURCE_SUSPEND_NONSTOP but the "else if" branch does apply.
The kernel seems to believe that the time spent sleeping is exactly the difference of two calls to read_persistent_clock64 with no option to adjust for persistent clock drift.
I would like to provide a way for user space to inform the kernel that the persistent clock drifts so it can make a corresponding adjustment when resuming from a long suspend period.
In my use case it would be enough for me to set this parameter on boot. In use cases with continuous network access, NTP daemons could be enhanced to periodically update this parameter with the daemon's best estimate of the persistent clock drift.
Regards, Joel
| |