Diff below moves resetpriority() out of updatepri() and resched_proc() out of resetpriority() in order to expose a double resched_proc() call in setrunnable().
This happens when a thread has slept for more than 1 second. Since p_usrpri is equal or bigger than p_priority, if the first call triggers a need_resched() then the second will also do so. I'd like to commit this diff which does not introduce any behavior change then remove the first resched_proc() in setrunnable(). ok? Index: kern/sched_bsd.c =================================================================== RCS file: /cvs/src/sys/kern/sched_bsd.c,v retrieving revision 1.43 diff -u -p -r1.43 sched_bsd.c --- kern/sched_bsd.c 9 Mar 2016 13:38:50 -0000 1.43 +++ kern/sched_bsd.c 24 Mar 2016 11:37:34 -0000 @@ -246,6 +246,7 @@ schedcpu(void *arg) newcpu = (u_int) decay_cpu(loadfac, p->p_estcpu); p->p_estcpu = newcpu; resetpriority(p); + resched_proc(p, p->p_usrpri); if (p->p_priority >= PUSER) { if (p->p_stat == SRUN && (p->p_priority / SCHED_PPQ) != @@ -284,7 +285,6 @@ updatepri(struct proc *p) newcpu = (int) decay_cpu(loadfac, newcpu); p->p_estcpu = newcpu; } - resetpriority(p); } /* @@ -454,7 +454,7 @@ mi_switch(void) #endif } -static __inline void +void resched_proc(struct proc *p, u_char pri) { struct cpu_info *ci; @@ -509,8 +509,11 @@ setrunnable(struct proc *p) p->p_stat = SRUN; p->p_cpu = sched_choosecpu(p); setrunqueue(p); - if (p->p_slptime > 1) + if (p->p_slptime > 1) { updatepri(p); + resetpriority(p); + resched_proc(p, p->p_usrpri); + } p->p_slptime = 0; resched_proc(p, p->p_priority); } @@ -531,7 +534,6 @@ resetpriority(struct proc *p) NICE_WEIGHT * (p->p_p->ps_nice - NZERO); newpriority = min(newpriority, MAXPRI); p->p_usrpri = newpriority; - resched_proc(p, p->p_usrpri); } /* @@ -556,6 +558,7 @@ schedclock(struct proc *p) SCHED_LOCK(s); p->p_estcpu = ESTCPULIM(p->p_estcpu + 1); resetpriority(p); + resched_proc(p, p->p_usrpri); if (p->p_priority >= PUSER) p->p_priority = p->p_usrpri; SCHED_UNLOCK(s); Index: kern/kern_resource.c =================================================================== RCS file: /cvs/src/sys/kern/kern_resource.c,v retrieving revision 1.55 diff -u -p -r1.55 kern_resource.c --- kern/kern_resource.c 5 Dec 2015 10:11:53 -0000 1.55 +++ kern/kern_resource.c 24 Mar 2016 11:30:32 -0000 @@ -194,8 +194,10 @@ donice(struct proc *curp, struct process return (EACCES); chgpr->ps_nice = n; SCHED_LOCK(s); - TAILQ_FOREACH(p, &chgpr->ps_threads, p_thr_link) - (void)resetpriority(p); + TAILQ_FOREACH(p, &chgpr->ps_threads, p_thr_link) { + resetpriority(p); + resched_proc(p, p->p_usrpri); + } SCHED_UNLOCK(s); return (0); } Index: sys/sched.h =================================================================== RCS file: /cvs/src/sys/sys/sched.h,v retrieving revision 1.41 diff -u -p -r1.41 sched.h --- sys/sched.h 17 Mar 2016 13:18:47 -0000 1.41 +++ sys/sched.h 24 Mar 2016 11:35:38 -0000 @@ -166,6 +166,7 @@ void sched_stop_secondary_cpus(void); #define cpu_is_idle(ci) ((ci)->ci_schedstate.spc_whichqs == 0) void sched_init_runqueues(void); +void resched_proc(struct proc *p, u_char); void setrunqueue(struct proc *); void remrunqueue(struct proc *);