From: john stultz <johnstul@us.ibm.com>
To: Roman Zippel <zippel@linux-m68k.org>
Cc: Ingo Molnar <mingo@elte.hu>, Thomas Gleixner <tglx@linutronix.de>,
Andrew Morton <akpm@osdl.org>,
linux-kernel@vger.kernel.org
Subject: [RFC] HZ free ntp
Date: Tue, 12 Dec 2006 12:40:20 -0800 [thread overview]
Message-ID: <1165956021.20229.10.camel@localhost> (raw)
In-Reply-To: <Pine.LNX.4.64.0612061422190.1867@scrub.home>
On Wed, 2006-12-06 at 15:33 +0100, Roman Zippel wrote:
> On Wed, 6 Dec 2006, Ingo Molnar wrote:
> > i disagree with you and it's pretty low-impact anyway. There's still
> > quite many HZ/tick assumptions all around the time code (NTP being one
> > example), we'll deal with those via other patches.
>
> Why do you pick on the NTP code? That's actually one of the places where
> assumptions about HZ are largely gone. NTP state is updated incrementally
> and this won't change, but the update frequency can now be easily
> disconnected from HZ.
Hey Roman,
Here's my rough first attempt at doing so. I'd not call it easy, but
maybe you have some suggestions for a simpler way?
Basically INTERVAL_LENGTH_NSEC defines the NTP interval length that the
time code will use to accumulate with. In this patch I've pushed it out
to a full second, but it could be set via config (NSEC_PER_SEC/HZ for
regular systems, something larger for systems using dynticks).
Thoughts?
-john
diff --git a/include/linux/timex.h b/include/linux/timex.h
index db501dc..be13daf 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -286,9 +286,10 @@ #endif /* !CONFIG_TIME_INTERPOLATION */
#define TICK_LENGTH_SHIFT 32
-/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
-extern u64 current_tick_length(void);
+#define INTERVAL_LENGTH_NSEC (NSEC_PER_SEC)
+/* Returns how long NTP intervals are at present, in ns / 2^(SHIFT_SCALE-10).*/
+extern u64 ntp_interval_length(void);
extern void second_overflow(void);
extern void update_ntp_one_tick(void);
extern int do_adjtimex(struct timex *);
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index d0ba190..53979a9 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -127,12 +127,14 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);
*/
static void hrtimer_get_softirq_time(struct hrtimer_base *base)
{
+ struct timespec ts;
ktime_t xtim, tomono;
unsigned long seq;
do {
seq = read_seqbegin(&xtime_lock);
- xtim = timespec_to_ktime(xtime);
+ getnstimeofday(&ts);
+ xtim = timespec_to_ktime(ts);
tomono = timespec_to_ktime(wall_to_monotonic);
} while (read_seqretry(&xtime_lock, seq));
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 3afeaa3..812c56f 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -20,11 +20,12 @@ #include <asm/timex.h>
*/
unsigned long tick_usec = TICK_USEC; /* USER_HZ period (usec) */
unsigned long tick_nsec; /* ACTHZ period (nsec) */
-static u64 tick_length, tick_length_base;
+static u64 interval_length, interval_length_base;
#define MAX_TICKADJ 500 /* microsecs */
-#define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
- TICK_LENGTH_SHIFT) / HZ)
+#define MAX_TICKADJ_SCALED \
+ ((((u64)MAX_TICKADJ * NSEC_PER_USEC * INTERVAL_LENGTH_NSEC) \
+ / NSEC_PER_SEC)<< TICK_LENGTH_SHIFT)
/*
* phase-lock loop variables
@@ -44,15 +45,45 @@ #define CLOCK_TICK_OVERFLOW (LATCH * HZ
#define CLOCK_TICK_ADJUST (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \
(s64)CLOCK_TICK_RATE)
+/**
+ * ntp_update_frequency - Calculates base values used for NTP adjustments
+ *
+ */
static void ntp_update_frequency(void)
{
- tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT;
- tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
- tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
-
- do_div(tick_length_base, HZ);
-
- tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT;
+ u64 second_length;
+ s64 adj_length;
+ u64 tick_length;
+ int neg = 0;
+ /* calculate the length of one NTP adjusted second */
+ second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ);
+ second_length += (s64)CLOCK_TICK_ADJUST;
+ adj_length = (s64)time_freq;
+
+ /* calculate tick length @ HZ*/
+ tick_length = (second_length << TICK_LENGTH_SHIFT)
+ + (adj_length << (TICK_LENGTH_SHIFT - SHIFT_NSEC));
+ do_div(tick_length, HZ);
+ tick_nsec = tick_length >> TICK_LENGTH_SHIFT;
+
+
+ /* calculate interval_length_base */
+ /* XXX - this is broken up to avoid 64bit overlfows */
+ interval_length_base = second_length * INTERVAL_LENGTH_NSEC;
+ interval_length_base <<= 2;
+ do_div(interval_length_base, NSEC_PER_SEC);
+ interval_length_base <<= TICK_LENGTH_SHIFT-2;
+
+ if (adj_length < 0) {
+ neg = 1;
+ adj_length = -adj_length;
+ }
+ adj_length *= INTERVAL_LENGTH_NSEC;
+ do_div(adj_length, NSEC_PER_SEC);
+ adj_length <<= (TICK_LENGTH_SHIFT - SHIFT_NSEC);
+ if(neg)
+ adj_length = -adj_length;
+ interval_length_base += adj_length;
}
/**
@@ -69,7 +100,7 @@ void ntp_clear(void)
ntp_update_frequency();
- tick_length = tick_length_base;
+ interval_length = interval_length_base;
time_offset = 0;
}
@@ -148,37 +179,39 @@ void second_overflow(void)
* Compute the phase adjustment for the next second. The offset is
* reduced by a fixed factor times the time constant.
*/
- tick_length = tick_length_base;
+ interval_length = interval_length_base;
time_adj = shift_right(time_offset, SHIFT_PLL + time_constant);
time_offset -= time_adj;
- tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE);
+ interval_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE);
if (unlikely(time_adjust)) {
if (time_adjust > MAX_TICKADJ) {
time_adjust -= MAX_TICKADJ;
- tick_length += MAX_TICKADJ_SCALED;
+ interval_length += MAX_TICKADJ_SCALED;
} else if (time_adjust < -MAX_TICKADJ) {
time_adjust += MAX_TICKADJ;
- tick_length -= MAX_TICKADJ_SCALED;
+ interval_length -= MAX_TICKADJ_SCALED;
} else {
- tick_length += (s64)(time_adjust * NSEC_PER_USEC /
- HZ) << TICK_LENGTH_SHIFT;
+ u64 adjlen = ((s64)time_adjust * NSEC_PER_USEC
+ * INTERVAL_LENGTH_NSEC) << TICK_LENGTH_SHIFT;
+ do_div(adjlen, NSEC_PER_SEC);
+ interval_length += adjlen;
time_adjust = 0;
}
}
}
/*
- * Return how long ticks are at the moment, that is, how much time
- * update_wall_time_one_tick will add to xtime next time we call it
+ * Return how long NTP intervals are at the moment, that is, how
+ * much time update_wall_time will add to xtime next time we call it
* (assuming no calls to do_adjtimex in the meantime).
* The return value is in fixed-point nanoseconds shifted by the
* specified number of bits to the right of the binary point.
* This function has no side-effects.
*/
-u64 current_tick_length(void)
+u64 ntp_interval_length(void)
{
- return tick_length;
+ return interval_length;
}
diff --git a/kernel/timer.c b/kernel/timer.c
index 0256ab4..3a9f2b4 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -890,7 +890,7 @@ void __init timekeeping_init(void)
ntp_clear();
clock = clocksource_get_next();
- clocksource_calculate_interval(clock, tick_nsec);
+ clocksource_calculate_interval(clock, INTERVAL_LENGTH_NSEC);
clock->cycle_last = clocksource_read(clock);
write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -980,7 +980,7 @@ static __always_inline int clocksource_b
* Now calculate the error in (1 << look_ahead) ticks, but first
* remove the single look ahead already included in the error.
*/
- tick_error = current_tick_length() >>
+ tick_error = ntp_interval_length() >>
(TICK_LENGTH_SHIFT - clock->shift + 1);
tick_error -= clock->xtime_interval >> 1;
error = ((error - tick_error) >> look_ahead) + tick_error;
@@ -1077,7 +1077,7 @@ #endif
>> clock->shift);
/* accumulate error between NTP and clock interval */
- clock->error += current_tick_length();
+ clock->error += ntp_interval_length();
clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
}
@@ -1092,7 +1092,7 @@ #endif
if (change_clocksource()) {
clock->error = 0;
clock->xtime_nsec = 0;
- clocksource_calculate_interval(clock, tick_nsec);
+ clocksource_calculate_interval(clock, INTERVAL_LENGTH_NSEC);
}
}
next prev parent reply other threads:[~2006-12-12 20:46 UTC|newest]
Thread overview: 85+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-05 4:40 -mm merge plans for 2.6.20 Andrew Morton
2006-12-05 4:56 ` Jeff Garzik
2006-12-05 5:41 ` Andrew Morton
2006-12-05 7:04 ` Jens Axboe
2006-12-05 15:00 ` Mark Lord
2006-12-06 19:19 ` Conke Hu
2006-12-06 19:26 ` Randy Dunlap
2006-12-06 19:40 ` Jeff Garzik
2006-12-06 22:36 ` Andrew Morton
2006-12-05 5:14 ` Paul Mackerras
2006-12-05 5:42 ` Andrew Morton
2006-12-05 5:53 ` Nick Piggin
2006-12-05 5:49 ` Nick Piggin
2006-12-05 8:36 ` Gautham R Shenoy
2006-12-05 8:47 ` Peter Zijlstra
2006-12-05 11:06 ` ext2 future [was Re: -mm merge plans for 2.6.20] Pavel Machek
2006-12-05 13:23 ` -mm merge plans for 2.6.20 John W. Linville
2006-12-05 14:27 ` Roman Zippel
2006-12-06 3:46 ` Horst Schirmeier
2006-12-05 16:02 ` Dave Jones
2006-12-12 17:49 ` Dave Jones
2006-12-19 5:20 ` Nick Piggin
2006-12-19 6:44 ` Dave Jones
2006-12-19 7:02 ` Nick Piggin
2007-01-07 17:36 ` page_mapcount(page) went negative Dave Jones
2007-01-10 23:53 ` Nick Piggin
2006-12-05 17:35 ` -mm merge plans for 2.6.20 James Simmons
2006-12-05 18:01 ` Andrew Morton
2006-12-05 18:25 ` James Simmons
2006-12-05 18:37 ` [PATCH] backlight sysfs change to the fbdev drivers James Simmons
2006-12-05 19:43 ` -mm merge plans for 2.6.20 Andrew Morton
2006-12-05 19:59 ` James Simmons
2006-12-05 20:20 ` Andrew Morton
2006-12-05 21:34 ` James Simmons
2006-12-06 23:40 ` Andrew Morton
2006-12-07 14:31 ` James Simmons
2006-12-05 20:40 ` Miguel Ojeda
2006-12-06 14:42 ` James Simmons
2006-12-05 19:18 ` Josef Sipek
2006-12-05 19:21 ` [PATCH 1/2] fsstack: Make fsstack_copy_attr_all copy inode size Josef Sipek
2006-12-05 19:22 ` [PATCH 2/2] fsstack: Fix up ecryptfs's fsstack usage Josef Sipek
2006-12-05 22:28 ` Andrew Morton
2006-12-05 22:38 ` Josef Sipek
2006-12-05 22:49 ` Andrew Morton
2006-12-05 23:16 ` Josef Sipek
2006-12-05 21:00 ` -mm merge plans for 2.6.20 Ingo Molnar
2006-12-05 21:17 ` -mm merge plans for 2.6.20, scheduler bits Ingo Molnar
2006-12-05 20:59 ` Siddha, Suresh B
2006-12-05 21:47 ` Ingo Molnar
2006-12-05 21:29 ` Miguel Ojeda
2006-12-06 2:59 ` -mm merge plans for 2.6.20 Roman Zippel
2006-12-06 4:30 ` Andrew Morton
2006-12-06 8:32 ` Thomas Gleixner
2006-12-06 12:54 ` Roman Zippel
2006-12-06 13:11 ` Ingo Molnar
2006-12-06 14:33 ` Roman Zippel
2006-12-06 15:22 ` Ingo Molnar
2006-12-06 16:42 ` Roman Zippel
2006-12-06 16:58 ` Ingo Molnar
2006-12-06 16:59 ` Ingo Molnar
2006-12-12 20:40 ` john stultz [this message]
2006-12-13 9:51 ` [RFC] HZ free ntp Ingo Molnar
2006-12-13 18:48 ` john stultz
2006-12-13 13:47 ` Roman Zippel
2006-12-13 19:19 ` john stultz
2006-12-13 20:40 ` Roman Zippel
2006-12-20 1:32 ` john stultz
2006-12-20 1:54 ` john stultz
2006-12-21 4:26 ` Andrew Morton
2007-01-01 18:29 ` Roman Zippel
2007-01-02 19:46 ` john stultz
2007-01-02 20:50 ` john stultz
2007-01-06 16:56 ` Roman Zippel
2007-01-22 19:27 ` [patch] HZ-free NTP Ingo Molnar
2007-01-22 19:39 ` Ingo Molnar
2007-01-01 16:27 ` [RFC] HZ free ntp Roman Zippel
2007-01-02 19:42 ` john stultz
2007-01-06 16:46 ` Roman Zippel
2006-12-06 12:33 ` -mm merge plans for 2.6.20 Roman Zippel
2006-12-08 14:09 ` Stephen Smalley
2006-12-08 20:58 ` Andrew Morton
2006-12-10 15:07 ` Mimi Zohar
2006-12-09 9:30 ` Randy Dunlap
2006-12-09 9:44 ` Andrew Morton
2006-12-10 20:12 ` Randy Dunlap
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=1165956021.20229.10.camel@localhost \
--to=johnstul@us.ibm.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tglx@linutronix.de \
--cc=zippel@linux-m68k.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