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);
 }
 
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to