Index: kern/kern_timeout.c =================================================================== --- kern/kern_timeout.c +++ kern/kern_timeout.c @@ -163,6 +163,7 @@ sbintime_t cc_lastscan; void *cc_cookie; u_int cc_bucket; + u_int cc_inited; char cc_ktr_event_name[20]; }; @@ -266,6 +267,7 @@ * XXX: Clip callout to result of previous function of maxusers * maximum 384. This is still huge, but acceptable. */ + memset(cc_cpu, 0, sizeof(cc_cpu)); ncallout = imin(16 + maxproc + maxfiles, 18508); TUNABLE_INT_FETCH("kern.ncallout", &ncallout); @@ -307,6 +309,7 @@ mtx_init(&cc->cc_lock, "callout", NULL, MTX_SPIN | MTX_RECURSE); SLIST_INIT(&cc->cc_callfree); + cc->cc_inited = 1; cc->cc_callwheel = malloc(sizeof(struct callout_list) * callwheelsize, M_CALLOUT, M_WAITOK); for (i = 0; i < callwheelsize; i++) @@ -346,6 +349,7 @@ * is blocked in order to avoid deadlocks as the new thread * may be willing to acquire the callout cpu lock. */ + c->l_cpu = c->c_cpu; c->c_cpu = CPUBLOCK; spinlock_enter(); CC_UNLOCK(cc); @@ -352,6 +356,7 @@ new_cc = CC_CPU(new_cpu); CC_LOCK(new_cc); spinlock_exit(); + c->l_cpu = new_cpu; c->c_cpu = new_cpu; return (new_cc); } @@ -945,6 +950,17 @@ int cancelled, direct; cancelled = 0; + if ((cpu >= CPUBLOCK) || (cpu < 0)) { + /* + * Most likely CPUBLOCK was set in c->c_cpu + * and this was passed in via macro, fix it + * to be the l_cpu we were on. + */ + cpu = c->l_cpu; + } else if (cc_cpu[cpu].cc_inited == 0) { + /* Invalid CPU spec */ + cpu = c->l_cpu; + } if (flags & C_ABSOLUTE) { to_sbt = sbt; } else { @@ -1350,7 +1366,7 @@ c->c_lock = &Giant.lock_object; c->c_flags = 0; } - c->c_cpu = timeout_cpu; + c->l_cpu = c->c_cpu = timeout_cpu; } void @@ -1366,7 +1382,7 @@ (LC_SPINLOCK | LC_SLEEPABLE)), ("%s: invalid lock class", __func__)); c->c_flags = flags & (CALLOUT_RETURNUNLOCKED | CALLOUT_SHAREDLOCK); - c->c_cpu = timeout_cpu; + c->l_cpu = c->c_cpu = timeout_cpu; } #ifdef APM_FIXUP_CALLTODO Index: sys/_callout.h =================================================================== --- sys/_callout.h +++ sys/_callout.h @@ -59,6 +59,7 @@ struct lock_object *c_lock; /* lock to handle */ int c_flags; /* state of this entry */ volatile int c_cpu; /* CPU we're scheduled on */ + volatile int l_cpu; /* CPU we last were on */ }; #endif