From patchwork Fri Jul 26 06:26:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Faggioli X-Patchwork-Id: 11060365 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 16D14746 for ; Fri, 26 Jul 2019 06:27:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 070F5205A9 for ; Fri, 26 Jul 2019 06:27:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EF86628A4F; Fri, 26 Jul 2019 06:27:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 85D6D205A9 for ; Fri, 26 Jul 2019 06:27:40 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hqtg5-0003BM-UK; Fri, 26 Jul 2019 06:26:05 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hqtg4-0003Az-Rk for xen-devel@lists.xenproject.org; Fri, 26 Jul 2019 06:26:04 +0000 X-Inumbo-ID: 3de65e79-af6e-11e9-8980-bc764e045a96 Received: from mx1.suse.de (unknown [195.135.220.15]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 3de65e79-af6e-11e9-8980-bc764e045a96; Fri, 26 Jul 2019 06:26:03 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id D003EAD31; Fri, 26 Jul 2019 06:26:02 +0000 (UTC) From: Dario Faggioli To: xen-devel@lists.xenproject.org Date: Fri, 26 Jul 2019 08:26:02 +0200 Message-ID: <156412236222.2385.236340632846050170.stgit@Palanthas> In-Reply-To: <156412188377.2385.12588508835559819141.stgit@Palanthas> References: <156412188377.2385.12588508835559819141.stgit@Palanthas> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v2 3/4] xen: sched: reassign vCPUs to pCPUs, when they come back online X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Roger Pau Monne , Stefano Stabellini , George Dunlap , Dario Faggioli Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: George Dunlap --- Cc: Stefano Stabellini Cc: Roger Pau Monne --- 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 10e96f21dd..1bbcaf92b9 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)) )