diff options
author | mav <mav@FreeBSD.org> | 2010-11-08 15:25:12 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2010-11-08 15:25:12 +0000 |
commit | 1828dd747851cf18a1b9806d08be3dafcdd76bed (patch) | |
tree | 2b5d37f105076dfa03156f277a8f7f3bfcc2c343 /sys/kern | |
parent | 87d7052b67ecff2cee15b1938937396309c0da83 (diff) | |
download | FreeBSD-src-1828dd747851cf18a1b9806d08be3dafcdd76bed.zip FreeBSD-src-1828dd747851cf18a1b9806d08be3dafcdd76bed.tar.gz |
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.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_clocksource.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c index e654659..ded6d64 100644 --- a/sys/kern/kern_clocksource.c +++ b/sys/kern/kern_clocksource.c @@ -208,12 +208,13 @@ handleevents(struct bintime *now, int fake) 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 fake) } 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); } /* |