scheduler panic
John Baldwin
jhb at freebsd.org
Fri Dec 23 14:55:00 UTC 2011
On Friday, December 23, 2011 8:21:41 am Larry Rosenman wrote:
> I've been getting these in a VirtualBox VM. I'm not sure what to do.
>
> I CAN give VNC access to this VM in this state.
>
> panic: sched_priority: invalid priority 331: nice 0, ticks 56612596
> ftick 1213618 itick 1214628 tick pri 159
In the past this happened because the 'ticks' value was bananas. Priority
values should only be from 0 to 255, so 331 is definitely too large. The
priority is computed like so:
pri = SCHED_PRI_MIN;
if (td->td_sched->ts_ticks)
pri += SCHED_PRI_TICKS(td->td_sched);
pri += SCHED_PRI_NICE(td->td_proc->p_nice);
KASSERT(pri >= PRI_MIN_BATCH && pri <= PRI_MAX_BATCH,
("sched_priority: invalid priority %d: nice %d, "
"ticks %d ftick %d ltick %d tick pri %d",
pri, td->td_proc->p_nice, td->td_sched->ts_ticks,
td->td_sched->ts_ftick, td->td_sched->ts_ltick,
SCHED_PRI_TICKS(td->td_sched)));
Note that you have:
kern/sched_ule.c:
#define PRI_TIMESHARE_RANGE (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE + 1)
#define PRI_INTERACT_RANGE ((PRI_TIMESHARE_RANGE - SCHED_PRI_NRESV) / 2)
#define PRI_BATCH_RANGE (PRI_TIMESHARE_RANGE - PRI_INTERACT_RANGE)
#define PRI_MIN_INTERACT PRI_MIN_TIMESHARE
#define PRI_MAX_INTERACT (PRI_MIN_TIMESHARE + PRI_INTERACT_RANGE - 1)
#define PRI_MIN_BATCH (PRI_MIN_TIMESHARE + PRI_INTERACT_RANGE)
#define PRI_MAX_BATCH PRI_MAX_TIMESHARE
#define SCHED_PRI_NRESV (PRIO_MAX - PRIO_MIN)
sys/resource.h:
#define PRIO_MIN -20
#define PRIO_MAX 20
sys/priority.h:
#define PRI_MIN_TIMESHARE (120)
#define PRI_MAX_TIMESHARE (PRI_MIN_IDLE - 1)
#define PRI_MIN_IDLE (224)
So PRI_MAX_BATCH is 223.
PRI_MIN_BATCH is 120 + (((223 - 120 + 1) - (20 - -20)) / 2) which is 152.
So given SCHED_PRI_TICKS() of 159, you end up with 152 + 159 = 311, and
since your nice is 0, SCHED_PRI_NICE() ends up being 20, hence 331. It
seems the largets value SCHED_PRI_TICKS() should ever generate is
(PRI_BATCH_RANGE - SCHED_PRI_NRESV), though ULE doesn't quite compute it
that way (it might be off by one):
#define SCHED_PRI_NRESV (PRIO_MAX - PRIO_MIN)
#define SCHED_PRI_NHALF (SCHED_PRI_NRESV / 2)
#define SCHED_PRI_MIN (PRI_MIN_BATCH + SCHED_PRI_NHALF)
#define SCHED_PRI_MAX (PRI_MAX_BATCH - SCHED_PRI_NHALF)
#define SCHED_PRI_RANGE (SCHED_PRI_MAX - SCHED_PRI_MIN + 1)
However, it's not clear that SCHED_PRI_TICKS() will cap its value to
SCHED_PRI_RANGE:
#define SCHED_PRI_TICKS(ts) \
(SCHED_TICK_HZ((ts)) / \
(roundup(SCHED_TICK_TOTAL((ts)), SCHED_PRI_RANGE) / SCHED_PRI_RANGE))
The sloppiest fix might be to do this:
Index: sched_ule.c
===================================================================
--- sched_ule.c (revision 228777)
+++ sched_ule.c (working copy)
@@ -1434,7 +1434,8 @@ sched_priority(struct thread *td)
} else {
pri = SCHED_PRI_MIN;
if (td->td_sched->ts_ticks)
- pri += SCHED_PRI_TICKS(td->td_sched);
+ pri += min(SCHED_PRI_TICKS(td->td_sched),
+ SCHED_PRI_RANGE);
pri += SCHED_PRI_NICE(td->td_proc->p_nice);
KASSERT(pri >= PRI_MIN_BATCH && pri <= PRI_MAX_BATCH,
("sched_priority: invalid priority %d: nice %d, "
--
John Baldwin
More information about the freebsd-current
mailing list