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
WARNING: multiple messages have this Message-ID (diff)
From: Thomas Gleixner <tglx@linutronix.de>
To: Jason Liu <liu.h.jason@gmail.com>
Cc: LKML <linux-kernel@vger.kernel.org>,
linux-arm-kernel@lists.infradead.org
Subject: Re: 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: 50+ 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 11:16 ` Jason Liu
2013-02-20 13:33 ` Thomas Gleixner
2013-02-20 13:33 ` Thomas Gleixner
2013-02-21 6:16 ` Jason Liu
2013-02-21 6:16 ` Jason Liu
2013-02-21 9:36 ` Thomas Gleixner [this message]
2013-02-21 9:36 ` Thomas Gleixner
2013-02-21 10:50 ` Jason Liu
2013-02-21 10:50 ` Jason Liu
2013-02-21 13:48 ` Thomas Gleixner
2013-02-21 13:48 ` Thomas Gleixner
2013-02-21 15:12 ` Santosh Shilimkar
2013-02-21 15:12 ` Santosh Shilimkar
2013-02-21 22:19 ` Thomas Gleixner
2013-02-21 22:19 ` Thomas Gleixner
2013-02-22 10:07 ` Santosh Shilimkar
2013-02-22 10:07 ` Santosh Shilimkar
2013-02-22 10:24 ` Thomas Gleixner
2013-02-22 10:24 ` Thomas Gleixner
2013-02-22 10:30 ` Santosh Shilimkar
2013-02-22 10:30 ` Santosh Shilimkar
2013-02-22 10:31 ` Lorenzo Pieralisi
2013-02-22 10:31 ` Lorenzo Pieralisi
2013-02-22 11:02 ` Santosh Shilimkar
2013-02-22 11:02 ` Santosh Shilimkar
2013-02-22 12:07 ` Thomas Gleixner
2013-02-22 12:07 ` Thomas Gleixner
2013-02-22 14:48 ` Lorenzo Pieralisi
2013-02-22 14:48 ` Lorenzo Pieralisi
2013-02-22 15:03 ` Thomas Gleixner
2013-02-22 15:03 ` Thomas Gleixner
2013-02-22 15:26 ` Lorenzo Pieralisi
2013-02-22 15:26 ` Lorenzo Pieralisi
2013-02-22 18:52 ` Thomas Gleixner
2013-02-22 18:52 ` Thomas Gleixner
2013-02-25 6:12 ` Santosh Shilimkar
2013-02-25 6:12 ` Santosh Shilimkar
2013-02-25 6:38 ` Jason Liu
2013-02-25 6:38 ` Jason Liu
2013-02-25 13:34 ` Lorenzo Pieralisi
2013-02-25 13:34 ` Lorenzo Pieralisi
2013-02-22 10:28 ` Lorenzo Pieralisi
2013-02-22 10:28 ` Lorenzo Pieralisi
2013-02-22 10:26 ` Jason Liu
2013-02-22 10:26 ` Jason Liu
2013-02-21 10:35 ` Lorenzo Pieralisi
2013-02-21 10:35 ` Lorenzo Pieralisi
2013-02-21 10:49 ` Jason Liu
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 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.