diff options
author | Andrew Morton <akpm@osdl.org> | 2006-12-06 20:38:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 08:39:39 -0800 |
commit | a38a44c1a93078fc5fadc4ac2df8dea4697069e2 (patch) | |
tree | 03ad860836722b803a02a58d5e988fb9f9b883fc | |
parent | 83df8db9e62129975fab6d800fb381faf0dfee74 (diff) | |
download | op-kernel-dev-a38a44c1a93078fc5fadc4ac2df8dea4697069e2.zip op-kernel-dev-a38a44c1a93078fc5fadc4ac2df8dea4697069e2.tar.gz |
[PATCH] smp_call_function_single() check that local interrupts are enabled
smp_call_function_single() can deadlock if the caller disabled local
interrupts (the target CPU could be spinning on call_lock). Check for that.
Why on earth do these functions use spin_lock_bh()??
Cc: "Randy.Dunlap" <rdunlap@xenotime.net>
Cc: Andi Kleen <ak@suse.de>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/i386/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/x86_64/kernel/smp.c | 4 |
2 files changed, 8 insertions, 0 deletions
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 31e5c65..9827cf9 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -699,6 +699,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, put_cpu(); return -EBUSY; } + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + spin_lock_bh(&call_lock); __smp_call_function_single(cpu, func, info, nonatomic, wait); spin_unlock_bh(&call_lock); diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 9f74c88..32f4d7e 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -379,6 +379,10 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info, put_cpu(); return 0; } + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + spin_lock_bh(&call_lock); __smp_call_function_single(cpu, func, info, nonatomic, wait); spin_unlock_bh(&call_lock); |