This normalizes the calculated value time_adj in second_overflow() to be
always positive. The difference is added to tick_nsec and stored in
tick_nsec_curr. This simplifies the work needed in
update_wall_time_one_tick() as time_phase is always positive.
Signed-off-by: Roman Zippel <[email protected]>
---
include/linux/timex.h | 2 +-
kernel/timer.c | 24 ++++++++++++++----------
2 files changed, 15 insertions(+), 11 deletions(-)
Index: linux-2.6-mm/include/linux/timex.h
===================================================================
--- linux-2.6-mm.orig/include/linux/timex.h 2005-12-21 12:11:48.000000000 +0100
+++ linux-2.6-mm/include/linux/timex.h 2005-12-21 12:11:56.000000000 +0100
@@ -93,7 +93,7 @@
#define SHIFT_SCALE 22 /* phase scale (shift) */
#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* time offset scale (shift) */
#define SHIFT_USEC 16 /* frequency offset scale (shift) */
-#define FINENSEC (1L << (SHIFT_SCALE - 10)) /* ~1 ns in phase units */
+#define FINENSEC (1L << SHIFT_SCALE) /* ~1 ns in phase units */
#define MAXPHASE 512000L /* max phase error (us) */
#define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */
Index: linux-2.6-mm/kernel/timer.c
===================================================================
--- linux-2.6-mm.orig/kernel/timer.c 2005-12-21 12:11:48.000000000 +0100
+++ linux-2.6-mm/kernel/timer.c 2005-12-21 12:11:56.000000000 +0100
@@ -552,6 +552,7 @@ found:
*/
unsigned long tick_usec = TICK_USEC; /* USER_HZ period (usec) */
unsigned long tick_nsec = TICK_NSEC; /* ACTHZ period (nsec) */
+static unsigned long tick_nsec_curr = TICK_NSEC;
/*
* The current time
@@ -601,7 +602,7 @@ long time_next_adjust;
*/
static void second_overflow(void)
{
- long ltemp;
+ long ltemp, adj;
/* Bump the maxerror field */
time_maxerror += time_tolerance >> SHIFT_USEC;
@@ -662,6 +663,7 @@ static void second_overflow(void)
time_state = TIME_OK;
}
+ tick_nsec_curr = tick_nsec;
/*
* Compute the phase adjustment for the next second. In PLL mode, the
* offset is reduced by a fixed factor times the time constant. In FLL
@@ -675,36 +677,38 @@ static void second_overflow(void)
ltemp = min(ltemp, (MAXPHASE / MINSEC) << SHIFT_UPDATE);
ltemp = max(ltemp, -(MAXPHASE / MINSEC) << SHIFT_UPDATE);
time_offset -= ltemp;
- time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
+ adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
/*
* Compute the frequency estimate and additional phase adjustment due
* to frequency error for the next second.
*/
ltemp = time_freq;
- time_adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
+ adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
#if HZ == 100
/*
* Compensate for (HZ==100) != (1 << SHIFT_HZ). Add 25% and 3.125% to
* get 128.125; => only 0.125% error (p. 14)
*/
- time_adj += shift_right(time_adj, 2) + shift_right(time_adj, 5);
+ adj += shift_right(adj, 2) + shift_right(adj, 5);
#endif
#if HZ == 250
/*
* Compensate for (HZ==250) != (1 << SHIFT_HZ). Add 1.5625% and
* 0.78125% to get 255.85938; => only 0.05% error (p. 14)
*/
- time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7);
+ adj += shift_right(adj, 6) + shift_right(adj, 7);
#endif
#if HZ == 1000
/*
* Compensate for (HZ==1000) != (1 << SHIFT_HZ). Add 1.5625% and
* 0.78125% to get 1023.4375; => only 0.05% error (p. 14)
*/
- time_adj += shift_right(time_adj, 6) + shift_right(time_adj, 7);
+ adj += shift_right(adj, 6) + shift_right(adj, 7);
#endif
+ tick_nsec_curr += adj >> (SHIFT_SCALE - 10);
+ time_adj = (adj << 10) & (FINENSEC - 1);
}
/* in the NTP reference this is called "hardclock()" */
@@ -727,15 +731,15 @@ static void update_wall_time_one_tick(vo
/* Reduce by this step the amount of time left */
time_adjust -= time_adjust_step;
}
- delta_nsec = tick_nsec + time_adjust_step * 1000;
+ delta_nsec = tick_nsec_curr + time_adjust_step * 1000;
/*
* Advance the phase, once it gets to one microsecond, then
* advance the tick more.
*/
time_phase += time_adj;
- if ((time_phase >= FINENSEC) || (time_phase <= -FINENSEC)) {
- long ltemp = shift_right(time_phase, (SHIFT_SCALE - 10));
- time_phase -= ltemp << (SHIFT_SCALE - 10);
+ if (time_phase >= FINENSEC) {
+ long ltemp = time_phase >> SHIFT_SCALE;
+ time_phase -= ltemp << SHIFT_SCALE;
delta_nsec += ltemp;
}
xtime.tv_nsec += delta_nsec;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]