svn commit: r205576 - head/sys/mips/mips
Neel Natu
neel at FreeBSD.org
Wed Mar 24 04:52:15 UTC 2010
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)
More information about the svn-src-head
mailing list