[parisc-linux] [PATCH] timer_interrupt and gettimeoffset.

John David Anglin dave at hiauly1.hia.nrc.ca
Sun Sep 3 15:22:14 MDT 2006


> The signed math works correctly as an approximation (off by 2) and I
> do admit I find no fault in the math, but it is still confusing.

The signed math works as long as the latency in delivering the
interruption is not larger than about half a cycle.  Once
next_tick - now >= halftick, then we stop updating next_tick
until the counter wraps.  Probably, this could be extended
using unsigned math but you still have to handle the wrap.

The other issue is to ensure that the compare value for the
next interrupt is set before the counter passes this count.
We could have an interruption between the read and write
of cr16 even with interrupts disabled.  So, I think we should
minimize memory accesses.  The enclosed change eliminates
the memory accesses.

It may be we don't need the save/restore if interrupts are disabled.

Dave
-- 
J. David Anglin                                  dave.anglin at nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

Index: time.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/time.c,v
retrieving revision 1.16
diff -u -p -u -r1.16 time.c
--- time.c	24 Jun 2006 16:05:18 -0000	1.16
+++ time.c	3 Sep 2006 21:17:25 -0000
@@ -47,29 +47,36 @@ irqreturn_t timer_interrupt(int irq, voi
 {
 	long now;
 	long next_tick;
-	int nticks;
+	unsigned long nticks = 0;
+	long ct = clocktick;
+	long ht = halftick;
 	int cpu = smp_processor_id();
+	long flags;
 
 	profile_tick(CPU_PROFILING, regs);
 
-	now = mfctl(16);
-	/* initialize next_tick to time at last clocktick */
+	/* Initialize next_tick to time at last clocktick */
 	next_tick = cpu_data[cpu].it_value;
 
-	/* since time passes between the interrupt and the mfctl()
-	 * above, it is never true that last_tick + clocktick == now.  If we
-	 * never miss a clocktick, we could set next_tick = last_tick + clocktick
-	 * but maybe we'll miss ticks, hence the loop.
+	/* Since time passes between the interrupt and the mfctl(),
+	 * it is never true that last_tick + clocktick == now.
+	 * If we never miss a clocktick, we could set
+	 * next_tick = last_tick + clocktick, * but maybe we'll miss
+	 * ticks, hence the loop.
 	 *
 	 * Variables are *signed*.
 	 */
 
-	nticks = 0;
-	while((next_tick - now) < halftick) {
-		next_tick += clocktick;
+	/* Don't want to be interrupted while calculating
+	 * the time for the next tick.  */
+	local_irq_save(flags);
+	now = mfctl(16);
+	while((next_tick - now) < ht) {
+		next_tick += ct;
 		nticks++;
 	}
 	mtctl(next_tick, 16);
+	local_irq_restore(flags);
 	cpu_data[cpu].it_value = next_tick;
 
 	while (nticks--) {



More information about the parisc-linux mailing list