xen: sched_credit, improve tickling of idle CPUs RFC: Re-organized ifs Signed-off-by: Dario Faggioli Signed-off-by: George Dunlap diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c --- a/xen/common/sched_credit.c +++ b/xen/common/sched_credit.c @@ -249,54 +249,53 @@ static inline void struct csched_vcpu * const cur = CSCHED_VCPU(per_cpu(schedule_data, cpu).curr); struct csched_private *prv = CSCHED_PRIV(per_cpu(scheduler, cpu)); - cpumask_t mask; + cpumask_t mask, idle_mask; + int idlers_empty; ASSERT(cur); cpumask_clear(&mask); - /* If strictly higher priority than current VCPU, signal the CPU */ - if ( new->pri > cur->pri ) + idlers_empty = cpumask_empty(prv->idlers); + /* + * If the pcpu is idle, or there are no idlers and the new + * vcpu is a higher priority than the old vcpu, run it here. + * + * If there are idle cpus, first try to find one suitable to run + * "new", so we can avoid preempting cur. If we cannot find a + * suitable idler on which to run "new", run it here, but try to + * find a suitable idler on which to run "cur" instead. + */ + if ( cur->pri == CSCHED_PRI_IDLE + || (idlers_empty && new->pri > cur->pri) ) { - if ( cur->pri == CSCHED_PRI_IDLE ) - SCHED_STAT_CRANK(tickle_local_idler); - else if ( cur->pri == CSCHED_PRI_TS_OVER ) - SCHED_STAT_CRANK(tickle_local_over); - else if ( cur->pri == CSCHED_PRI_TS_UNDER ) - SCHED_STAT_CRANK(tickle_local_under); - else - SCHED_STAT_CRANK(tickle_local_other); - cpumask_set_cpu(cpu, &mask); } + else if (!idlers_empty) + { + /* Check whether or not there are idlers that can run new */ + cpumask_and(&idle_mask, prv->idlers, new->vcpu->cpu_affinity); - /* - * If this CPU has at least two runnable VCPUs, we tickle any idlers to - * let them know there is runnable work in the system... - */ - if ( cur->pri > CSCHED_PRI_IDLE ) - { - if ( cpumask_empty(prv->idlers) ) + /* If there are no suitable idlers for new, and it's higher + * priority than cur, wake up the current cpu, but also + * look for idlers suitable for cur. */ + if (cpumask_empty(&idle_mask) && new->pri > cur->pri) { - SCHED_STAT_CRANK(tickle_idlers_none); + cpumask_set_cpu(cpu, &mask); + cpumask_and(&idle_mask, prv->idlers, cur->vcpu->cpu_affinity); } - else + + /* Which of the idlers shall we wake up? */ + if ( !cpumask_empty(&idle_mask) ) { - cpumask_t idle_mask; - - cpumask_and(&idle_mask, prv->idlers, new->vcpu->cpu_affinity); - if ( !cpumask_empty(&idle_mask) ) + SCHED_STAT_CRANK(tickle_idlers_some); + if ( opt_tickle_one_idle ) { - SCHED_STAT_CRANK(tickle_idlers_some); - if ( opt_tickle_one_idle ) - { - this_cpu(last_tickle_cpu) = - cpumask_cycle(this_cpu(last_tickle_cpu), &idle_mask); - cpumask_set_cpu(this_cpu(last_tickle_cpu), &mask); - } - else - cpumask_or(&mask, &mask, &idle_mask); + this_cpu(last_tickle_cpu) = + cpumask_cycle(this_cpu(last_tickle_cpu), &idle_mask); + cpumask_set_cpu(this_cpu(last_tickle_cpu), &mask); } - cpumask_and(&mask, &mask, new->vcpu->cpu_affinity); + else + cpumask_or(&mask, &mask, &idle_mask); } }