Merge branch 'formingo/3.2/tip/timers/core' of git://git.linaro.org/people/jstultz...
Ingo Molnar [Fri, 11 Nov 2011 07:10:42 +0000 (08:10 +0100)]
Conflicts:
kernel/time/timekeeping.c

kernel/time/timekeeping.c

index e65ff31..e9f60d3 100644 (file)
@@ -802,14 +802,44 @@ static void timekeeping_adjust(s64 offset)
        s64 error, interval = timekeeper.cycle_interval;
        int adj;
 
+       /*
+        * The point of this is to check if the error is greater then half
+        * an interval.
+        *
+        * First we shift it down from NTP_SHIFT to clocksource->shifted nsecs.
+        *
+        * Note we subtract one in the shift, so that error is really error*2.
+        * This "saves" dividing(shifting) intererval twice, but keeps the
+        * (error > interval) comparision as still measuring if error is
+        * larger then half an interval.
+        *
+        * Note: It does not "save" on aggrivation when reading the code.
+        */
        error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
        if (error > interval) {
+               /*
+                * We now divide error by 4(via shift), which checks if
+                * the error is greater then twice the interval.
+                * If it is greater, we need a bigadjust, if its smaller,
+                * we can adjust by 1.
+                */
                error >>= 2;
+               /*
+                * XXX - In update_wall_time, we round up to the next
+                * nanosecond, and store the amount rounded up into
+                * the error. This causes the likely below to be unlikely.
+                *
+                * The properfix is to avoid rounding up by using
+                * the high precision timekeeper.xtime_nsec instead of
+                * xtime.tv_nsec everywhere. Fixing this will take some
+                * time.
+                */
                if (likely(error <= interval))
                        adj = 1;
                else
                        adj = timekeeping_bigadjust(error, &interval, &offset);
        } else if (error < -interval) {
+               /* See comment above, this is just switched for the negative */
                error >>= 2;
                if (likely(error >= -interval)) {
                        adj = -1;
@@ -817,7 +847,7 @@ static void timekeeping_adjust(s64 offset)
                        offset = -offset;
                } else
                        adj = timekeeping_bigadjust(error, &interval, &offset);
-       } else
+       } else /* No adjustment needed */
                return;
 
        WARN_ONCE(timekeeper.clock->maxadj &&
@@ -827,6 +857,55 @@ static void timekeeping_adjust(s64 offset)
                        timekeeper.clock->name, (long)timekeeper.mult + adj,
                        (long)timekeeper.clock->mult +
                                timekeeper.clock->maxadj);
+       /*
+        * So the following can be confusing.
+        *
+        * To keep things simple, lets assume adj == 1 for now.
+        *
+        * When adj != 1, remember that the interval and offset values
+        * have been appropriately scaled so the math is the same.
+        *
+        * The basic idea here is that we're increasing the multiplier
+        * by one, this causes the xtime_interval to be incremented by
+        * one cycle_interval. This is because:
+        *      xtime_interval = cycle_interval * mult
+        * So if mult is being incremented by one:
+        *      xtime_interval = cycle_interval * (mult + 1)
+        * Its the same as:
+        *      xtime_interval = (cycle_interval * mult) + cycle_interval
+        * Which can be shortened to:
+        *      xtime_interval += cycle_interval
+        *
+        * So offset stores the non-accumulated cycles. Thus the current
+        * time (in shifted nanoseconds) is:
+        *      now = (offset * adj) + xtime_nsec
+        * Now, even though we're adjusting the clock frequency, we have
+        * to keep time consistent. In other words, we can't jump back
+        * in time, and we also want to avoid jumping forward in time.
+        *
+        * So given the same offset value, we need the time to be the same
+        * both before and after the freq adjustment.
+        *      now = (offset * adj_1) + xtime_nsec_1
+        *      now = (offset * adj_2) + xtime_nsec_2
+        * So:
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * adj_2) + xtime_nsec_2
+        * And we know:
+        *      adj_2 = adj_1 + 1
+        * So:
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * (adj_1+1)) + xtime_nsec_2
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * adj_1) + offset + xtime_nsec_2
+        * Canceling the sides:
+        *      xtime_nsec_1 = offset + xtime_nsec_2
+        * Which gives us:
+        *      xtime_nsec_2 = xtime_nsec_1 - offset
+        * Which simplfies to:
+        *      xtime_nsec -= offset
+        *
+        * XXX - TODO: Doc ntp_error calculation.
+        */
        timekeeper.mult += adj;
        timekeeper.xtime_interval += interval;
        timekeeper.xtime_nsec -= offset;