]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
xen: sched_credit: when picking, make sure we get an idle one, if any
authorDario Faggioli <dario.faggioli@citrix.com>
Wed, 17 Apr 2013 10:57:30 +0000 (10:57 +0000)
committerIan Campbell <ian.campbell@citrix.com>
Wed, 17 Apr 2013 11:11:14 +0000 (12:11 +0100)
The pcpu picking algorithm treats two threads of a SMT core the same.
More specifically, if one is idle and the other one is busy, they both
will be assigned a weight of 1. Therefore, when picking begins, if the
first target pcpu is the busy thread (and if there are no other idle
pcpu than its sibling), that will never change.

This change fixes this by ensuring that, before entering the core of
the picking algorithm, the target pcpu is an idle one (if there is an
idle pcpu at all, of course).

Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
Acked-by: Juergen Gross <juergen.gross@ts.fujitsu.com>
Acked-by: George Dunlap <george.dunlap@eu.citrix.com>
Acked-by: Keir Fraser <keir@xen.org>
xen/common/sched_credit.c

index 9e9ef33a49979bbf75e8d95b6990e01481e72c2e..64e76c5bef4718c486590614f0fdbb52fa978ee4 100644 (file)
@@ -532,6 +532,21 @@ _csched_cpu_pick(const struct scheduler *ops, struct vcpu *vc, bool_t commit)
     if ( vc->processor == cpu && IS_RUNQ_IDLE(cpu) )
         cpumask_set_cpu(cpu, &idlers);
     cpumask_and(&cpus, &cpus, &idlers);
+
+    /*
+     * It is important that cpu points to an idle processor, if a suitable
+     * one exists (and we can use cpus to check and, possibly, choose a new
+     * CPU, as we just &&-ed it with idlers). In fact, if we are on SMT, and
+     * cpu points to a busy thread with an idle sibling, both the threads
+     * will be considered the same, from the "idleness" calculation point
+     * of view", preventing vcpu from being moved to the thread that is
+     * actually idle.
+     *
+     * Notice that cpumask_test_cpu() is quicker than cpumask_empty(), so
+     * we check for it first.
+     */
+    if ( !cpumask_test_cpu(cpu, &cpus) && !cpumask_empty(&cpus) )
+        cpu = cpumask_cycle(cpu, &cpus);
     cpumask_clear_cpu(cpu, &cpus);
 
     while ( !cpumask_empty(&cpus) )