aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-02-16 18:30:23 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-17 11:24:29 -0500
commit726c14bf499e91e7ede4f1728830aba05c675061 (patch)
treec9dfbc8f8fe7facc58e07e5699b6d97c41bd2b8e /kernel
parentdd942ae331425812930cd01766178b7e28e65f2d (diff)
[PATCH] Provide an interface for getting the current tick length
This provides an interface for arch code to find out how many nanoseconds are going to be added on to xtime by the next call to do_timer. The value returned is a fixed-point number in 52.12 format in nanoseconds. The reason for this format is that it gives the full precision that the timekeeping code is using internally. The motivation for this is to fix a problem that has arisen on 32-bit powerpc in that the value returned by do_gettimeofday drifts apart from xtime if NTP is being used. PowerPC is now using a lockless do_gettimeofday based on reading the timebase register and performing some simple arithmetic. (This method of getting the time is also exported to userspace via the VDSO.) However, the factor and offset it uses were calculated based on the nominal tick length and weren't being adjusted when NTP varied the tick length. Note that 64-bit powerpc has had the lockless do_gettimeofday for a long time now. It also had an extremely hairy routine that got called from the 32-bit compat routine for adjtimex, which adjusted the factor and offset according to what it thought the timekeeping code was going to do. Not only was this only called if a 32-bit task did adjtimex (i.e. not if a 64-bit task did adjtimex), it was also duplicating computations from kernel/timer.c and it wasn't clear that it was (still) correct. The simple solution is to ask the timekeeping code how long the current jiffy will be on each timer interrupt, after calling do_timer. If this jiffy will be a different length from the last one, we then need to compute new values for the factor and offset used in the lockless do_gettimeofday. In this way we can keep xtime and do_gettimeofday in sync, even when NTP is varying the tick length. Note that when adjtimex varies the tick length, it almost always introduces the variation from the next tick on. The only case I could see where adjtimex would vary the length of the current tick is when an old-style adjtime adjustment is being cancelled. (It's not clear to me why the adjustment has to be cancelled immediately rather than from the next tick on.) Thus I don't see any real need for a hook in adjtimex; the rare case of an old-style adjustment being cancelled can be fixed up at the next tick. Signed-off-by: Paul Mackerras <paulus@samba.org> Acked-by: john stultz <johnstul@us.ibm.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/timer.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/kernel/timer.c b/kernel/timer.c
index b9dad3994676..fe3a9a9f8328 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -717,12 +717,16 @@ static void second_overflow(void)
717#endif 717#endif
718} 718}
719 719
720/* in the NTP reference this is called "hardclock()" */ 720/*
721static void update_wall_time_one_tick(void) 721 * Returns how many microseconds we need to add to xtime this tick
722 * in doing an adjustment requested with adjtime.
723 */
724static long adjtime_adjustment(void)
722{ 725{
723 long time_adjust_step, delta_nsec; 726 long time_adjust_step;
724 727
725 if ((time_adjust_step = time_adjust) != 0 ) { 728 time_adjust_step = time_adjust;
729 if (time_adjust_step) {
726 /* 730 /*
727 * We are doing an adjtime thing. Prepare time_adjust_step to 731 * We are doing an adjtime thing. Prepare time_adjust_step to
728 * be within bounds. Note that a positive time_adjust means we 732 * be within bounds. Note that a positive time_adjust means we
@@ -733,10 +737,19 @@ static void update_wall_time_one_tick(void)
733 */ 737 */
734 time_adjust_step = min(time_adjust_step, (long)tickadj); 738 time_adjust_step = min(time_adjust_step, (long)tickadj);
735 time_adjust_step = max(time_adjust_step, (long)-tickadj); 739 time_adjust_step = max(time_adjust_step, (long)-tickadj);
740 }
741 return time_adjust_step;
742}
736 743
744/* in the NTP reference this is called "hardclock()" */
745static void update_wall_time_one_tick(void)
746{
747 long time_adjust_step, delta_nsec;
748
749 time_adjust_step = adjtime_adjustment();
750 if (time_adjust_step)
737 /* Reduce by this step the amount of time left */ 751 /* Reduce by this step the amount of time left */
738 time_adjust -= time_adjust_step; 752 time_adjust -= time_adjust_step;
739 }
740 delta_nsec = tick_nsec + time_adjust_step * 1000; 753 delta_nsec = tick_nsec + time_adjust_step * 1000;
741 /* 754 /*
742 * Advance the phase, once it gets to one microsecond, then 755 * Advance the phase, once it gets to one microsecond, then
@@ -759,6 +772,22 @@ static void update_wall_time_one_tick(void)
759} 772}
760 773
761/* 774/*
775 * Return how long ticks are at the moment, that is, how much time
776 * update_wall_time_one_tick will add to xtime next time we call it
777 * (assuming no calls to do_adjtimex in the meantime).
778 * The return value is in fixed-point nanoseconds with SHIFT_SCALE-10
779 * bits to the right of the binary point.
780 * This function has no side-effects.
781 */
782u64 current_tick_length(void)
783{
784 long delta_nsec;
785
786 delta_nsec = tick_nsec + adjtime_adjustment() * 1000;
787 return ((u64) delta_nsec << (SHIFT_SCALE - 10)) + time_adj;
788}
789
790/*
762 * Using a loop looks inefficient, but "ticks" is 791 * Using a loop looks inefficient, but "ticks" is
763 * usually just one (we shouldn't be losing ticks, 792 * usually just one (we shouldn't be losing ticks,
764 * we're doing this this way mainly for interrupt 793 * we're doing this this way mainly for interrupt