From: Dario Faggioli <dario.faggioli@citrix.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
Julien Grall <julien.grall@arm.com>,
Stefano Stabellini <sstabellini@kernel.org>,
BorisOstrovsky <boris.ostrovsky@oracle.com>,
xen-devel@lists.xenproject.org
Subject: Re: [PATCH] xen: idle_loop: either deal with tasklets or go idle
Date: Fri, 16 Jun 2017 15:34:07 +0200 [thread overview]
Message-ID: <1497620047.30417.7.camel@citrix.com> (raw)
In-Reply-To: <5943E16D02000078001636DC@prv-mh.provo.novell.com>
[-- Attachment #1.1: Type: text/plain, Size: 5245 bytes --]
On Fri, 2017-06-16 at 05:47 -0600, Jan Beulich wrote:
> > On Fri, 2017-06-16 at 02:54 -0600, Jan Beulich wrote:
> > > > > > On 14.06.17 at 18:53, <dario.faggioli@citrix.com> wrote:
> > > > unsigned long *work_to_do = &per_cpu(tasklet_work_to_do,
> > > > cpu);
> > > > struct list_head *list = &per_cpu(tasklet_list, cpu);
> > > >
> > > > - /*
> > > > - * Work must be enqueued *and* scheduled. Otherwise there
> > > > is
> > > > no work to
> > > > - * do, and/or scheduler needs to run to update idle vcpu
> > > > priority.
> > > > - */
> > > > - if ( likely(*work_to_do !=
> > > > (TASKLET_enqueued|TASKLET_scheduled)) )
> > > > - return;
> > >
> > > Perhaps it also wouldn't hurt to convert this to an ASSERT() too.
> > >
> >
> > Nope, I can't. It's a best effort check, and *work_to_do (which is
> > per_cpu(tasklet_work_to_do,cpu)) can change, and the assert may
> > fail.
>
> How that? TASKLET_enqueued can only be cleared by do_tasklet()
> itself, and I don't think nesting invocations of the function can or
> should occur. TASKLET_scheduled is only being cleared when
> schedule() observes that bit set without TASKLET_enqueued also
> set. IOW there may be races in setting of the bits, but since we
> expect the caller to have done this check already, I think an
> ASSERT() would be quite fine here.
>
Ok, makes sense. I will add the ASSERT() (with something like what you
wrote here as a comment).
> > > Wouldn't cpu_is_haltable() then also better use this new
> > > function?
> > >
> >
> > Mmm... Perhaps. It's certainly less code chrun.
> >
> > ARM code would then contain two invocations of cpu_is_haltable()
> > (the
> > first happens with IRQ enabled, so a second one with IRQ disabled
> > is
> > necessary). But that is *exactly* the same thing we do on x86
> > (they're
> > just in different functions in that case).
> >
> > So, I reworked the patch according to these suggestions, and you
> > can
> > look at it below.
>
> I'm confused: You've added further uses of cpu_is_haltable()
> where the cheaper tasklet_work_to_do() would do.
>
Indeed. Sorry!
Fact is, I've read your comment backwards, i.e., as you were saying
something like "wouldn't cpu_is_haltable() better be used here, instead
of this new function?"
And it's not that your wording is ambiguous, it's me that, apparently,
can't read English! :-/
I'll rework the patch again...
> Of course that suggestion
> of mine was more than 1:1 replacement - the implied question was
> whether cpu_is_haltable() simply checking tasklet_work_to_do to
> be non-zero isn't too lax (and wouldn't better be
> !tasklet_work_to_do()).
>
Now, to try to answer the real question...
Let's assume that, on cpu x, we are about to check cpu_is_haltable(),
while, on cpu y, tasklet_schedule_on_cpu(x) is being called, and
manages to set _TASKLET_enqueued in *work_to_do.
I.e., in current code:
CPU x CPU y
| |
cpu_is_haltable(x) tasklet_schedule_on_cpu(x)
|!softirq_pending(x) == true tasklet_enqueue()
|cpu_online(x) == true test_and_set(TASKLET_enqueued,
| work_to_do)
|!work_to_do == FALSE
So we don't go to sleep, and we stay in the idle loop for the next
iteration. At which point, CPU y will have raised SCHEDULE_SOFTIRQ on
x, schedule (still on x) will set TASKLET_scheduled, and we'll call
do_tasklet().
Basically, right now, we risk spinning for the time that passes between
TASKLET_enqueued being set and SCHEDULE_SOFTIRQ being raised and
reaching cpu x. This should be a very short window, and, considering
how the TASKLET_* flags are handled, this looks the correct behavior to
me.
If we use !tasklet_work_to_do() in cpu_is_haltable():
CPU x CPU y
| |
cpu_is_haltable(x) tasklet_schedule_on_cpu(x)
|!softirq_pending(x) == true tasklet_enqueue()
|cpu_online(x) == true test_and_set(TASKLET_enqueued,
| work_to_do)
|!(work_to_do == TASKLET_enqueued+
TASKLET_scheduled) == TRUE
Which means we'd go to sleep... just for (most likely) be woken up very
very soon by SCHEDULE_SOFTIRQ being thrown at us (cpu x) by cpu y.
Am I overlooking anything? And is this (this time) what you were
asking?
Assuming answers are 'no' and 'yes', I think I'd leave
cpu_is_haltable() as it is (perhaps adding a brief comment on why it's
ok/better to check work_to_do directly, instead than calling
tasklet_work_to_do()).
Sorry again for the misunderstanding,
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
next prev parent reply other threads:[~2017-06-16 13:34 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-14 16:53 [PATCH] xen: idle_loop: either deal with tasklets or go idle Dario Faggioli
2017-06-14 16:53 ` Dario Faggioli
2017-06-16 8:54 ` Jan Beulich
2017-06-16 10:44 ` Dario Faggioli
2017-06-16 11:47 ` Jan Beulich
2017-06-16 13:34 ` Dario Faggioli [this message]
2017-06-16 14:09 ` Jan Beulich
2017-06-16 17:41 ` Stefano Stabellini
2017-06-16 20:06 ` Dario Faggioli
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=1497620047.30417.7.camel@citrix.com \
--to=dario.faggioli@citrix.com \
--cc=JBeulich@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=boris.ostrovsky@oracle.com \
--cc=julien.grall@arm.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.