Re: scheduler panic

From: John Baldwin <jhb_at_freebsd.org>
Date: Fri, 23 Dec 2011 09:54:57 -0500
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)
_at__at_ -1434,7 +1434,8 _at__at_ 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
Received on Fri Dec 23 2011 - 13:55:00 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:22 UTC