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

[Xen-changelog] [xen staging] xen: sched: reassign vCPUs to pCPUs, when they come back online



commit faa2c904fbc05cb740d6d9369cd6c32258736b0e
Author:     Dario Faggioli <dfaggioli@xxxxxxxx>
AuthorDate: Mon Aug 5 11:50:56 2019 +0100
Commit:     George Dunlap <george.dunlap@xxxxxxxxxx>
CommitDate: Mon Aug 5 11:50:56 2019 +0100

    xen: sched: reassign vCPUs to pCPUs, when they come back online
    
    When a vcpu that was offline, comes back online, we do want it to either
    be assigned to a pCPU, or go into the wait list.
    
    Detecting that a vcpu is coming back online is a bit tricky. Basically,
    if the vcpu is waking up, and is neither assigned to a pCPU, nor in the
    wait list, it must be coming back from offline.
    
    When this happens, we put it in the waitqueue, and we "tickle" an idle
    pCPU (if any), to go pick it up.
    
    Looking at the patch, it seems that the vcpu wakeup code is getting
    complex, and hence that it could potentially introduce latencies.
    However, all this new logic is triggered only by the case of a vcpu
    coming online, so, basically, the overhead during normal operations is
    just an additional 'if()'.
    
    Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxx>
    Reviewed-by: George Dunlap <george.dunlap@xxxxxxxxxx>
    Message-Id: <156412236222.2385.236340632846050170.stgit@Palanthas>
---
 xen/common/sched_null.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/xen/common/sched_null.c b/xen/common/sched_null.c
index dd11db6aa4..2edac234a5 100644
--- a/xen/common/sched_null.c
+++ b/xen/common/sched_null.c
@@ -542,15 +542,19 @@ static void null_vcpu_remove(const struct scheduler *ops, 
struct vcpu *v)
 
 static void null_vcpu_wake(const struct scheduler *ops, struct vcpu *v)
 {
+    struct null_private *prv = null_priv(ops);
+    struct null_vcpu *nvc = null_vcpu(v);
+    unsigned int cpu = v->processor;
+
     ASSERT(!is_idle_vcpu(v));
 
-    if ( unlikely(curr_on_cpu(v->processor) == v) )
+    if ( unlikely(curr_on_cpu(cpu) == v) )
     {
         SCHED_STAT_CRANK(vcpu_wake_running);
         return;
     }
 
-    if ( unlikely(!list_empty(&null_vcpu(v)->waitq_elem)) )
+    if ( unlikely(!list_empty(&nvc->waitq_elem)) )
     {
         /* Not exactly "on runq", but close enough for reusing the counter */
         SCHED_STAT_CRANK(vcpu_wake_onrunq);
@@ -562,6 +566,48 @@ static void null_vcpu_wake(const struct scheduler *ops, 
struct vcpu *v)
     else
         SCHED_STAT_CRANK(vcpu_wake_not_runnable);
 
+    /*
+     * If a vcpu is neither on a pCPU nor in the waitqueue, it means it was
+     * offline, and that it is now coming back being online.
+     */
+    if ( unlikely(per_cpu(npc, cpu).vcpu != v && list_empty(&nvc->waitq_elem)) 
)
+    {
+        spin_lock(&prv->waitq_lock);
+        list_add_tail(&nvc->waitq_elem, &prv->waitq);
+        spin_unlock(&prv->waitq_lock);
+
+        cpumask_and(cpumask_scratch_cpu(cpu), v->cpu_hard_affinity,
+                    cpupool_domain_cpumask(v->domain));
+
+        if ( !cpumask_intersects(&prv->cpus_free, cpumask_scratch_cpu(cpu)) )
+        {
+            dprintk(XENLOG_G_WARNING, "WARNING: d%dv%d not assigned to any 
CPU!\n",
+                    v->domain->domain_id, v->vcpu_id);
+            return;
+        }
+
+        /*
+         * Now we would want to assign the vcpu to cpu, but we can't, because
+         * we don't have the lock. So, let's do the following:
+         * - try to remove cpu from the list of free cpus, to avoid races with
+         *   other onlining, inserting or migrating operations;
+         * - tickle the cpu, which will pickup work from the waitqueue, and
+         *   assign it to itself;
+         * - if we're racing already, and if there still are free cpus, try
+         *   again.
+         */
+        while ( cpumask_intersects(&prv->cpus_free, cpumask_scratch_cpu(cpu)) )
+        {
+            unsigned int new_cpu = pick_cpu(prv, v);
+
+            if ( test_and_clear_bit(new_cpu, &prv->cpus_free) )
+            {
+                cpu_raise_softirq(new_cpu, SCHEDULE_SOFTIRQ);
+                return;
+            }
+        }
+    }
+
     /* Note that we get here only for vCPUs assigned to a pCPU */
     cpu_raise_softirq(v->processor, SCHEDULE_SOFTIRQ);
 }
@@ -808,6 +854,9 @@ static struct task_slice null_schedule(const struct 
scheduler *ops,
         }
  unlock:
         spin_unlock(&prv->waitq_lock);
+
+        if ( ret.task == NULL && !cpumask_test_cpu(cpu, &prv->cpus_free) )
+            cpumask_set_cpu(cpu, &prv->cpus_free);
     }
 
     if ( unlikely(ret.task == NULL || !vcpu_runnable(ret.task)) )
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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