From: Roman Zippel <zippel@linux-m68k.org>
To: johnstul@us.ibm.com, linux-kernel@vger.kernel.org
Subject: [PATCH 4/10] NTP: precalculate time_adj from frequency
Date: Thu, 22 Dec 2005 00:22:30 +0100 (CET) [thread overview]
Message-ID: <Pine.LNX.4.61.0512220022010.30903@scrub.home> (raw)
This adds the frequency part to ntp_update_frequency(). It basically
calculates from tick_usec and time_freq how many nsec the time should be
advanced per second and converts it into the nsec and fraction per tick
(tick_nsec and time_adj).
Precalculating these values allows to be more precise and avoids the
crude time_freq to time_adj conversion in second_overflow().
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
---
kernel/time.c | 2 +-
kernel/timer.c | 36 ++++++++++++++++++++++++++++--------
2 files changed, 29 insertions(+), 9 deletions(-)
Index: linux-2.6-mm/kernel/time.c
===================================================================
--- linux-2.6-mm.orig/kernel/time.c 2005-12-21 12:12:00.000000000 +0100
+++ linux-2.6-mm/kernel/time.c 2005-12-21 12:12:04.000000000 +0100
@@ -337,7 +337,7 @@ int do_adjtimex(struct timex *txc)
if (txc->modes & ADJ_TICK)
tick_usec = txc->tick;
- if (txc->modes & ADJ_TICK)
+ if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
ntp_update_frequency();
} /* txc->modes */
leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
Index: linux-2.6-mm/kernel/timer.c
===================================================================
--- linux-2.6-mm.orig/kernel/timer.c 2005-12-21 12:12:00.000000000 +0100
+++ linux-2.6-mm/kernel/timer.c 2005-12-21 12:12:04.000000000 +0100
@@ -584,9 +584,8 @@ long time_precision = 1; /* clock preci
long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */
long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */
static long time_phase; /* phase offset (scaled us) */
-long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC;
- /* frequency offset (scaled ppm)*/
-static long time_adj; /* tick adjust (scaled 1 / HZ) */
+long time_freq; /* frequency offset (scaled ppm)*/
+static long time_adj, time_adj_curr; /* tick adjust (scaled 1 / HZ) */
long time_reftime; /* time at last adjustment (s) */
long time_adjust;
long time_next_adjust;
@@ -606,11 +605,33 @@ void ntp_clear(void)
ntp_update_frequency();
tick_nsec_curr = tick_nsec;
+ time_adj_curr = time_adj;
}
void ntp_update_frequency(void)
{
- tick_nsec = tick_usec * 1000;
+ long time;
+ s64 freq;
+
+ /*
+ * Split the frequency value into a nsec value and fraction, which are
+ * used to advance xtime at every tick. First calculate the nsec value
+ * for the next HZ ticks with the remainder in freq (scaled by
+ * (SHIFT_USEC - 3)).
+ */
+ freq = (s64)time_freq * 1000;
+ time = tick_usec * 1000 * USER_HZ;
+ time += freq >> SHIFT_USEC;
+
+ /*
+ * Now calculate the per tick values.
+ */
+ tick_nsec = time / HZ;
+ time = (time % HZ) << SHIFT_USEC;
+ time += freq & ((1 << SHIFT_USEC) - 1);
+ time <<= SHIFT_SCALE - SHIFT_USEC;
+ time_adj = time / HZ;
+
tick_nsec -= NSEC_PER_SEC / HZ - TICK_NSEC;
}
@@ -687,6 +708,7 @@ static void second_overflow(void)
}
tick_nsec_curr = tick_nsec;
+ time_adj_curr = time_adj;
/*
* 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
@@ -706,8 +728,6 @@ static void second_overflow(void)
* Compute the frequency estimate and additional phase adjustment due
* to frequency error for the next second.
*/
- ltemp = time_freq;
- adj += shift_right(ltemp,(SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE));
#if HZ == 100
/*
@@ -731,7 +751,7 @@ static void second_overflow(void)
adj += shift_right(adj, 6) + shift_right(adj, 7);
#endif
tick_nsec_curr += adj >> (SHIFT_SCALE - 10);
- time_adj = (adj << 10) & (FINENSEC - 1);
+ time_adj_curr += (adj << 10) & (FINENSEC - 1);
}
/* in the NTP reference this is called "hardclock()" */
@@ -759,7 +779,7 @@ static void update_wall_time_one_tick(vo
* Advance the phase, once it gets to one microsecond, then
* advance the tick more.
*/
- time_phase += time_adj;
+ time_phase += time_adj_curr;
if (time_phase >= FINENSEC) {
long ltemp = time_phase >> SHIFT_SCALE;
time_phase -= ltemp << SHIFT_SCALE;
next reply other threads:[~2005-12-21 23:22 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-12-21 23:22 Roman Zippel [this message]
2006-01-12 2:36 ` [PATCH 4/10] NTP: precalculate time_adj from frequency john stultz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.61.0512220022010.30903@scrub.home \
--to=zippel@linux-m68k.org \
--cc=johnstul@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).