xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Dario Faggioli <dario.faggioli@citrix.com>
To: Stefano Stabellini <sstabellini@kernel.org>
Cc: Jonathan Davies <Jonathan.Davies@citrix.com>,
	Julien Grall <julien.grall@arm.com>,
	George Dunlap <george.dunlap@citrix.com>,
	Marcus Granado <marcus.granado@citrix.com>,
	xen-devel@lists.xenproject.org
Subject: Re: [PATCH 1/3] xen: sched: introduce the 'null' semi-static scheduler
Date: Tue, 21 Mar 2017 09:26:23 +0100	[thread overview]
Message-ID: <1490084783.15340.10.camel@citrix.com> (raw)
In-Reply-To: <alpine.DEB.2.10.1703201524020.11533@sstabellini-ThinkPad-X260>


[-- Attachment #1.1: Type: text/plain, Size: 9015 bytes --]

On Mon, 2017-03-20 at 16:21 -0700, Stefano Stabellini wrote:
> On Fri, 17 Mar 2017, Dario Faggioli wrote:
> > 
> > --- /dev/null
> > +++ b/xen/common/sched_null.c

> > +/*
> > + * Virtual CPU
> > + */
> > +struct null_vcpu {
> > +    struct list_head waitq_elem;
> > +    struct null_dom *ndom;
> 
> This field is redundant, given that from struct vcpu you can get
> struct
> domain and from struct domain you can get struct null_dom. I would
> remove it.
> 
It's kind of a paradigm, followed by pretty much all schedulers. So
it's good to uniform to that, and it's often quite useful (or it may be
in future)... I'll have a look, though, at whether it is really
important to have it in this simple scheduler too, and do remove it if
it's not worth.

> > +    struct vcpu *vcpu;
> > +    int pcpu;          /* To what pCPU the vCPU is assigned (-1 if
> > none) */
> 
> Isn't this always the same as struct vcpu->processor?
> If it's only different when the vcpu is waiting in the waitq, then
> you
> can just remove this field and replace the pcpu == -1 test with
> list_empty(waitq_elem).
> 
I'll think about it. Right now, it's useful for ASSERTing and
consistency checking, which is something I want, at least in this
phase. It is also useful for reporting to what pcpu a vcpu is currently
assigned, for which thing you can't trust v->processor. That only
happens in `xl debug-key r' for now, but we may want to have less
tricky way of exporting such information in future.

Anyway, as I said, I'll ponder whether I can get rid of it.

> > +static void null_vcpu_remove(const struct scheduler *ops, struct
> > vcpu *v)
> > +{
> > +    struct null_private *prv = null_priv(ops);
> > +    struct null_vcpu *wvc, *nvc = null_vcpu(v);
> > +    unsigned int cpu;
> > +    spinlock_t *lock;
> > +
> > +    ASSERT(!is_idle_vcpu(v));
> > +
> > +    lock = vcpu_schedule_lock_irq(v);
> > +
> > +    cpu = v->processor;
> > +
> > +    /* If v is in waitqueue, just get it out of there and bail */
> > +    if ( unlikely(nvc->pcpu == -1) )
> > +    {
> > +        spin_lock(&prv->waitq_lock);
> > +
> > +        ASSERT(!list_empty(&null_vcpu(v)->waitq_elem));
> > +        list_del_init(&nvc->waitq_elem);
> > +
> > +        spin_unlock(&prv->waitq_lock);
> > +
> > +        goto out;
> > +    }
> > +
> > +    /*
> > +     * If v is assigned to a pCPU, let's see if there is someone
> > waiting.
> > +     * If yes, we assign it to cpu, in spite of v. If no, we just
> > set
> > +     * cpu free.
> > +     */
> > +
> > +    ASSERT(per_cpu(npc, cpu).vcpu == v);
> > +    ASSERT(!cpumask_test_cpu(cpu, &prv->cpus_free));
> > +
> > +    spin_lock(&prv->waitq_lock);
> > +    wvc = list_first_entry_or_null(&prv->waitq, struct null_vcpu,
> > waitq_elem);
> > +    if ( wvc )
> > +    {
> > +        vcpu_assign(prv, wvc->vcpu, cpu);
> 
> The vcpu_assign in null_vcpu_insert is protected by the pcpu runq
> lock,
> while this call is protected by the waitq_lock lock. Is that safe?
> 
vcpu assignment is always protected by the runqueue lock. Both in
null_vcpu_insert and() in here, we take it with:

 lock = vcpu_schedule_lock_irq(v);

at the beginning of the function (left in context, see above).

Taking the waitq_lock here serializes access to the waitqueue
(prv->waitqueue), i.e., the list_first_entry_or_null() call above, and
the list_del_init() call below.

> > +        list_del_init(&wvc->waitq_elem);
> > +        cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
> > +    }
> > +    else
> > +    {
> > +        vcpu_deassign(prv, v, cpu);
> > +    }
> > +    spin_unlock(&prv->waitq_lock);
> > +
> > + out:
> > +    vcpu_schedule_unlock_irq(lock, v);
> > +
> > +    SCHED_STAT_CRANK(vcpu_remove);
> > +}
> > +
> > +static void null_vcpu_wake(const struct scheduler *ops, struct
> > vcpu *v)
> > +{
> > +    ASSERT(!is_idle_vcpu(v));
> > +
> > +    if ( unlikely(curr_on_cpu(v->processor) == v) )
> > +    {
> > +        SCHED_STAT_CRANK(vcpu_wake_running);
> > +        return;
> > +    }
> > +
> > +    if ( null_vcpu(v)->pcpu == -1 )
> > +    {
> > +	/* Not exactly "on runq", but close enough for reusing the
> > counter */
> > +        SCHED_STAT_CRANK(vcpu_wake_onrunq);
> > +	return;
> 
> coding style
> 
Yeah... I need to double check the style of all the file (patch
series?). I mostly wrote this while travelling, with an editor set
differently from what I use when at home. I thought I had done that,
but I clearly missed a couple of sports. Sorry.

> > +static void null_vcpu_migrate(const struct scheduler *ops, struct
> > vcpu *v,
> > +                              unsigned int new_cpu)
> > +{
> > +    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 ( v->processor == new_cpu )
> > +        return;
> > +
> > +    /*
> > +     * v is either in the waitqueue, or assigned to a pCPU.
> > +     *
> > +     * In the former case, there is nothing to do.
> > +     *
> > +     * In the latter, the pCPU to which it was assigned would
> > become free,
> > +     * and we, therefore, should check whether there is anyone in
> > the
> > +     * waitqueue that can be assigned to it.
> > +     */
> > +    if ( likely(nvc->pcpu != -1) )
> > +    {
> > +        struct null_vcpu *wvc;
> > +
> > +        spin_lock(&prv->waitq_lock);
> > +        wvc = list_first_entry_or_null(&prv->waitq, struct
> > null_vcpu, waitq_elem);
> > +        if ( wvc && cpumask_test_cpu(cpu,
> > cpupool_domain_cpumask(v->domain)) )
> > +        {
> > +            vcpu_assign(prv, wvc->vcpu, cpu);
> > +            list_del_init(&wvc->waitq_elem);
> > +            cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
> > +        }
> > +        else
> > +        {
> > +            vcpu_deassign(prv, v, cpu);
> > +        }
> > +        spin_unlock(&prv->waitq_lock);
> 
> This looks very similar to null_vcpu_remove, maybe you want to
> refactor
> the code and call a single shared service function.
> 
Yes, maybe I can.

> > +	SCHED_STAT_CRANK(migrate_running);
> > +    }
> > +    else
> > +        SCHED_STAT_CRANK(migrate_on_runq);
> > +
> > +    SCHED_STAT_CRANK(migrated);
> > +
> > +    /*
> > +     * Let's now consider new_cpu, which is where v is being sent.
> > It can be
> > +     * either free, or have a vCPU already assigned to it.
> > +     *
> > +     * In the former case, we should assign v to it, and try to
> > get it to run.
> > +     *
> > +     * In latter, all we can do is to park v in the waitqueue.
> > +     */
> > +    if ( per_cpu(npc, new_cpu).vcpu == NULL )
> > +    {
> > +        /* We don't know whether v was in the waitqueue. If yes,
> > remove it */
> > +        spin_lock(&prv->waitq_lock);
> > +        list_del_init(&nvc->waitq_elem);
> > +        spin_unlock(&prv->waitq_lock);
> > +
> > +        vcpu_assign(prv, v, new_cpu);
> 
> This vcpu_assign call seems to be unprotected. Should it be within a
> spin_lock'ed area?
> 
Lock is taken by the caller. Check calls to SCHED_OP(...,migrate) in
xen/common/schedule.c.

That's by design, and it's like that for most functions (with the sole
exceptions of debug dump and insert/remove, IIRC), for all schedulers.

> > diff --git a/xen/common/schedule.c b/xen/common/schedule.c
> > index 223a120..b482037 100644
> > --- a/xen/common/schedule.c
> > +++ b/xen/common/schedule.c
> > @@ -1785,6 +1785,8 @@ int schedule_cpu_switch(unsigned int cpu,
> > struct cpupool *c)
> >  
> >   out:
> >      per_cpu(cpupool, cpu) = c;
> > +    /* Trigger a reschedule so the CPU can pick up some work ASAP.
> > */
> > +    cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ);
> >  
> >      return 0;
> >  }
> 
> Why? This change is not explained in the commit message.
> 
You're right. This may well go into it's own patch, actually. I'll see
how I like it better.

Thanks and Regards,
Dario
-- 
<<This happens because I choose it to happen!>> (Raistlin Majere)
-----------------------------------------------------------------
Dario Faggioli, Ph.D, http://about.me/dario.faggioli
Senior Software Engineer, Citrix Systems R&D Ltd., Cambridge (UK)

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2017-03-21  8:26 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-17 18:42 [PATCH 0/3] The 'null' Scheduler Dario Faggioli
2017-03-17 18:42 ` [PATCH 1/3] xen: sched: introduce the 'null' semi-static scheduler Dario Faggioli
2017-03-20 23:21   ` Stefano Stabellini
2017-03-21  8:26     ` Dario Faggioli [this message]
2017-03-27 10:31   ` George Dunlap
2017-03-27 10:48     ` George Dunlap
2017-04-06 14:43       ` Dario Faggioli
2017-04-06 15:07     ` Dario Faggioli
2017-03-17 18:43 ` [PATCH 2/3] xen: sched_null: support for hard affinity Dario Faggioli
2017-03-20 23:46   ` Stefano Stabellini
2017-03-21  8:47     ` Dario Faggioli
2017-03-17 18:43 ` [PATCH 3/3] tools: sched: add support for 'null' scheduler Dario Faggioli
2017-03-20 22:28   ` Stefano Stabellini
2017-03-21 17:09   ` Wei Liu
2017-03-27 10:50   ` George Dunlap
2017-04-06 10:49     ` Dario Faggioli
2017-04-06 13:59       ` George Dunlap
2017-04-06 15:18         ` Dario Faggioli
2017-04-07  9:42           ` Wei Liu
2017-04-07 10:05             ` Dario Faggioli
2017-04-07 10:13               ` Wei Liu
2017-03-20 22:23 ` [PATCH 0/3] The 'null' Scheduler Stefano Stabellini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1490084783.15340.10.camel@citrix.com \
    --to=dario.faggioli@citrix.com \
    --cc=Jonathan.Davies@citrix.com \
    --cc=george.dunlap@citrix.com \
    --cc=julien.grall@arm.com \
    --cc=marcus.granado@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).