All of lore.kernel.org
 help / color / mirror / Atom feed
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);
 	}
 }
 




  parent reply	other threads:[~2006-12-12 20:46 UTC|newest]

Thread overview: 86+ 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 18:37         ` 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.