History

genirq: Change force_irqthreads to a static key

With CONFIG_IRQ_FORCED_THREADING=y, testing the boolean force_irqthreads could incur a cache line miss in invoke_softirq() and other places. Replace the test with a static key to avoid the potential cache miss. [ tglx: Dropped the IDE part, removed the export and updated blk-mq ]

Tanner Love committed 5 years ago

Commit 91cc4701 parent 5a6c76b4 files · +12 −11Browse files

Unified · Split

4 files
  1. block/blk-mq.c +1 −1
  2. include/linux/interrupt.h +5 −3
  3. kernel/irq/manage.c +5 −6
  4. kernel/softirq.c +1 −1
block/blk-mq.c+1−1
@@ -606,7 +606,7 @@ static inline bool blk_mq_complete_need_ipi(struct request *rq) · 605 unmodified lines
606606 * This is probably worse than completing the request on a different
607607 * cache domain.
608608 */
609− if (force_irqthreads)
609+ if (force_irqthreads())
610610 return false;
611611
612612 /* same CPU or cache domain? Complete locally */
include/linux/interrupt.h+5−3
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #include <linux/hrtimer.h>
1414 #include <linux/kref.h>
1515 #include <linux/workqueue.h>
16+#include <linux/jump_label.h>
1617
1718 #include <linux/atomic.h>
1819 #include <asm/ptrace.h>
@@ -474,12 +475,13 @@ extern int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, · 455 unmodified lines
474475
475476 #ifdef CONFIG_IRQ_FORCED_THREADING
476477 # ifdef CONFIG_PREEMPT_RT
477−# define force_irqthreads (true)
478+# define force_irqthreads() (true)
478479 # else
479−extern bool force_irqthreads;
480+DECLARE_STATIC_KEY_FALSE(force_irqthreads_key);
481+# define force_irqthreads() (static_branch_unlikely(&force_irqthreads_key))
480482 # endif
481483 #else
482−#define force_irqthreads (0)
484+#define force_irqthreads() (false)
483485 #endif
484486
485487 #ifndef local_softirq_pending
kernel/irq/manage.c+5−6
@@ -25,12 +25,11 @@ · 24 unmodified lines
2525 #include "internals.h"
2626
2727 #if defined(CONFIG_IRQ_FORCED_THREADING) && !defined(CONFIG_PREEMPT_RT)
28−__read_mostly bool force_irqthreads;
29−EXPORT_SYMBOL_GPL(force_irqthreads);
28+DEFINE_STATIC_KEY_FALSE(force_irqthreads_key);
3029
3130 static int __init setup_forced_irqthreads(char *arg)
3231 {
33− force_irqthreads = true;
32+ static_branch_enable(&force_irqthreads_key);
3433 return 0;
3534 }
3635 early_param("threadirqs", setup_forced_irqthreads);
@@ -1260,8 +1259,8 @@ static int irq_thread(void *data) · 1223 unmodified lines
12601259 irqreturn_t (*handler_fn)(struct irq_desc *desc,
12611260 struct irqaction *action);
12621261
1263− if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD,
1264− &action->thread_flags))
1262+ if (force_irqthreads() && test_bit(IRQTF_FORCED_THREAD,
1263+ &action->thread_flags))
12651264 handler_fn = irq_forced_thread_fn;
12661265 else
12671266 handler_fn = irq_thread_fn;
@@ -1322,7 +1321,7 @@ EXPORT_SYMBOL_GPL(irq_wake_thread); · 54 unmodified lines
13221321
13231322 static int irq_setup_forced_threading(struct irqaction *new)
13241323 {
1325− if (!force_irqthreads)
1324+ if (!force_irqthreads())
13261325 return 0;
13271326 if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
13281327 return 0;
kernel/softirq.c+1−1
@@ -422,7 +422,7 @@ static inline void invoke_softirq(void) · 421 unmodified lines
422422 if (ksoftirqd_running(local_softirq_pending()))
423423 return;
424424
425− if (!force_irqthreads || !__this_cpu_read(ksoftirqd)) {
425+ if (!force_irqthreads() || !__this_cpu_read(ksoftirqd)) {
426426 #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
427427 /*
428428 * We can safely execute softirq on the current stack if