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);
 
        /*
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to