* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
[not found] <1361373336-11337-1-git-send-email-fweisbec@gmail.com>
@ 2013-02-20 21:00 ` Thomas Gleixner
2013-02-20 22:01 ` Frederic Weisbecker
2013-02-21 17:53 ` Linus Torvalds
0 siblings, 2 replies; 10+ messages in thread
From: Thomas Gleixner @ 2013-02-20 21:00 UTC (permalink / raw)
To: Frederic Weisbecker; +Cc: Ingo Molnar, LKML, Peter Zijlstra, stable
On Wed, 20 Feb 2013, Frederic Weisbecker wrote:
> As it stands, irq_exit() may or may not be called with
> irqs disabled, depending on __ARCH_IRQ_EXIT_IRQS_DISABLED
> that the arch can define.
>
> It makes tick_nohz_irq_exit() unsafe. For example two
> interrupts can race in tick_nohz_stop_sched_tick(): the inner
> most one computes the expiring time on top of the timer list,
> then it's interrupted right before reprogramming the
> clock. The new interrupt enqueues a new timer list timer,
> it reprogram the clock to take it into account and it exits.
> The CPUs resumes the inner most interrupt and performs the clock
> reprogramming without considering the new timer list timer.
>
> This regression has been introduced by:
> 280f06774afedf849f0b34248ed6aff57d0f6908
> ("nohz: Separate out irq exit and idle loop dyntick logic")
>
> Let's fix it right now with the appropriate protections.
That's not a fix. That's an hack.
> A saner long term solution will be to remove
> __ARCH_IRQ_EXIT_IRQS_DISABLED.
We really want to enforce that interrupt disabled condition for
calling irq_exit(). So why make this exclusive to tick_nohz_irq_exit()?
Thanks,
tglx
Index: linux-2.6/kernel/softirq.c
===================================================================
--- linux-2.6.orig/kernel/softirq.c
+++ linux-2.6/kernel/softirq.c
@@ -322,18 +322,10 @@ void irq_enter(void)
static inline void invoke_softirq(void)
{
- if (!force_irqthreads) {
-#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
+ if (!force_irqthreads)
__do_softirq();
-#else
- do_softirq();
-#endif
- } else {
- __local_bh_disable((unsigned long)__builtin_return_address(0),
- SOFTIRQ_OFFSET);
+ else
wakeup_softirqd();
- __local_bh_enable(SOFTIRQ_OFFSET);
- }
}
/*
@@ -341,6 +333,14 @@ static inline void invoke_softirq(void)
*/
void irq_exit(void)
{
+#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
+ unsigned long flags;
+
+ local_irq_save(flags);
+#else
+ BUG_ON(!irqs_disabled();
+#endif
+
account_irq_exit_time(current);
trace_hardirq_exit();
sub_preempt_count(IRQ_EXIT_OFFSET);
@@ -354,6 +354,9 @@ void irq_exit(void)
#endif
rcu_irq_exit();
sched_preempt_enable_no_resched();
+#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
+ local_irq_restore(flags);
+#endif
}
/*
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-20 21:00 ` [PATCH] nohz: Make tick_nohz_irq_exit() irq safe Thomas Gleixner
@ 2013-02-20 22:01 ` Frederic Weisbecker
2013-02-20 23:15 ` Thomas Gleixner
2013-02-21 17:53 ` Linus Torvalds
1 sibling, 1 reply; 10+ messages in thread
From: Frederic Weisbecker @ 2013-02-20 22:01 UTC (permalink / raw)
To: Thomas Gleixner; +Cc: Ingo Molnar, LKML, Peter Zijlstra, stable
2013/2/20 Thomas Gleixner <tglx@linutronix.de>:
> On Wed, 20 Feb 2013, Frederic Weisbecker wrote:
>
>> As it stands, irq_exit() may or may not be called with
>> irqs disabled, depending on __ARCH_IRQ_EXIT_IRQS_DISABLED
>> that the arch can define.
>>
>> It makes tick_nohz_irq_exit() unsafe. For example two
>> interrupts can race in tick_nohz_stop_sched_tick(): the inner
>> most one computes the expiring time on top of the timer list,
>> then it's interrupted right before reprogramming the
>> clock. The new interrupt enqueues a new timer list timer,
>> it reprogram the clock to take it into account and it exits.
>> The CPUs resumes the inner most interrupt and performs the clock
>> reprogramming without considering the new timer list timer.
>>
>> This regression has been introduced by:
>> 280f06774afedf849f0b34248ed6aff57d0f6908
>> ("nohz: Separate out irq exit and idle loop dyntick logic")
>>
>> Let's fix it right now with the appropriate protections.
>
> That's not a fix. That's an hack.
I know it looks that way. That's because it's a pure regression fix,
minimal for backportability.
I'm distinguishing two different things here: the fact that some archs
can call irq_exit() with interrupts enabled which is a global design
problem, and the fact that tick_nohz_irq_exit() was safe against that
until 3.2 when I broke it with a commit of mine.
My goal was basically to restore that protection in a minimal commit
such that we can backport the regression fix, then deal with
__ARCH_IRQ_EXIT_IRQS_DISABLED afterward, since it requires some more
invasive changes.
>> A saner long term solution will be to remove
>> __ARCH_IRQ_EXIT_IRQS_DISABLED.
>
> We really want to enforce that interrupt disabled condition for
> calling irq_exit(). So why make this exclusive to tick_nohz_irq_exit()?
I need a fix that I can backport. Is the below fine with a stable tag?
It looks a bit too invasive for the single regression involved.
Thanks.
>
> Thanks,
>
> tglx
>
> Index: linux-2.6/kernel/softirq.c
> ===================================================================
> --- linux-2.6.orig/kernel/softirq.c
> +++ linux-2.6/kernel/softirq.c
> @@ -322,18 +322,10 @@ void irq_enter(void)
>
> static inline void invoke_softirq(void)
> {
> - if (!force_irqthreads) {
> -#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
> + if (!force_irqthreads)
> __do_softirq();
> -#else
> - do_softirq();
> -#endif
> - } else {
> - __local_bh_disable((unsigned long)__builtin_return_address(0),
> - SOFTIRQ_OFFSET);
> + else
> wakeup_softirqd();
> - __local_bh_enable(SOFTIRQ_OFFSET);
> - }
> }
>
> /*
> @@ -341,6 +333,14 @@ static inline void invoke_softirq(void)
> */
> void irq_exit(void)
> {
> +#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
> + unsigned long flags;
> +
> + local_irq_save(flags);
> +#else
> + BUG_ON(!irqs_disabled();
> +#endif
> +
> account_irq_exit_time(current);
> trace_hardirq_exit();
> sub_preempt_count(IRQ_EXIT_OFFSET);
> @@ -354,6 +354,9 @@ void irq_exit(void)
> #endif
> rcu_irq_exit();
> sched_preempt_enable_no_resched();
> +#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
> + local_irq_restore(flags);
> +#endif
> }
>
> /*
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-20 22:01 ` Frederic Weisbecker
@ 2013-02-20 23:15 ` Thomas Gleixner
2013-02-21 16:13 ` Frederic Weisbecker
0 siblings, 1 reply; 10+ messages in thread
From: Thomas Gleixner @ 2013-02-20 23:15 UTC (permalink / raw)
To: Frederic Weisbecker; +Cc: Ingo Molnar, LKML, Peter Zijlstra, stable
On Wed, 20 Feb 2013, Frederic Weisbecker wrote:
> 2013/2/20 Thomas Gleixner <tglx@linutronix.de>:
> > That's not a fix. That's an hack.
>
> I know it looks that way. That's because it's a pure regression fix,
> minimal for backportability.
>
> I'm distinguishing two different things here: the fact that some archs
> can call irq_exit() with interrupts enabled which is a global design
> problem, and the fact that tick_nohz_irq_exit() was safe against that
> until 3.2 when I broke it with a commit of mine.
>
> My goal was basically to restore that protection in a minimal commit
> such that we can backport the regression fix, then deal with
> __ARCH_IRQ_EXIT_IRQS_DISABLED afterward, since it requires some more
> invasive changes.
>
> >> A saner long term solution will be to remove
> >> __ARCH_IRQ_EXIT_IRQS_DISABLED.
> >
> > We really want to enforce that interrupt disabled condition for
> > calling irq_exit(). So why make this exclusive to tick_nohz_irq_exit()?
>
> I need a fix that I can backport. Is the below fine with a stable tag?
> It looks a bit too invasive for the single regression involved.
I think that's fine as it's obviously correct and not diluting the
real underlying issue of the __ARCH_IRQ_EXIT_IRQS_DISABLED insanity.
Thanks,
tglx
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-20 23:15 ` Thomas Gleixner
@ 2013-02-21 16:13 ` Frederic Weisbecker
2013-02-21 16:46 ` Thomas Gleixner
0 siblings, 1 reply; 10+ messages in thread
From: Frederic Weisbecker @ 2013-02-21 16:13 UTC (permalink / raw)
To: Thomas Gleixner; +Cc: Ingo Molnar, LKML, Peter Zijlstra, stable
2013/2/21 Thomas Gleixner <tglx@linutronix.de>:
> On Wed, 20 Feb 2013, Frederic Weisbecker wrote:
>> 2013/2/20 Thomas Gleixner <tglx@linutronix.de>:
>> > That's not a fix. That's an hack.
>>
>> I know it looks that way. That's because it's a pure regression fix,
>> minimal for backportability.
>>
>> I'm distinguishing two different things here: the fact that some archs
>> can call irq_exit() with interrupts enabled which is a global design
>> problem, and the fact that tick_nohz_irq_exit() was safe against that
>> until 3.2 when I broke it with a commit of mine.
>>
>> My goal was basically to restore that protection in a minimal commit
>> such that we can backport the regression fix, then deal with
>> __ARCH_IRQ_EXIT_IRQS_DISABLED afterward, since it requires some more
>> invasive changes.
>>
>> >> A saner long term solution will be to remove
>> >> __ARCH_IRQ_EXIT_IRQS_DISABLED.
>> >
>> > We really want to enforce that interrupt disabled condition for
>> > calling irq_exit(). So why make this exclusive to tick_nohz_irq_exit()?
>>
>> I need a fix that I can backport. Is the below fine with a stable tag?
>> It looks a bit too invasive for the single regression involved.
>
> I think that's fine as it's obviously correct and not diluting the
> real underlying issue of the __ARCH_IRQ_EXIT_IRQS_DISABLED insanity.
Ok fine. Do you plan to commit your proposed change then?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-21 16:13 ` Frederic Weisbecker
@ 2013-02-21 16:46 ` Thomas Gleixner
2013-02-21 16:49 ` Frederic Weisbecker
0 siblings, 1 reply; 10+ messages in thread
From: Thomas Gleixner @ 2013-02-21 16:46 UTC (permalink / raw)
To: Frederic Weisbecker; +Cc: Ingo Molnar, LKML, Peter Zijlstra, stable
On Thu, 21 Feb 2013, Frederic Weisbecker wrote:
> 2013/2/21 Thomas Gleixner <tglx@linutronix.de>:
> > On Wed, 20 Feb 2013, Frederic Weisbecker wrote:
> >> 2013/2/20 Thomas Gleixner <tglx@linutronix.de>:
> >> > That's not a fix. That's an hack.
> >>
> >> I know it looks that way. That's because it's a pure regression fix,
> >> minimal for backportability.
> >>
> >> I'm distinguishing two different things here: the fact that some archs
> >> can call irq_exit() with interrupts enabled which is a global design
> >> problem, and the fact that tick_nohz_irq_exit() was safe against that
> >> until 3.2 when I broke it with a commit of mine.
> >>
> >> My goal was basically to restore that protection in a minimal commit
> >> such that we can backport the regression fix, then deal with
> >> __ARCH_IRQ_EXIT_IRQS_DISABLED afterward, since it requires some more
> >> invasive changes.
> >>
> >> >> A saner long term solution will be to remove
> >> >> __ARCH_IRQ_EXIT_IRQS_DISABLED.
> >> >
> >> > We really want to enforce that interrupt disabled condition for
> >> > calling irq_exit(). So why make this exclusive to tick_nohz_irq_exit()?
> >>
> >> I need a fix that I can backport. Is the below fine with a stable tag?
> >> It looks a bit too invasive for the single regression involved.
> >
> > I think that's fine as it's obviously correct and not diluting the
> > real underlying issue of the __ARCH_IRQ_EXIT_IRQS_DISABLED insanity.
>
> Ok fine. Do you plan to commit your proposed change then?
Second thoughts. I probably go for your minimal fix for stable and
then push my version on top of it to Linus only.
Thanks,
tglx
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-21 16:46 ` Thomas Gleixner
@ 2013-02-21 16:49 ` Frederic Weisbecker
0 siblings, 0 replies; 10+ messages in thread
From: Frederic Weisbecker @ 2013-02-21 16:49 UTC (permalink / raw)
To: Thomas Gleixner; +Cc: Ingo Molnar, LKML, Peter Zijlstra, stable
2013/2/21 Thomas Gleixner <tglx@linutronix.de>:
> On Thu, 21 Feb 2013, Frederic Weisbecker wrote:
> Second thoughts. I probably go for your minimal fix for stable and
> then push my version on top of it to Linus only.
Thanks, I feel more comfortable with that. Then I'll try to iterate
over archs to finally remove that damn macro.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-20 21:00 ` [PATCH] nohz: Make tick_nohz_irq_exit() irq safe Thomas Gleixner
2013-02-20 22:01 ` Frederic Weisbecker
@ 2013-02-21 17:53 ` Linus Torvalds
2013-02-21 18:21 ` Thomas Gleixner
1 sibling, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2013-02-21 17:53 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Frederic Weisbecker, Ingo Molnar, LKML, Peter Zijlstra, stable
On Wed, Feb 20, 2013 at 1:00 PM, Thomas Gleixner <tglx@linutronix.de> wrote:
> */
> void irq_exit(void)
> {
> +#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
> + unsigned long flags;
> +
> + local_irq_save(flags);
> +#else
> + BUG_ON(!irqs_disabled();
> +#endif
Guys, STOP DOING THIS!
Adding BUG_ON()'s just makes things much much much worse. There is
*never* a reason to add a BUG_ON(). And doing it in an interrupt path
is totally unacceptable. BUG_ON() makes it almost impossible to debug
something, because you just killed the machine. So using BUG_ON() for
"please notice this" is stupid as hell, because the most common end
result is: "Oh, the machine just hung with no messages".
Make it WARN_ON_ONCE() if you absolutely have to let people know, but
for something like this, why would you do even that?
Linus
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-21 17:53 ` Linus Torvalds
@ 2013-02-21 18:21 ` Thomas Gleixner
2013-02-21 18:28 ` Linus Torvalds
0 siblings, 1 reply; 10+ messages in thread
From: Thomas Gleixner @ 2013-02-21 18:21 UTC (permalink / raw)
To: Linus Torvalds
Cc: Frederic Weisbecker, Ingo Molnar, LKML, Peter Zijlstra, stable
On Thu, 21 Feb 2013, Linus Torvalds wrote:
> On Wed, Feb 20, 2013 at 1:00 PM, Thomas Gleixner <tglx@linutronix.de> wrote:
> > */
> > void irq_exit(void)
> > {
> > +#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
> > + unsigned long flags;
> > +
> > + local_irq_save(flags);
> > +#else
> > + BUG_ON(!irqs_disabled();
> > +#endif
>
> Guys, STOP DOING THIS!
>
> Adding BUG_ON()'s just makes things much much much worse. There is
> *never* a reason to add a BUG_ON(). And doing it in an interrupt path
> is totally unacceptable. BUG_ON() makes it almost impossible to debug
> something, because you just killed the machine. So using BUG_ON() for
> "please notice this" is stupid as hell, because the most common end
> result is: "Oh, the machine just hung with no messages".
>
> Make it WARN_ON_ONCE() if you absolutely have to let people know, but
> for something like this, why would you do even that?
This was a draft patch. I made it a WARN_ON_ONCE() already.
We really want to enforce that irq_exit() is called with interrupts
disabled.
Thanks,
tglx
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-21 18:21 ` Thomas Gleixner
@ 2013-02-21 18:28 ` Linus Torvalds
2013-02-22 8:54 ` Ingo Molnar
0 siblings, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2013-02-21 18:28 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Frederic Weisbecker, Ingo Molnar, LKML, Peter Zijlstra, stable
On Thu, Feb 21, 2013 at 10:21 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
>
> This was a draft patch. I made it a WARN_ON_ONCE() already.
Ok, good.
I really wish we could just get rid of BUG_ON(). It was a bad idea,
and it makes it easy for people to do the wrong thing. Sadly, we have
tons of them.
Linus
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] nohz: Make tick_nohz_irq_exit() irq safe
2013-02-21 18:28 ` Linus Torvalds
@ 2013-02-22 8:54 ` Ingo Molnar
0 siblings, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2013-02-22 8:54 UTC (permalink / raw)
To: Linus Torvalds
Cc: Thomas Gleixner, Frederic Weisbecker, LKML, Peter Zijlstra,
stable
* Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Thu, Feb 21, 2013 at 10:21 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> >
> > This was a draft patch. I made it a WARN_ON_ONCE() already.
>
> Ok, good.
>
> I really wish we could just get rid of BUG_ON(). It was a bad
> idea, and it makes it easy for people to do the wrong thing.
> Sadly, we have tons of them.
So my old plan was to use a little bit of psychology.
Firstly, we could just turn BUG_ON() into a WARN() variant that
emits:
BUG: ...
while a WARN()ings emit:
WARNING: ...
and then we could introduce a new primitive:
CRASH_ON();
which would be used in the (few) places that really, really
cannot continue sanely and need to crash the box.
This naming alone would inhibit its use through two channels:
- Putting the word 'CRASH' into your code feels risky,
dissonant and wrong (perfect code does not crash) and thus
needs conscious frontal lobe effort to justify it - while
BUG_ON() really feels more like a harmless assert to most
kernel developers, which is in our muscle memory through
years training.
- CRASH_ON() takes one character more typing than WARN_ON(),
and we know good kernel developers are fundamentally lazy.
[ This is an arguably lazy plan that does not involve changing
the 10,000+ BUG_ON() call sites and does not involve the
re-training of thousands of mis-trained kernel developers who
introduced over 900 new BUG_ON()s in the v3.7->v3.8 cycle
alone (!). ]
So while I don't think we can win the war against BUG_ON(), I
think we can fight the lazy general's war: turn the enemy over
to our side and declare victory?
Thanks,
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-02-22 8:54 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1361373336-11337-1-git-send-email-fweisbec@gmail.com>
2013-02-20 21:00 ` [PATCH] nohz: Make tick_nohz_irq_exit() irq safe Thomas Gleixner
2013-02-20 22:01 ` Frederic Weisbecker
2013-02-20 23:15 ` Thomas Gleixner
2013-02-21 16:13 ` Frederic Weisbecker
2013-02-21 16:46 ` Thomas Gleixner
2013-02-21 16:49 ` Frederic Weisbecker
2013-02-21 17:53 ` Linus Torvalds
2013-02-21 18:21 ` Thomas Gleixner
2013-02-21 18:28 ` Linus Torvalds
2013-02-22 8:54 ` Ingo Molnar
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).