Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Mar 2010 04:52:15 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r205576 - head/sys/mips/mips
Message-ID:  <201003240452.o2O4qF54092840@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Wed Mar 24 04:52:15 2010
New Revision: 205576
URL: http://svn.freebsd.org/changeset/base/205576

Log:
  Fix periodic "t_delta 16.01359db7eb5eb3c0 too long" messages on the console by
  accounting for the "lost time" between when the timer interrupt fired
  and when clock_intr() actually started executing.

Modified:
  head/sys/mips/mips/tick.c

Modified: head/sys/mips/mips/tick.c
==============================================================================
--- head/sys/mips/mips/tick.c	Wed Mar 24 04:37:19 2010	(r205575)
+++ head/sys/mips/mips/tick.c	Wed Mar 24 04:52:15 2010	(r205576)
@@ -63,17 +63,14 @@ static uint64_t cycles_per_hz, cycles_pe
 static u_int32_t counter_upper = 0;
 static u_int32_t counter_lower_last = 0;
 
-struct clk_ticks
-{
+struct clk_ticks {
 	u_long hard_ticks;
 	u_long stat_ticks;
 	u_long prof_ticks;
-	/*
-	 * pad for cache line alignment of pcpu info
-	 * cache-line-size - number of used bytes
-	 */
-	char   pad[32-(3*sizeof (u_long))];
-} static pcpu_ticks[MAXCPU];
+	uint32_t compare_ticks;
+} __aligned(CACHE_LINE_SIZE);
+
+static struct clk_ticks pcpu_ticks[MAXCPU];
 
 /*
  * Device methods
@@ -260,25 +257,47 @@ clock_intr(void *arg)
 {
 	struct clk_ticks *cpu_ticks;
 	struct trapframe *tf;
-	uint32_t ltick;
+	uint32_t count, compare, delta;
+
+	cpu_ticks = &pcpu_ticks[PCPU_GET(cpuid)];
+
 	/*
 	 * Set next clock edge.
 	 */
-	ltick = mips_rd_count();
-	mips_wr_compare(ltick + cycles_per_tick);
-	cpu_ticks = &pcpu_ticks[PCPU_GET(cpuid)];
+	count = mips_rd_count();
+	compare = cpu_ticks->compare_ticks;
+	cpu_ticks->compare_ticks = count + cycles_per_tick;
+	mips_wr_compare(cpu_ticks->compare_ticks);
 	critical_enter();
-	if (ltick < counter_lower_last) {
+	if (count < counter_lower_last) {
 		counter_upper++;
-		counter_lower_last = ltick;
+		counter_lower_last = count;
 	}
 	/*
 	 * Magic.  Setting up with an arg of NULL means we get passed tf.
 	 */
 	tf = (struct trapframe *)arg;
 
+	delta = cycles_per_tick;
+
+	/*
+	 * Account for the "lost time" between when the timer interrupt fired
+	 * and when 'clock_intr' actually started executing.
+	 */
+	delta += count - compare;
+
+	/*
+	 * If the COUNT and COMPARE registers are no longer in sync then make
+	 * up some reasonable value for the 'delta'.
+	 *
+	 * This could happen, for e.g., after we resume normal operations after
+	 * exiting the debugger.
+	 */
+	if (delta > cycles_per_hz)
+		delta = cycles_per_hz;
+
 	/* Fire hardclock at hz. */
-	cpu_ticks->hard_ticks += cycles_per_tick;
+	cpu_ticks->hard_ticks += delta;
 	if (cpu_ticks->hard_ticks >= cycles_per_hz) {
 	        cpu_ticks->hard_ticks -= cycles_per_hz;
 		if (PCPU_GET(cpuid) == 0)
@@ -288,14 +307,14 @@ clock_intr(void *arg)
 	}
 
 	/* Fire statclock at stathz. */
-	cpu_ticks->stat_ticks += cycles_per_tick;
+	cpu_ticks->stat_ticks += delta;
 	if (cpu_ticks->stat_ticks >= cycles_per_stathz) {
 		cpu_ticks->stat_ticks -= cycles_per_stathz;
 		statclock(USERMODE(tf->sr));
 	}
 
 	/* Fire profclock at profhz, but only when needed. */
-	cpu_ticks->prof_ticks += cycles_per_tick;
+	cpu_ticks->prof_ticks += delta;
 	if (cpu_ticks->prof_ticks >= cycles_per_profhz) {
 		cpu_ticks->prof_ticks -= cycles_per_profhz;
 		if (profprocs != 0)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003240452.o2O4qF54092840>