Date: Mon, 22 Nov 2010 09:13:25 +0000 (UTC) From: Colin Percival <cperciva@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r215665 - head/sys/kern Message-ID: <201011220913.oAM9DP3J084457@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: cperciva Date: Mon Nov 22 09:13:25 2010 New Revision: 215665 URL: http://svn.freebsd.org/changeset/base/215665 Log: In tc_windup, handle the case where the previous call to tc_windup was more than 1s earlier. Prior to this commit, the computation of th_scale * delta (which produces a 64-bit value equal to the time since the last tc_windup call in units of 2^(-64) seconds) would overflow and any complete seconds would be lost. We fix this by repeatedly converting tc_frequency units of timecounter to one seconds; this is not exactly correct, since it loses the NTP adjustment, but if we find ourselves going more than 1s at a time between clock interrupts, losing a few seconds worth of NTP adjustments is the least of our problems... Modified: head/sys/kern/kern_tc.c Modified: head/sys/kern/kern_tc.c ============================================================================== --- head/sys/kern/kern_tc.c Mon Nov 22 09:06:59 2010 (r215664) +++ head/sys/kern/kern_tc.c Mon Nov 22 09:13:25 2010 (r215665) @@ -442,6 +442,16 @@ tc_windup(void) ncount = 0; th->th_offset_count += delta; th->th_offset_count &= th->th_counter->tc_counter_mask; + while (delta > th->th_counter->tc_frequency) { + /* Eat complete unadjusted seconds. */ + delta -= th->th_counter->tc_frequency; + th->th_offset.sec++; + } + if ((delta > th->th_counter->tc_frequency / 2) && + (th->th_scale * delta < (uint64_t)1 << 63)) { + /* The product th_scale * delta just barely overflows. */ + th->th_offset.sec++; + } bintime_addx(&th->th_offset, th->th_scale * delta); /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201011220913.oAM9DP3J084457>