|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] xen: idle_loop: either deal with tasklets or go idle
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@xxxxxxxxxx> 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:
signature.asc _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |