From ef7e40c45196cb84991cf5a82ee07e0f77267b0a Mon Sep 17 00:00:00 2001 From: imp Date: Wed, 20 Aug 2003 05:34:27 +0000 Subject: [PATCH] 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 --- sys/kern/kern_tc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index a3cef31a8ec8..005936fbe7f4 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. */