summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_tc.c
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2003-08-20 05:34:27 +0000
committerimp <imp@FreeBSD.org>2003-08-20 05:34:27 +0000
commitef7e40c45196cb84991cf5a82ee07e0f77267b0a (patch)
treee89469a9af7ac163717ba6afe66001593eec9346 /sys/kern/kern_tc.c
parentdd5e41ad29251b7e8976041130e911e9635a6eef (diff)
downloadFreeBSD-src-ef7e40c45196cb84991cf5a82ee07e0f77267b0a.zip
FreeBSD-src-ef7e40c45196cb84991cf5a82ee07e0f77267b0a.tar.gz
Fix an extreme edge case in leap second handling. We need to call
ntp_update_second twice when we have a large step in case that step goes across a scheduled leap second. The only way this could happen would be if we didn't call tc_windup over the end of day on the day of a leap second, which would only happen if timeouts were delayed for seconds. While it is an edge case, it is an important one to get right for my employer. Sponsored by: Timing Solutions Corporation
Diffstat (limited to 'sys/kern/kern_tc.c')
-rw-r--r--sys/kern/kern_tc.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index a3cef31..005936f 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -406,15 +406,17 @@ tc_windup(void)
* iterates once, but in extreme situations it might keep NTP sane
* if timeouts are not run for several seconds. At boot, the
* time step can be large when the TOD hardware has been read, so
- * on really large steps, we call ntp_update_second only once.
+ * on really large steps, we call ntp_update_second only twice.
+ * We need to call it twice in case we missed a leap second.
*/
- for (i = bt.sec - tho->th_microtime.tv_sec; i > 0; i--) {
+ i = bt.sec - tho->th_microtime.tv_sec;
+ if (i > LARGE_STEP)
+ i = 2;
+ for (; i > 0; i--) {
t = bt.sec;
ntp_update_second(&th->th_adjustment, &bt.sec);
if (bt.sec != t)
boottimebin.sec += bt.sec - t;
- if (i > LARGE_STEP)
- break;
}
/* Now is a good time to change timecounters. */
OpenPOWER on IntegriCloud