All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 02/02 -rt] Include an interval timer for timeofday_periodic_hook
@ 2006-04-03 15:27 Steven Rostedt
  0 siblings, 0 replies; only message in thread
From: Steven Rostedt @ 2006-04-03 15:27 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Ingo Molnar, john stultz, LKML, rostedt

This patch uses an interval timer that can be updated in interrupt
context without too much latency, so that the timeofday_periodic_hook
doesn't wrap if is is prevented from executing because of a high
priority task.

-- Steve

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

Index: linux-2.6.16-rt12/kernel/time/timeofday.c
===================================================================
--- linux-2.6.16-rt12.orig/kernel/time/timeofday.c	2006-04-03 11:14:29.000000000 -0400
+++ linux-2.6.16-rt12/kernel/time/timeofday.c	2006-04-03 11:18:44.000000000 -0400
@@ -69,8 +69,19 @@ static struct timespec monotonic_time_of
  * cycle_last:
  *	Value of the clocksource at the last timeofday_periodic_hook()
  *	(adjusted only minorly to account for rounded off cycles)
+ * cycle_last_interval:
+ *	A value called at small intervals to prevent the cycle_last
+ *	from wrapping.  The difference is added to cycle_last_index
+ *	to keep a running value of the time from the last call to
+ *	timeofday_periodic_hook.
+ * cycle_last_index:
+ *	The time called by the cycle update between calls
+ *	to timeofday_periodic_hook.  The cycle update can be done in
+ *	interrupt context, where as the periodic hook is too heavy.
  */
 static cycle_t cycle_last;
+static cycle_t cycle_last_interval;
+static cycle_t cycle_last_index;
 
 /* [clocksource_interval variables]
  * ts_interval:
@@ -271,7 +282,8 @@ static inline s64 __get_nsec_offset(void
 	cycle_now = read_clocksource(clock);
 
 	/* calculate the delta since the last timeofday_periodic_hook: */
-	cycle_delta = (cycle_now - cycle_last) & clock->mask;
+	cycle_delta = (cycle_now - cycle_last_interval) & clock->mask;
+	cycle_delta += cycle_last_index;
 
 	/* convert to nanoseconds: */
 	ns_offset = cyc2ns(clock, ntp_adj, cycle_delta);
@@ -575,7 +587,8 @@ static int timeofday_resume_hook(struct 
 	 * time drift.
 	 */
 	suspend_end = read_persistent_clock();
-	cycle_last = read_clocksource(clock);
+	cycle_last = cycle_last_interval = read_clocksource(clock);
+	cycle_last_index = 0;
 
 	/* calculate suspend time and add it to system time: */
 	suspend_time = suspend_end - suspend_start;
@@ -619,6 +632,48 @@ static int timeofday_init_device(void)
 
 device_initcall(timeofday_init_device);
 
+static int timeofday_update_cycles(struct hrtimer *timer)
+{
+	unsigned long flags;
+
+	cycle_t cycle_now, cycle_delta;
+
+	write_seqlock_irqsave(&system_time_lock, flags);
+
+	/* read time source & calc time since last call: */
+	cycle_now = read_clocksource(clock);
+	cycle_delta = (cycle_now - cycle_last_interval) & clock->mask;
+	cycle_last_interval = cycle_now;
+
+	cycle_last_index += cycle_delta;
+
+	write_sequnlock_irqrestore(&system_time_lock, flags);
+
+	timer->expires.tv64 += TICK_NSEC;
+
+	return HRTIMER_RESTART;
+}
+
+static struct hrtimer cycle_update_timer;
+
+static void timeofday_init_update_cycles(void)
+{
+	ktime_t now;
+
+	hrtimer_init(&cycle_update_timer, CLOCK_MONOTONIC,
+		     HRTIMER_ABS);
+
+	cycle_update_timer.function = timeofday_update_cycles;
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+	cycle_update_timer.mode = HRTIMER_CB_IRQSAFE;
+#endif
+	now = ktime_get();
+	now.tv64 += TICK_NSEC;
+
+	hrtimer_start(&cycle_update_timer, now, HRTIMER_ABS);
+}
+
 /**
  * timeofday_periodic_hook - Does periodic update of timekeeping values.
  * @unused:	unused value
@@ -652,10 +707,12 @@ static void timeofday_periodic_hook(unsi
 	/* read time source & calc time since last call: */
 	cycle_now = read_clocksource(clock);
 	check_periodic_interval(cycle_now);
-	cycle_delta = (cycle_now - cycle_last) & clock->mask;
+	cycle_delta = (cycle_now - cycle_last_interval) & clock->mask;
+	cycle_delta += cycle_last_index;
+	cycle_last = cycle_last_interval = cycle_now;
+	cycle_last_index = 0;
 
 	delta_nsec = cyc2ns_fixed_rem(ts_interval, &cycle_delta, &remainder);
-	cycle_last = (cycle_now - cycle_delta)&clock->mask;
 
 	/* update system_time:  */
 	__increment_system_time(delta_nsec);
@@ -681,7 +738,8 @@ static void timeofday_periodic_hook(unsi
 	next = get_next_clocksource();
 	if (next != clock) {
 		/* immediately set new cycle_last: */
-		cycle_last = read_clocksource(next);
+		cycle_last = cycle_last_interval = read_clocksource(next);
+		cycle_last_index = 0;
 		/* update cycle_now to avoid problems in accumulation later: */
 		cycle_now = cycle_last;
 		/* swap clocksources: */
@@ -728,7 +786,8 @@ static void timeofday_periodic_hook(unsi
 		if (cycle_delta) {
 			delta_nsec = cyc2ns_rem(&old_clock, ntp_adj,
 						cycle_delta, &remainder);
-			cycle_last = cycle_now;
+			cycle_last = cycle_last_interval = cycle_now;
+			cycle_last_index = 0;
 			__increment_system_time(delta_nsec);
 			ntp_advance(delta_nsec);
 		}
@@ -810,7 +869,7 @@ void __init timeofday_init(void)
 	clock = get_next_clocksource();
 
 	/* initialize cycle_last offset base: */
-	cycle_last = read_clocksource(clock);
+	cycle_last = cycle_last_interval = read_clocksource(clock);
 
 	/* initialize wall_time_offset to now: */
 	/* XXX - this should be something like ns_to_ktime() */
@@ -828,6 +887,8 @@ void __init timeofday_init(void)
 
 	write_sequnlock_irqrestore(&system_time_lock, flags);
 
+	timeofday_init_update_cycles();
+
 	/* install timeofday_periodic_hook timer: */
 	init_timer(&timeofday_timer);
 	timeofday_timer.function = timeofday_periodic_hook;



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2006-04-03 15:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-03 15:27 [PATCH 02/02 -rt] Include an interval timer for timeofday_periodic_hook Steven Rostedt

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.