diff options
author | imp <imp@FreeBSD.org> | 2003-08-20 05:34:27 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2003-08-20 05:34:27 +0000 |
commit | ef7e40c45196cb84991cf5a82ee07e0f77267b0a (patch) | |
tree | e89469a9af7ac163717ba6afe66001593eec9346 /sys/kern/kern_tc.c | |
parent | dd5e41ad29251b7e8976041130e911e9635a6eef (diff) | |
download | FreeBSD-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.c | 10 |
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. */ |