aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/softirq.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2013-09-24 11:17:47 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2013-10-01 06:53:27 -0400
commitcc1f027454929924471bea2f362431072e3c71be (patch)
treed5e732927b0a7ad19f9d1a3f4aa30c4bce6ebbba /kernel/softirq.c
parent0bed698a334766ed07bacd6cb33f0228003a7f61 (diff)
irq: Optimize softirq stack selection in irq exit
If irq_exit() is called on the arch's specified irq stack, it should be safe to run softirqs inline under that same irq stack as it is near empty by the time we call irq_exit(). For example if we use the same stack for both hard and soft irqs here, the worst case scenario is: hardirq -> softirq -> hardirq. But then the softirq supersedes the first hardirq as the stack user since irq_exit() is called in a mostly empty stack. So the stack merge in this case looks acceptable. Stack overrun still have a chance to happen if hardirqs have more opportunities to nest, but then it's another problem to solve. So lets adapt the irq exit's softirq stack on top of a new Kconfig symbol that can be defined when irq_exit() runs on the irq stack. That way we can spare some stack switch on irq processing and all the cache issues that come along. Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@au1.ibm.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul Mackerras <paulus@au1.ibm.com> Cc: James Hogan <james.hogan@imgtec.com> Cc: James E.J. Bottomley <jejb@parisc-linux.org> Cc: Helge Deller <deller@gmx.de> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: David S. Miller <davem@davemloft.net> Cc: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r--kernel/softirq.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 2b4328ea769f..dacd0ab51df4 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -332,15 +332,21 @@ void irq_enter(void)
332static inline void invoke_softirq(void) 332static inline void invoke_softirq(void)
333{ 333{
334 if (!force_irqthreads) { 334 if (!force_irqthreads) {
335#ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
335 /* 336 /*
336 * We can safely execute softirq on the current stack if 337 * We can safely execute softirq on the current stack if
337 * it is the irq stack, because it should be near empty 338 * it is the irq stack, because it should be near empty
338 * at this stage. But we have no way to know if the arch 339 * at this stage.
339 * calls irq_exit() on the irq stack. So call softirq 340 */
340 * in its own stack to prevent from any overrun on top 341 __do_softirq();
341 * of a potentially deep task stack. 342#else
343 /*
344 * Otherwise, irq_exit() is called on the task stack that can
345 * be potentially deep already. So call softirq in its own stack
346 * to prevent from any overrun.
342 */ 347 */
343 do_softirq_own_stack(); 348 do_softirq_own_stack();
349#endif
344 } else { 350 } else {
345 wakeup_softirqd(); 351 wakeup_softirqd();
346 } 352 }