diff options
author | Peter Zijlstra <peterz@infradead.org> | 2013-11-19 10:13:38 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-01-13 11:32:27 -0500 |
commit | 0bd3a173d711857fc9f583eb5825386cc08f3948 (patch) | |
tree | 3807a2744f0e22afa0a009c6c2cb2bf8d7fb746e | |
parent | 10b033d434c25a6c9e0f4f4dc2418af1b8236c63 (diff) |
sched/preempt, locking: Rework local_bh_{dis,en}able()
Currently local_bh_disable() is out-of-line for no apparent reason.
So inline it to save a few cycles on call/return nonsense, the
function body is a single add on x86 (a few loads and store extra on
load/store archs).
Also expose two new local_bh functions:
__local_bh_{dis,en}able_ip(unsigned long ip, unsigned int cnt);
Which implement the actual local_bh_{dis,en}able() behaviour.
The next patch uses the exposed @cnt argument to optimize bh lock
functions.
With build fixes from Jacob Pan.
Cc: rjw@rjwysocki.net
Cc: rui.zhang@intel.com
Cc: jacob.jun.pan@linux.intel.com
Cc: Mike Galbraith <bitbucket@online.de>
Cc: hpa@zytor.com
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: lenb@kernel.org
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20131119151338.GF3694@twins.programming.kicks-ass.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | include/linux/bottom_half.h | 32 | ||||
-rw-r--r-- | include/linux/hardirq.h | 1 | ||||
-rw-r--r-- | include/linux/preempt_mask.h | 1 | ||||
-rw-r--r-- | kernel/softirq.c | 35 |
4 files changed, 36 insertions, 33 deletions
diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h index 27b1bcffe408..86c12c93e3cf 100644 --- a/include/linux/bottom_half.h +++ b/include/linux/bottom_half.h | |||
@@ -1,9 +1,35 @@ | |||
1 | #ifndef _LINUX_BH_H | 1 | #ifndef _LINUX_BH_H |
2 | #define _LINUX_BH_H | 2 | #define _LINUX_BH_H |
3 | 3 | ||
4 | extern void local_bh_disable(void); | 4 | #include <linux/preempt.h> |
5 | #include <linux/preempt_mask.h> | ||
6 | |||
7 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
8 | extern void __local_bh_disable_ip(unsigned long ip, unsigned int cnt); | ||
9 | #else | ||
10 | static __always_inline void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) | ||
11 | { | ||
12 | preempt_count_add(cnt); | ||
13 | barrier(); | ||
14 | } | ||
15 | #endif | ||
16 | |||
17 | static inline void local_bh_disable(void) | ||
18 | { | ||
19 | __local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET); | ||
20 | } | ||
21 | |||
5 | extern void _local_bh_enable(void); | 22 | extern void _local_bh_enable(void); |
6 | extern void local_bh_enable(void); | 23 | extern void __local_bh_enable_ip(unsigned long ip, unsigned int cnt); |
7 | extern void local_bh_enable_ip(unsigned long ip); | 24 | |
25 | static inline void local_bh_enable_ip(unsigned long ip) | ||
26 | { | ||
27 | __local_bh_enable_ip(ip, SOFTIRQ_DISABLE_OFFSET); | ||
28 | } | ||
29 | |||
30 | static inline void local_bh_enable(void) | ||
31 | { | ||
32 | __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET); | ||
33 | } | ||
8 | 34 | ||
9 | #endif /* _LINUX_BH_H */ | 35 | #endif /* _LINUX_BH_H */ |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index d9cf963ac832..12d5f972f23f 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/lockdep.h> | 5 | #include <linux/lockdep.h> |
6 | #include <linux/ftrace_irq.h> | 6 | #include <linux/ftrace_irq.h> |
7 | #include <linux/vtime.h> | 7 | #include <linux/vtime.h> |
8 | #include <asm/hardirq.h> | ||
8 | 9 | ||
9 | 10 | ||
10 | extern void synchronize_irq(unsigned int irq); | 11 | extern void synchronize_irq(unsigned int irq); |
diff --git a/include/linux/preempt_mask.h b/include/linux/preempt_mask.h index b8d96bca4357..dbeec4d4a3be 100644 --- a/include/linux/preempt_mask.h +++ b/include/linux/preempt_mask.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define LINUX_PREEMPT_MASK_H | 2 | #define LINUX_PREEMPT_MASK_H |
3 | 3 | ||
4 | #include <linux/preempt.h> | 4 | #include <linux/preempt.h> |
5 | #include <asm/hardirq.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We put the hardirq and softirq counter into the preemption | 7 | * We put the hardirq and softirq counter into the preemption |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 7500cce1ebfd..9e368ef35f9a 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -89,7 +89,7 @@ static void wakeup_softirqd(void) | |||
89 | * where hardirqs are disabled legitimately: | 89 | * where hardirqs are disabled legitimately: |
90 | */ | 90 | */ |
91 | #ifdef CONFIG_TRACE_IRQFLAGS | 91 | #ifdef CONFIG_TRACE_IRQFLAGS |
92 | static void __local_bh_disable(unsigned long ip, unsigned int cnt) | 92 | void __local_bh_disable_ip(unsigned long ip, unsigned int cnt) |
93 | { | 93 | { |
94 | unsigned long flags; | 94 | unsigned long flags; |
95 | 95 | ||
@@ -114,21 +114,9 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt) | |||
114 | if (preempt_count() == cnt) | 114 | if (preempt_count() == cnt) |
115 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); | 115 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); |
116 | } | 116 | } |
117 | #else /* !CONFIG_TRACE_IRQFLAGS */ | 117 | EXPORT_SYMBOL(__local_bh_disable_ip); |
118 | static inline void __local_bh_disable(unsigned long ip, unsigned int cnt) | ||
119 | { | ||
120 | preempt_count_add(cnt); | ||
121 | barrier(); | ||
122 | } | ||
123 | #endif /* CONFIG_TRACE_IRQFLAGS */ | 118 | #endif /* CONFIG_TRACE_IRQFLAGS */ |
124 | 119 | ||
125 | void local_bh_disable(void) | ||
126 | { | ||
127 | __local_bh_disable(_RET_IP_, SOFTIRQ_DISABLE_OFFSET); | ||
128 | } | ||
129 | |||
130 | EXPORT_SYMBOL(local_bh_disable); | ||
131 | |||
132 | static void __local_bh_enable(unsigned int cnt) | 120 | static void __local_bh_enable(unsigned int cnt) |
133 | { | 121 | { |
134 | WARN_ON_ONCE(!irqs_disabled()); | 122 | WARN_ON_ONCE(!irqs_disabled()); |
@@ -151,7 +139,7 @@ void _local_bh_enable(void) | |||
151 | 139 | ||
152 | EXPORT_SYMBOL(_local_bh_enable); | 140 | EXPORT_SYMBOL(_local_bh_enable); |
153 | 141 | ||
154 | static inline void _local_bh_enable_ip(unsigned long ip) | 142 | void __local_bh_enable_ip(unsigned long ip, unsigned int cnt) |
155 | { | 143 | { |
156 | WARN_ON_ONCE(in_irq() || irqs_disabled()); | 144 | WARN_ON_ONCE(in_irq() || irqs_disabled()); |
157 | #ifdef CONFIG_TRACE_IRQFLAGS | 145 | #ifdef CONFIG_TRACE_IRQFLAGS |
@@ -166,7 +154,7 @@ static inline void _local_bh_enable_ip(unsigned long ip) | |||
166 | * Keep preemption disabled until we are done with | 154 | * Keep preemption disabled until we are done with |
167 | * softirq processing: | 155 | * softirq processing: |
168 | */ | 156 | */ |
169 | preempt_count_sub(SOFTIRQ_DISABLE_OFFSET - 1); | 157 | preempt_count_sub(cnt - 1); |
170 | 158 | ||
171 | if (unlikely(!in_interrupt() && local_softirq_pending())) { | 159 | if (unlikely(!in_interrupt() && local_softirq_pending())) { |
172 | /* | 160 | /* |
@@ -182,18 +170,7 @@ static inline void _local_bh_enable_ip(unsigned long ip) | |||
182 | #endif | 170 | #endif |
183 | preempt_check_resched(); | 171 | preempt_check_resched(); |
184 | } | 172 | } |
185 | 173 | EXPORT_SYMBOL(__local_bh_enable_ip); | |
186 | void local_bh_enable(void) | ||
187 | { | ||
188 | _local_bh_enable_ip(_RET_IP_); | ||
189 | } | ||
190 | EXPORT_SYMBOL(local_bh_enable); | ||
191 | |||
192 | void local_bh_enable_ip(unsigned long ip) | ||
193 | { | ||
194 | _local_bh_enable_ip(ip); | ||
195 | } | ||
196 | EXPORT_SYMBOL(local_bh_enable_ip); | ||
197 | 174 | ||
198 | /* | 175 | /* |
199 | * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times, | 176 | * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times, |
@@ -230,7 +207,7 @@ asmlinkage void __do_softirq(void) | |||
230 | pending = local_softirq_pending(); | 207 | pending = local_softirq_pending(); |
231 | account_irq_enter_time(current); | 208 | account_irq_enter_time(current); |
232 | 209 | ||
233 | __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET); | 210 | __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); |
234 | lockdep_softirq_enter(); | 211 | lockdep_softirq_enter(); |
235 | 212 | ||
236 | cpu = smp_processor_id(); | 213 | cpu = smp_processor_id(); |