tc_windup() calls ntp_update_second() up to 200 times:

/*
 * A large step happens on boot.  This constant detects such steps.
 * It is relatively small so that ntp_update_second gets called enough
 * in the typical 'missed a couple of seconds' case, but doesn't loop
 * forever when the time step is large.
 */
#define LARGE_STEP      200

ntp_update_second() subtracts some amount of time from adjtimedelta and sets th->th_adjustment accordingly. However, if ntp_update_second is called more than once in a row, only the last value of th->th_adjustment is actually applied. Shouldn't the adjustments from all ntp_update_second calls be added instead? I don't know how often this is actually hit in practice, the normal case is that ntp_update_second is called only once.

diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
index 59b31dc..60ea119 100644
--- sys/kern/kern_tc.c
+++ sys/kern/kern_tc.c
@@ -425,8 +426,12 @@ tc_windup(void)
        i = bt.sec - tho->th_microtime.tv_sec;
        if (i > LARGE_STEP)
                i = 2;
-       for (; i > 0; i--)
-               ntp_update_second(&th->th_adjustment, &bt.sec);
+       th->th_adjustment = 0;
+       for (; i > 0; i--) {
+               uint64_t adj;
+               ntp_update_second(&adj, &bt.sec);
+               th->th_adjustment += adj;
+       }

        /* Update the UTC timestamps used by the get*() functions. */
        /* XXX shouldn't do this here.  Should force non-`get' versions. */

Reply via email to