aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2011-10-27 21:12:42 -0400
committerIngo Molnar <mingo@elte.hu>2011-10-28 02:57:38 -0400
commitc2bc11113c50449f23c40b724fe410fc2380a8e9 (patch)
treef5a6a5f9c199d6b3ed7a973dfb7556ad2af2bf5a /kernel
parente35f95b36e43f67a6f806172555a152c11ea0a78 (diff)
time: Improve documentation of timekeeeping_adjust()
After getting a number of questions in private emails about the math around admittedly very complex timekeeping_adjust() and timekeeping_big_adjust(), I figure the code needs some better comments. Hopefully the explanations are clear enough and don't muddy the water any worse. Still needs documentation for ntp_error, but I couldn't recall exactly the full explanation behind the code that's there (although I do recall once working it out when Roman first proposed it). Given a bit more time I can probably work it out, but I don't want to hold back this documentation until then. Signed-off-by: John Stultz <john.stultz@linaro.org> Cc: Chen Jie <chenj@lemote.com> Cc: Steven Rostedt <rostedt@goodmis.org> Link: http://lkml.kernel.org/r/1319764362-32367-1-git-send-email-john.stultz@linaro.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/timekeeping.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 2b021b0e8507..025e136f3881 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -802,14 +802,44 @@ static void timekeeping_adjust(s64 offset)
802 s64 error, interval = timekeeper.cycle_interval; 802 s64 error, interval = timekeeper.cycle_interval;
803 int adj; 803 int adj;
804 804
805 /*
806 * The point of this is to check if the error is greater then half
807 * an interval.
808 *
809 * First we shift it down from NTP_SHIFT to clocksource->shifted nsecs.
810 *
811 * Note we subtract one in the shift, so that error is really error*2.
812 * This "saves" dividing(shifting) intererval twice, but keeps the
813 * (error > interval) comparision as still measuring if error is
814 * larger then half an interval.
815 *
816 * Note: It does not "save" on aggrivation when reading the code.
817 */
805 error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1); 818 error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
806 if (error > interval) { 819 if (error > interval) {
820 /*
821 * We now divide error by 4(via shift), which checks if
822 * the error is greater then twice the interval.
823 * If it is greater, we need a bigadjust, if its smaller,
824 * we can adjust by 1.
825 */
807 error >>= 2; 826 error >>= 2;
827 /*
828 * XXX - In update_wall_time, we round up to the next
829 * nanosecond, and store the amount rounded up into
830 * the error. This causes the likely below to be unlikely.
831 *
832 * The properfix is to avoid rounding up by using
833 * the high precision timekeeper.xtime_nsec instead of
834 * xtime.tv_nsec everywhere. Fixing this will take some
835 * time.
836 */
808 if (likely(error <= interval)) 837 if (likely(error <= interval))
809 adj = 1; 838 adj = 1;
810 else 839 else
811 adj = timekeeping_bigadjust(error, &interval, &offset); 840 adj = timekeeping_bigadjust(error, &interval, &offset);
812 } else if (error < -interval) { 841 } else if (error < -interval) {
842 /* See comment above, this is just switched for the negative */
813 error >>= 2; 843 error >>= 2;
814 if (likely(error >= -interval)) { 844 if (likely(error >= -interval)) {
815 adj = -1; 845 adj = -1;
@@ -817,9 +847,58 @@ static void timekeeping_adjust(s64 offset)
817 offset = -offset; 847 offset = -offset;
818 } else 848 } else
819 adj = timekeeping_bigadjust(error, &interval, &offset); 849 adj = timekeeping_bigadjust(error, &interval, &offset);
820 } else 850 } else /* No adjustment needed */
821 return; 851 return;
822 852
853 /*
854 * So the following can be confusing.
855 *
856 * To keep things simple, lets assume adj == 1 for now.
857 *
858 * When adj != 1, remember that the interval and offset values
859 * have been appropriately scaled so the math is the same.
860 *
861 * The basic idea here is that we're increasing the multiplier
862 * by one, this causes the xtime_interval to be incremented by
863 * one cycle_interval. This is because:
864 * xtime_interval = cycle_interval * mult
865 * So if mult is being incremented by one:
866 * xtime_interval = cycle_interval * (mult + 1)
867 * Its the same as:
868 * xtime_interval = (cycle_interval * mult) + cycle_interval
869 * Which can be shortened to:
870 * xtime_interval += cycle_interval
871 *
872 * So offset stores the non-accumulated cycles. Thus the current
873 * time (in shifted nanoseconds) is:
874 * now = (offset * adj) + xtime_nsec
875 * Now, even though we're adjusting the clock frequency, we have
876 * to keep time consistent. In other words, we can't jump back
877 * in time, and we also want to avoid jumping forward in time.
878 *
879 * So given the same offset value, we need the time to be the same
880 * both before and after the freq adjustment.
881 * now = (offset * adj_1) + xtime_nsec_1
882 * now = (offset * adj_2) + xtime_nsec_2
883 * So:
884 * (offset * adj_1) + xtime_nsec_1 =
885 * (offset * adj_2) + xtime_nsec_2
886 * And we know:
887 * adj_2 = adj_1 + 1
888 * So:
889 * (offset * adj_1) + xtime_nsec_1 =
890 * (offset * (adj_1+1)) + xtime_nsec_2
891 * (offset * adj_1) + xtime_nsec_1 =
892 * (offset * adj_1) + offset + xtime_nsec_2
893 * Canceling the sides:
894 * xtime_nsec_1 = offset + xtime_nsec_2
895 * Which gives us:
896 * xtime_nsec_2 = xtime_nsec_1 - offset
897 * Which simplfies to:
898 * xtime_nsec -= offset
899 *
900 * XXX - TODO: Doc ntp_error calculation.
901 */
823 timekeeper.mult += adj; 902 timekeeper.mult += adj;
824 timekeeper.xtime_interval += interval; 903 timekeeper.xtime_interval += interval;
825 timekeeper.xtime_nsec -= offset; 904 timekeeper.xtime_nsec -= offset;