Messages in this thread Patch in this message |  | | Date | Wed, 6 Feb 2013 05:42:58 -0800 | From | tip-bot for Chuansheng Liu <> | Subject | [tip:core/locking] smp: Give WARN()ing if in_interrupt() when calling smp_call_function_many()/single() |
| |
Commit-ID: b29f39c7c3e75a741a7da88244ec707f293ec04c Gitweb: http://git.kernel.org/tip/b29f39c7c3e75a741a7da88244ec707f293ec04c Author: Chuansheng Liu <chuansheng.liu@intel.com> AuthorDate: Wed, 6 Feb 2013 23:18:21 +0800 Committer: Ingo Molnar <mingo@kernel.org> CommitDate: Wed, 6 Feb 2013 12:00:30 +0100
smp: Give WARN()ing if in_interrupt() when calling smp_call_function_many()/single()
Currently the functions smp_call_function_many()/single() will give a WARN()ing only in the case of irqs_disabled(), but that check is not enough to guarantee execution of the SMP cross-calls.
In many other cases such as softirq handling/interrupt handling, the two APIs still can not be called, just as the smp_call_function_many() comments say:
* You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. Preemption * must be disabled when calling this function.
There is a real case for softirq DEADLOCK case:
CPUA CPUB spin_lock(&spinlock) Any irq coming, call the irq handler irq_exit() spin_lock_irq(&spinlock) <== Blocking here due to CPUB hold it __do_softirq() run_timer_softirq() timer_cb() call smp_call_function_many() send IPI interrupt to CPUA wait_csd()
Then both CPUA and CPUB will be deadlocked here.
So we should give a warning in the in_interrupt() case as well.
Signed-off-by: liu chuansheng <chuansheng.liu@intel.com> Cc: jun.zhang@intel.com Cc: peterz@infradead.org Cc: jbeulich@suse.com Cc: paulmck@linux.vnet.ibm.com Cc: mina86@mina86.org Cc: srivatsa.bhat@linux.vnet.ibm.com Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1360163901.24670.13.camel@cliu38-desktop-build Signed-off-by: Ingo Molnar <mingo@kernel.org> --- kernel/smp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/kernel/smp.c b/kernel/smp.c index 29dd40a..fec45aa 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -12,6 +12,7 @@ #include <linux/gfp.h> #include <linux/smp.h> #include <linux/cpu.h> +#include <linux/hardirq.h> #include "smpboot.h" @@ -318,7 +319,7 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info, * send smp call function interrupt to this cpu and as such deadlocks * can't happen. */ - WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled() + WARN_ON_ONCE(cpu_online(this_cpu) && (irqs_disabled() || in_interrupt()) && !oops_in_progress); if (cpu == this_cpu) { @@ -416,8 +417,9 @@ void __smp_call_function_single(int cpu, struct call_single_data *data, * send smp call function interrupt to this cpu and as such deadlocks * can't happen. */ - WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait && irqs_disabled() - && !oops_in_progress); + WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait + && (irqs_disabled() || in_interrupt()) + && !oops_in_progress); if (cpu == this_cpu) { local_irq_save(flags);
|  |