Index: sys/kern/sched_ule.c =================================================================== --- sys/kern/sched_ule.c +++ sys/kern/sched_ule.c @@ -298,6 +298,9 @@ #define TDQ_CPU(x) (&tdq_cpu) #endif +static COUNTER_U64_DEFINE_EARLY(ithread_demotions); +static COUNTER_U64_DEFINE_EARLY(ithread_preemptions); + #define TDQ_LOCK_ASSERT(t, type) mtx_assert(TDQ_LOCKPTR((t)), (type)) #define TDQ_LOCK(t) mtx_lock_spin(TDQ_LOCKPTR((t))) #define TDQ_LOCK_FLAGS(t, f) mtx_lock_spin_flags(TDQ_LOCKPTR((t)), (f)) @@ -2336,6 +2339,15 @@ sched_interact_update(td); sched_pctcpu_update(ts, 0); } + + /* + * When resuming an idle thread, restore its base ithread + * priority. + */ + if (PRI_BASE(td->td_pri_class) == PRI_ITHD && + td->td_priority != td->td_base_ithread_pri) + sched_prio(td, td->td_base_ithread_pri); + /* * Reset the slice value since we slept and advanced the round-robin. */ @@ -2505,7 +2517,7 @@ /* * Handle a stathz tick. This is really only relevant for timeshare - * threads. + * and interrupt threads. */ void sched_clock(struct thread *td, int cnt) @@ -2557,6 +2569,34 @@ sched_priority(td); } + if (PRI_BASE(td->td_pri_class) == PRI_ITHD) { + /* + * If an ithread uses a full quantum, demote its + * priority and preempt it if there is another ithread + * of the same or higher priority to run. + * + * The check for preemption is performed before + * demoting the priority so that the current thread + * isn't preempted to run an ithread in the priority + * band the running thread is being demoted to while + * still ensuring that preemptions occur once the + * ithread is demoted to the lowest ithread priority. + */ + ts->ts_slice += cnt; + if (ts->ts_slice >= sched_slice) { + ts->ts_slice = 0; + if (td->td_priority >= tdq->tdq_lowpri) { + counter_u64_add(ithread_preemptions, 1); + td->td_owepreempt = 1; + } + if (td->td_base_pri + RQ_PPQ < PRI_MAX_ITHD) { + counter_u64_add(ithread_demotions, 1); + sched_prio(td, td->td_base_pri + RQ_PPQ); + } + } + return; + } + /* * Force a context switch if the current thread has used up a full * time slice (default is 100ms). @@ -3270,3 +3310,12 @@ static int ccpu = 0; SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, "Decay factor used for updating %CPU in 4BSD scheduler"); + +SYSCTL_NODE(_kern_sched, OID_AUTO, ithread, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, + "Interrupt thread stats"); +SYSCTL_COUNTER_U64(_kern_sched_ithread, OID_AUTO, demotions, + CTLFLAG_RD, &ithread_demotions, + "Count of interrupt thread priority demotions"); +SYSCTL_COUNTER_U64(_kern_sched_ithread, OID_AUTO, preemptions, + CTLFLAG_RD, &ithread_preemptions, + "Count of interrupt thread preemptions due to time-sharing");