aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2013-11-19 19:07:34 -0500
committerIngo Molnar <mingo@kernel.org>2013-11-27 05:09:40 -0500
commit5c4853b60ca8ec3d989ce05a5e995d15c3ed52c0 (patch)
treec1dce0aa885edfab01f7f213bb734f285ad83b56 /kernel
parent7d5b15831039837f3551bf40f188385ed8ad5e16 (diff)
lockdep: Simplify a bit hardirq <-> softirq transitions
Instead of saving the hardirq state on a per CPU variable, which require an explicit call before the softirq handling and some complication, just save and restore the hardirq tracing state through functions return values and parameters. It simplifies a bit the black magic that works around the fact that softirqs can be called from hardirqs while hardirqs can nest on softirqs but those two cases have very different semantics and only the latter case assume both states. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Link: http://lkml.kernel.org/r/1384906054-30676-1-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/softirq.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c
index f84aa48c0e66..9a4500e4c189 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -213,40 +213,35 @@ EXPORT_SYMBOL(local_bh_enable_ip);
213 213
214#ifdef CONFIG_TRACE_IRQFLAGS 214#ifdef CONFIG_TRACE_IRQFLAGS
215/* 215/*
216 * Convoluted means of passing __do_softirq() a message through the various
217 * architecture execute_on_stack() bits.
218 *
219 * When we run softirqs from irq_exit() and thus on the hardirq stack we need 216 * When we run softirqs from irq_exit() and thus on the hardirq stack we need
220 * to keep the lockdep irq context tracking as tight as possible in order to 217 * to keep the lockdep irq context tracking as tight as possible in order to
221 * not miss-qualify lock contexts and miss possible deadlocks. 218 * not miss-qualify lock contexts and miss possible deadlocks.
222 */ 219 */
223static DEFINE_PER_CPU(int, softirq_from_hardirq);
224 220
225static inline void lockdep_softirq_from_hardirq(void) 221static inline bool lockdep_softirq_start(void)
226{ 222{
227 this_cpu_write(softirq_from_hardirq, 1); 223 bool in_hardirq = false;
228}
229 224
230static inline void lockdep_softirq_start(void) 225 if (trace_hardirq_context(current)) {
231{ 226 in_hardirq = true;
232 if (this_cpu_read(softirq_from_hardirq))
233 trace_hardirq_exit(); 227 trace_hardirq_exit();
228 }
229
234 lockdep_softirq_enter(); 230 lockdep_softirq_enter();
231
232 return in_hardirq;
235} 233}
236 234
237static inline void lockdep_softirq_end(void) 235static inline void lockdep_softirq_end(bool in_hardirq)
238{ 236{
239 lockdep_softirq_exit(); 237 lockdep_softirq_exit();
240 if (this_cpu_read(softirq_from_hardirq)) { 238
241 this_cpu_write(softirq_from_hardirq, 0); 239 if (in_hardirq)
242 trace_hardirq_enter(); 240 trace_hardirq_enter();
243 }
244} 241}
245
246#else 242#else
247static inline void lockdep_softirq_from_hardirq(void) { } 243static inline bool lockdep_softirq_start(void) { return false; }
248static inline void lockdep_softirq_start(void) { } 244static inline void lockdep_softirq_end(bool in_hardirq) { }
249static inline void lockdep_softirq_end(void) { }
250#endif 245#endif
251 246
252asmlinkage void __do_softirq(void) 247asmlinkage void __do_softirq(void)
@@ -255,6 +250,7 @@ asmlinkage void __do_softirq(void)
255 unsigned long old_flags = current->flags; 250 unsigned long old_flags = current->flags;
256 int max_restart = MAX_SOFTIRQ_RESTART; 251 int max_restart = MAX_SOFTIRQ_RESTART;
257 struct softirq_action *h; 252 struct softirq_action *h;
253 bool in_hardirq;
258 __u32 pending; 254 __u32 pending;
259 int cpu; 255 int cpu;
260 256
@@ -269,7 +265,7 @@ asmlinkage void __do_softirq(void)
269 account_irq_enter_time(current); 265 account_irq_enter_time(current);
270 266
271 __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET); 267 __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET);
272 lockdep_softirq_start(); 268 in_hardirq = lockdep_softirq_start();
273 269
274 cpu = smp_processor_id(); 270 cpu = smp_processor_id();
275restart: 271restart:
@@ -316,7 +312,7 @@ restart:
316 wakeup_softirqd(); 312 wakeup_softirqd();
317 } 313 }
318 314
319 lockdep_softirq_end(); 315 lockdep_softirq_end(in_hardirq);
320 account_irq_exit_time(current); 316 account_irq_exit_time(current);
321 __local_bh_enable(SOFTIRQ_OFFSET); 317 __local_bh_enable(SOFTIRQ_OFFSET);
322 WARN_ON_ONCE(in_interrupt()); 318 WARN_ON_ONCE(in_interrupt());
@@ -365,7 +361,6 @@ void irq_enter(void)
365static inline void invoke_softirq(void) 361static inline void invoke_softirq(void)
366{ 362{
367 if (!force_irqthreads) { 363 if (!force_irqthreads) {
368 lockdep_softirq_from_hardirq();
369#ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK 364#ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
370 /* 365 /*
371 * We can safely execute softirq on the current stack if 366 * We can safely execute softirq on the current stack if