aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timekeeping.c
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2012-07-13 01:21:56 -0400
committerThomas Gleixner <tglx@linutronix.de>2012-07-15 04:39:07 -0400
commit2a8c0883c3cfffcc148ea606e2a4e7453cd75e73 (patch)
tree9a340aaef6785881ec0eab74c32ad35841441889 /kernel/time/timekeeping.c
parentf2a5a0854efc62abe7f69e9947842cb135837f9a (diff)
time: Move xtime_nsec adjustment underflow handling timekeeping_adjust
When we make adjustments speeding up the clock, its possible for xtime_nsec to underflow. We already handle this properly, but we do so from update_wall_time() instead of the more logical timekeeping_adjust(), where the possible underflow actually occurs. Thus, move the correction logic to the timekeeping_adjust, which is the function that causes the issue. Making update_wall_time() more readable. Signed-off-by: John Stultz <johnstul@us.ibm.com> Reviewed-by: Ingo Molnar <mingo@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Richard Cochran <richardcochran@gmail.com> Cc: Prarit Bhargava <prarit@redhat.com> Link: http://lkml.kernel.org/r/1342156917-25092-8-git-send-email-john.stultz@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r--kernel/time/timekeeping.c42
1 files changed, 21 insertions, 21 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index e43289df28c2..aeeaab8cba6e 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -980,6 +980,27 @@ static void timekeeping_adjust(s64 offset)
980 timekeeper.xtime_nsec -= offset; 980 timekeeper.xtime_nsec -= offset;
981 timekeeper.ntp_error -= (interval - offset) << 981 timekeeper.ntp_error -= (interval - offset) <<
982 timekeeper.ntp_error_shift; 982 timekeeper.ntp_error_shift;
983
984 /*
985 * It may be possible that when we entered this function, xtime_nsec
986 * was very small. Further, if we're slightly speeding the clocksource
987 * in the code above, its possible the required corrective factor to
988 * xtime_nsec could cause it to underflow.
989 *
990 * Now, since we already accumulated the second, cannot simply roll
991 * the accumulated second back, since the NTP subsystem has been
992 * notified via second_overflow. So instead we push xtime_nsec forward
993 * by the amount we underflowed, and add that amount into the error.
994 *
995 * We'll correct this error next time through this function, when
996 * xtime_nsec is not as small.
997 */
998 if (unlikely((s64)timekeeper.xtime_nsec < 0)) {
999 s64 neg = -(s64)timekeeper.xtime_nsec;
1000 timekeeper.xtime_nsec = 0;
1001 timekeeper.ntp_error += neg << timekeeper.ntp_error_shift;
1002 }
1003
983} 1004}
984 1005
985 1006
@@ -1105,27 +1126,6 @@ static void update_wall_time(void)
1105 /* correct the clock when NTP error is too big */ 1126 /* correct the clock when NTP error is too big */
1106 timekeeping_adjust(offset); 1127 timekeeping_adjust(offset);
1107 1128
1108 /*
1109 * Since in the loop above, we accumulate any amount of time
1110 * in xtime_nsec over a second into xtime.tv_sec, its possible for
1111 * xtime_nsec to be fairly small after the loop. Further, if we're
1112 * slightly speeding the clocksource up in timekeeping_adjust(),
1113 * its possible the required corrective factor to xtime_nsec could
1114 * cause it to underflow.
1115 *
1116 * Now, we cannot simply roll the accumulated second back, since
1117 * the NTP subsystem has been notified via second_overflow. So
1118 * instead we push xtime_nsec forward by the amount we underflowed,
1119 * and add that amount into the error.
1120 *
1121 * We'll correct this error next time through this function, when
1122 * xtime_nsec is not as small.
1123 */
1124 if (unlikely((s64)timekeeper.xtime_nsec < 0)) {
1125 s64 neg = -(s64)timekeeper.xtime_nsec;
1126 timekeeper.xtime_nsec = 0;
1127 timekeeper.ntp_error += neg << timekeeper.ntp_error_shift;
1128 }
1129 1129
1130 /* 1130 /*
1131 * Store only full nanoseconds into xtime_nsec after rounding 1131 * Store only full nanoseconds into xtime_nsec after rounding