From: tglx@linutronix.de (Thomas Gleixner)
To: linux-arm-kernel@lists.infradead.org
Subject: too many timer retries happen when do local timer swtich with broadcast timer
Date: Thu, 21 Feb 2013 10:36:51 +0100 (CET) [thread overview]
Message-ID: <alpine.LFD.2.02.1302211015270.22263@ionos> (raw)
In-Reply-To: <CAB4PhKfxPcyQfpM2Ra1OxsyYhS5fnkjtPy=uYgxFHim1rOdoug@mail.gmail.com>
On Thu, 21 Feb 2013, Jason Liu wrote:
> 2013/2/20 Thomas Gleixner <tglx@linutronix.de>:
> > On Wed, 20 Feb 2013, Jason Liu wrote:
> >> void arch_idle(void)
> >> {
> >> ....
> >> clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
> >>
> >> enter_the_wait_mode();
> >>
> >> clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
> >> }
> >>
> >> when the broadcast timer interrupt arrives(this interrupt just wakeup
> >> the ARM, and ARM has no chance
> >> to handle it since local irq is disabled. In fact it's disabled in
> >> cpu_idle() of arch/arm/kernel/process.c)
> >>
> >> the broadcast timer interrupt will wake up the CPU and run:
> >>
> >> clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); ->
> >> tick_broadcast_oneshot_control(...);
> >> ->
> >> tick_program_event(dev->next_event, 1);
> >> ->
> >> tick_dev_program_event(dev, expires, force);
> >> ->
> >> for (i = 0;;) {
> >> int ret = clockevents_program_event(dev, expires, now);
> >> if (!ret || !force)
> >> return ret;
> >>
> >> dev->retries++;
> >> ....
> >> now = ktime_get();
> >> expires = ktime_add_ns(now, dev->min_delta_ns);
> >> }
> >> clockevents_program_event(dev, expires, now);
> >>
> >> delta = ktime_to_ns(ktime_sub(expires, now));
> >>
> >> if (delta <= 0)
> >> return -ETIME;
> >>
> >> when the bc timer interrupt arrives, which means the last local timer
> >> expires too. so,
> >> clockevents_program_event will return -ETIME, which will cause the
> >> dev->retries++
> >> when retry to program the expired timer.
> >>
> >> Even under the worst case, after the re-program the expired timer,
> >> then CPU enter idle
> >> quickly before the re-progam timer expired, it will make system
> >> ping-pang forever,
> >
> > That's nonsense.
>
> I don't think so.
>
> >
> > The timer IPI brings the core out of the deep idle state.
> >
> > So after returning from enter_wait_mode() and after calling
> > clockevents_notify() it returns from arch_idle() to cpu_idle().
> >
> > In cpu_idle() interrupts are reenabled, so the timer IPI handler is
> > invoked. That calls the event_handler of the per cpu local clockevent
> > device (the one which stops in C3). That ends up in the generic timer
> > code which expires timers and reprograms the local clock event device
> > with the next pending timer.
> >
> > So you cannot go idle again, before the expired timers of this event
> > are handled and their callbacks invoked.
>
> That's true for the CPUs which not response to the global timer interrupt.
> Take our platform as example: we have 4CPUs(CPU0, CPU1,CPU2,CPU3)
> The global timer device will keep running even in the deep idle mode, so, it
> can be used as the broadcast timer device, and the interrupt of this device
> just raised to CPU0 when the timer expired, then, CPU0 will broadcast the
> IPI timer to other CPUs which is in deep idle mode.
>
> So for CPU1, CPU2, CPU3, you are right, the IPI timer will bring it out of idle
> state, after running clockevents_notify() it returns from arch_idle()
> to cpu_idle(),
> then local_irq_enable(), the IPI handler will be invoked and handle
> the expires times
> and re-program the next pending timer.
>
> But, that's not true for the CPU0. The flow for CPU0 is:
> the global timer interrupt wakes up CPU0 and then call:
> clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
>
> which will cpumask_clear_cpu(cpu, tick_get_broadcast_oneshot_mask());
> in the function tick_broadcast_oneshot_control(),
Now your explanation makes sense.
I have no fast solution for this, but I think that I have an idea how
to fix it. Stay tuned.
Thanks,
tglx
next prev parent reply other threads:[~2013-02-21 9:36 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-20 11:16 too many timer retries happen when do local timer swtich with broadcast timer Jason Liu
2013-02-20 13:33 ` Thomas Gleixner
2013-02-21 6:16 ` Jason Liu
2013-02-21 9:36 ` Thomas Gleixner [this message]
2013-02-21 10:50 ` Jason Liu
2013-02-21 13:48 ` Thomas Gleixner
2013-02-21 15:12 ` Santosh Shilimkar
2013-02-21 22:19 ` Thomas Gleixner
2013-02-22 10:07 ` Santosh Shilimkar
2013-02-22 10:24 ` Thomas Gleixner
2013-02-22 10:30 ` Santosh Shilimkar
2013-02-22 10:31 ` Lorenzo Pieralisi
2013-02-22 11:02 ` Santosh Shilimkar
2013-02-22 12:07 ` Thomas Gleixner
2013-02-22 14:48 ` Lorenzo Pieralisi
2013-02-22 15:03 ` Thomas Gleixner
2013-02-22 15:26 ` Lorenzo Pieralisi
2013-02-22 18:52 ` Thomas Gleixner
2013-02-25 6:12 ` Santosh Shilimkar
2013-02-25 6:38 ` Jason Liu
2013-02-25 13:34 ` Lorenzo Pieralisi
2013-02-22 10:28 ` Lorenzo Pieralisi
2013-02-22 10:26 ` Jason Liu
2013-02-21 10:35 ` Lorenzo Pieralisi
2013-02-21 10:49 ` Jason Liu
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=alpine.LFD.2.02.1302211015270.22263@ionos \
--to=tglx@linutronix.de \
--cc=linux-arm-kernel@lists.infradead.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).