[PATCH -rt] new update for tod periodic hook cycle times.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



OK, scratch the two patches that I sent earlier. The ones that added the
enqueue to the hrtimer_interrupt and the tod update.  This patch does
the tod update from update_process_times.  This way we don't need to
allow driver writers the ability to create large latencies, because they
can add their call backs into the hrtimer_interrupt.

-- Steve

Signed-off-by: Steven Rostedt <[email protected]>

Index: linux-2.6.16-rt12/kernel/time/timeofday.c
===================================================================
--- linux-2.6.16-rt12.orig/kernel/time/timeofday.c	2006-04-03 12:09:48.000000000 -0400
+++ linux-2.6.16-rt12/kernel/time/timeofday.c	2006-04-03 12:23:59.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;
@@ -618,6 +631,34 @@ static int timeofday_init_device(void)
 }
 
 device_initcall(timeofday_init_device);
+/**
+ * timeofday_update_cycles - Does periodic update of the cycle_last_interval
+ *	this prevents cycle_last from wrapping in the case that
+ *	 timeofday_periodic_hook is preempted too long to do a update in time.
+ *
+ * Does small interval updates to assist with timeofday_periodic_hook, since
+ * that function is too big to be called from hard interrupt context.
+ *
+ * Called via update_process_times (in interrupt context)
+ */
+
+void timeofday_update_cycles(void)
+{
+	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);
+}
 
 /**
  * timeofday_periodic_hook - Does periodic update of timekeeping values.
@@ -652,10 +693,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 +724,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 +772,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 +855,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() */
Index: linux-2.6.16-rt12/include/linux/timeofday.h
===================================================================
--- linux-2.6.16-rt12.orig/include/linux/timeofday.h	2006-03-31 20:24:38.000000000 -0500
+++ linux-2.6.16-rt12/include/linux/timeofday.h	2006-04-03 12:13:38.000000000 -0400
@@ -32,6 +32,7 @@ extern int do_settimeofday(struct timesp
 extern int timeofday_is_continuous(void);
 extern u32 timeofday_get_clockres(void);
 extern void timeofday_init(void);
+extern void timeofday_update_cycles(void);
 
 #ifndef CONFIG_IS_TICK_BASED
 #define arch_getoffset() (0)
Index: linux-2.6.16-rt12/kernel/timer.c
===================================================================
--- linux-2.6.16-rt12.orig/kernel/timer.c	2006-04-03 12:14:44.000000000 -0400
+++ linux-2.6.16-rt12/kernel/timer.c	2006-04-03 12:14:54.000000000 -0400
@@ -1015,6 +1015,7 @@ void update_process_times(int user_tick)
 	if (rcu_pending(cpu))
 		rcu_check_callbacks(cpu, user_tick);
 	scheduler_tick();
+	timeofday_update_cycles();
 #ifndef CONFIG_PREEMPT_RT
  	run_posix_cpu_timers(p);
 #endif


-
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]
  Powered by Linux