Commit-ID: b29f39c7c3e75a741a7da88244ec707f293ec04c Gitweb: http://git.kernel.org/tip/b29f39c7c3e75a741a7da88244ec707f293ec04c Author: Chuansheng Liu <chuansheng....@intel.com> AuthorDate: Wed, 6 Feb 2013 23:18:21 +0800 Committer: Ingo Molnar <mi...@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....@intel.com> Cc: jun.zh...@intel.com Cc: pet...@infradead.org Cc: jbeul...@suse.com Cc: paul...@linux.vnet.ibm.com Cc: min...@mina86.org Cc: srivatsa.b...@linux.vnet.ibm.com Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Andrew Morton <a...@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijls...@chello.nl> Link: http://lkml.kernel.org/r/1360163901.24670.13.camel@cliu38-desktop-build Signed-off-by: Ingo Molnar <mi...@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); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/