[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] xen/sched: fix credit2 smt idle handling



Credit2's smt_idle_mask_set() and smt_idle_mask_clear() are used to
identify idle cores where vcpus can be moved to. A core is thought to
be idle when all siblings are known to have the idle vcpu running on
them.

Unfortunately the information of a vcpu running on a cpu is per
runqueue. So in case not all siblings are in the same runqueue a core
will never be regarded to be idle, as the sibling not in the runqueue
is never known to run the idle vcpu.

This problem can be solved by and-ing the core's sibling cpumask with
the runqueue's active mask before doing the idle test.

In order for not having to allocate another cpumask the interfaces of
smt_idle_mask_set() and smt_idle_mask_clear() are modified to not take
a mask as input, but the runqueue data pointer, as those functions are
always called with the same masks as parameters.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 xen/common/sched_credit2.c | 35 ++++++++++++++++-------------------
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
index 543dc3664d..ab50e7ad23 100644
--- a/xen/common/sched_credit2.c
+++ b/xen/common/sched_credit2.c
@@ -638,7 +638,8 @@ static inline bool has_cap(const struct csched2_vcpu *svc)
 
 /*
  * If all the siblings of cpu (including cpu itself) are both idle and
- * untickled, set all their bits in mask.
+ * untickled, set all their bits in mask. Note that only siblings handled
+ * by the rqd can be taken into account.
  *
  * NB that rqd->smt_idle is different than rqd->idle.  rqd->idle
  * records pcpus that at are merely idle (i.e., at the moment do not
@@ -653,25 +654,23 @@ static inline bool has_cap(const struct csched2_vcpu *svc)
  * changes.
  */
 static inline
-void smt_idle_mask_set(unsigned int cpu, const cpumask_t *idlers,
-                       cpumask_t *mask)
+void smt_idle_mask_set(unsigned int cpu, struct csched2_runqueue_data *rqd)
 {
-    const cpumask_t *cpu_siblings = per_cpu(cpu_sibling_mask, cpu);
-
-    if ( cpumask_subset(cpu_siblings, idlers) )
-        cpumask_or(mask, mask, cpu_siblings);
+    cpumask_and(cpumask_scratch, per_cpu(cpu_sibling_mask, cpu), &rqd->active);
+    if ( cpumask_subset(cpumask_scratch, &rqd->idle) &&
+         !cpumask_intersects(cpumask_scratch, &rqd->tickled) )
+        cpumask_or(&rqd->smt_idle, &rqd->smt_idle, cpumask_scratch);
 }
 
 /*
  * Clear the bits of all the siblings of cpu from mask (if necessary).
  */
 static inline
-void smt_idle_mask_clear(unsigned int cpu, cpumask_t *mask)
+void smt_idle_mask_clear(unsigned int cpu, struct csched2_runqueue_data *rqd)
 {
-    const cpumask_t *cpu_siblings = per_cpu(cpu_sibling_mask, cpu);
-
-    if ( cpumask_subset(cpu_siblings, mask) )
-        cpumask_andnot(mask, mask, per_cpu(cpu_sibling_mask, cpu));
+    cpumask_and(cpumask_scratch, per_cpu(cpu_sibling_mask, cpu), &rqd->active);
+    if ( cpumask_subset(cpumask_scratch, &rqd->smt_idle) )
+        cpumask_andnot(&rqd->smt_idle, &rqd->smt_idle, cpumask_scratch);
 }
 
 /*
@@ -1323,7 +1322,7 @@ static inline void
 tickle_cpu(unsigned int cpu, struct csched2_runqueue_data *rqd)
 {
     __cpumask_set_cpu(cpu, &rqd->tickled);
-    smt_idle_mask_clear(cpu, &rqd->smt_idle);
+    smt_idle_mask_clear(cpu, rqd);
     cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
 }
 
@@ -3468,8 +3467,7 @@ csched2_schedule(
     if ( tickled )
     {
         __cpumask_clear_cpu(cpu, &rqd->tickled);
-        cpumask_andnot(cpumask_scratch, &rqd->idle, &rqd->tickled);
-        smt_idle_mask_set(cpu, cpumask_scratch, &rqd->smt_idle);
+        smt_idle_mask_set(cpu, rqd);
     }
 
     if ( unlikely(tb_init_done) )
@@ -3553,7 +3551,7 @@ csched2_schedule(
         if ( cpumask_test_cpu(cpu, &rqd->idle) )
         {
             __cpumask_clear_cpu(cpu, &rqd->idle);
-            smt_idle_mask_clear(cpu, &rqd->smt_idle);
+            smt_idle_mask_clear(cpu, rqd);
         }
 
         /*
@@ -3599,14 +3597,13 @@ csched2_schedule(
             if ( cpumask_test_cpu(cpu, &rqd->idle) )
             {
                 __cpumask_clear_cpu(cpu, &rqd->idle);
-                smt_idle_mask_clear(cpu, &rqd->smt_idle);
+                smt_idle_mask_clear(cpu, rqd);
             }
         }
         else if ( !cpumask_test_cpu(cpu, &rqd->idle) )
         {
             __cpumask_set_cpu(cpu, &rqd->idle);
-            cpumask_andnot(cpumask_scratch, &rqd->idle, &rqd->tickled);
-            smt_idle_mask_set(cpu, cpumask_scratch, &rqd->smt_idle);
+            smt_idle_mask_set(cpu, rqd);
         }
         /* Make sure avgload gets updated periodically even
          * if there's no activity */
-- 
2.16.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.