svn commit: r214987 - head/sys/kern

Alexander Motin mav at FreeBSD.org
Mon Nov 8 15:25:12 UTC 2010


Author: mav
Date: Mon Nov  8 15:25:12 2010
New Revision: 214987
URL: http://svn.freebsd.org/changeset/base/214987

Log:
  On APs startup skip hard-/statclock events, which time passed before CPU
  was lauched. Few seconds event burst, accumulated during long startup,
  reported to cause panic in SCHED_ULE priority calculation logic.

Modified:
  head/sys/kern/kern_clocksource.c

Modified: head/sys/kern/kern_clocksource.c
==============================================================================
--- head/sys/kern/kern_clocksource.c	Mon Nov  8 15:22:20 2010	(r214986)
+++ head/sys/kern/kern_clocksource.c	Mon Nov  8 15:25:12 2010	(r214987)
@@ -208,12 +208,13 @@ handleevents(struct bintime *now, int fa
 		bintime_add(&state->nexthard, &hardperiod);
 		runs++;
 	}
-	if (runs) {
+	if (runs && fake < 2) {
 		hardclock_anycpu(runs, usermode);
 		done = 1;
 	}
 	while (bintime_cmp(now, &state->nextstat, >=)) {
-		statclock(usermode);
+		if (fake < 2)
+			statclock(usermode);
 		bintime_add(&state->nextstat, &statperiod);
 		done = 1;
 	}
@@ -227,6 +228,10 @@ handleevents(struct bintime *now, int fa
 	} else
 		state->nextprof = state->nextstat;
 	getnextcpuevent(&t, 0);
+	if (fake == 2) {
+		state->nextevent = t;
+		return (done);
+	}
 	ET_HW_LOCK(state);
 	if (!busy) {
 		state->idle = 0;
@@ -383,6 +388,11 @@ loadtimer(struct bintime *now, int start
 	uint64_t tmp;
 	int eq;
 
+	if (timer->et_flags & ET_FLAGS_PERCPU) {
+		state = DPCPU_PTR(timerstate);
+		next = &state->nexttick;
+	} else
+		next = &nexttick;
 	if (periodic) {
 		if (start) {
 			/*
@@ -391,20 +401,18 @@ loadtimer(struct bintime *now, int start
 			 */
 			tmp = ((uint64_t)now->sec << 36) + (now->frac >> 28);
 			tmp = (tmp % (timerperiod.frac >> 28)) << 28;
-			tmp = timerperiod.frac - tmp;
-			new = timerperiod;
-			bintime_addx(&new, tmp);
+			new.sec = 0;
+			new.frac = timerperiod.frac - tmp;
+			if (new.frac < tmp)	/* Left less then passed. */
+				bintime_add(&new, &timerperiod);
 			CTR5(KTR_SPARE2, "load p at %d:   now %d.%08x first in %d.%08x",
 			    curcpu, now->sec, (unsigned int)(now->frac >> 32),
 			    new.sec, (unsigned int)(new.frac >> 32));
+			*next = new;
+			bintime_add(next, now);
 			et_start(timer, &new, &timerperiod);
 		}
 	} else {
-		if (timer->et_flags & ET_FLAGS_PERCPU) {
-			state = DPCPU_PTR(timerstate);
-			next = &state->nexttick;
-		} else
-			next = &nexttick;
 		getnextevent(&new);
 		eq = bintime_cmp(&new, next, ==);
 		CTR5(KTR_SPARE2, "load at %d:    next %d.%08x%08x eq %d",
@@ -669,13 +677,19 @@ cpu_initclocks_ap(void)
 	struct bintime now;
 	struct pcpu_state *state;
 
-	if (timer->et_flags & ET_FLAGS_PERCPU) {
-		state = DPCPU_PTR(timerstate);
-		binuptime(&now);
-		ET_HW_LOCK(state);
+	state = DPCPU_PTR(timerstate);
+	binuptime(&now);
+	ET_HW_LOCK(state);
+	if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 && periodic) {
+		state->now = nexttick;
+		bintime_sub(&state->now, &timerperiod);
+	} else
+		state->now = now;
+	hardclock_sync(curcpu);
+	handleevents(&state->now, 2);
+	if (timer->et_flags & ET_FLAGS_PERCPU)
 		loadtimer(&now, 1);
-		ET_HW_UNLOCK(state);
-	}
+	ET_HW_UNLOCK(state);
 }
 
 /*


More information about the svn-src-head mailing list