2.6.6-rc3 Warn when smp_call_function() is called with interrupts disabled
Subsystems (6)
PATCH 1/1 2.6.6-rc3 Warn when smp_call_function() is called with interrupts disabled
Almost every architecture has a comment above smp_call_function()
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
I have not seen any problems with calling smp_call_function() from a bottom half handler, but calling it with interrupts disabled can definitely deadlock. This bug is hard to reproduce and even harder to debug.
CPU A CPU B
Disable interrupts
smp_call_function()
Take call_lock
Send IPIs
Wait for all cpus to acknowledge IPI CPU A has not responded, spin waiting for cpu A to respond, holding call_locksmp_call_function()
Spin waiting for call_lock
Deadlock Deadlock
Change all smp_call_function() to WARN_ON(irqs_disabled()). It should be BUG_ON() but some buggy code like SCSI sg will break with BUG_ON, so just warn for now. Change it to BUG_ON after the buggy code has been fixed.
Tested on ia64 and i386. It was even tested on UP, just for akpm ;)
arch/alpha/kernel/smp.c +3 -0
@@ -820,6 +820,9 @@unsigned long timeout;int num_cpus_to_call; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info; data.wait = wait;
arch/i386/kernel/smp.c +3 -0
@@ -519,6 +519,9 @@if (!cpus)return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info;atomic_set (&data.started,0 );
arch/i386/mach-voyager/voyager_smp.c +3 -0
@@ -1106,6 +1106,9 @@if (!mask)return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info; data.started = mask;
arch/ia64/kernel/smp.c +3 -0
@@ -308,6 +308,9 @@if (!cpus)return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info;atomic_set (&data.started,0 );
arch/mips/kernel/smp.c +3 -0
@@ -151,6 +151,9 @@if (!cpus)return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info;atomic_set (&data.started,0 );
arch/parisc/kernel/smp.c +3 -0
@@ -327,6 +327,9 @@struct smp_call_struct data;unsigned long timeout;static spinlock_t lock =SPIN_LOCK_UNLOCKED ; + +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); data.func = func; data.info = info;
arch/ppc/kernel/smp.c +2 -0
@@ -211,6 +211,8 @@bitmask. --RR */ if (num_online_cpus () <=1 )return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ());return __smp_call_function (func, info, wait,MSG_ALL_BUT_SELF ); }
arch/ppc64/kernel/smp.c +3 -0
@@ -692,6 +692,9 @@int ret =-1 , cpus;unsigned long timeout; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info;atomic_set (&data.started,0 );
arch/s390/kernel/smp.c +3 -0
@@ -127,6 +127,9 @@if (cpus <=0 )return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info;atomic_set (&data.started,0 );
arch/sh/kernel/smp.c +3 -0
@@ -181,6 +181,9 @@if (nr_cpus <2 )return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); +spin_lock (&smp_fn_call.lock);atomic_set (&smp_fn_call.finished,0 );
arch/sparc64/kernel/smp.c +3 -0
@@ -598,6 +598,9 @@if (!cpus)return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info;atomic_set (&data.finished,0 );
arch/um/kernel/smp.c +3 -0
@@ -266,6 +266,9 @@if (!cpus)return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); +spin_lock_bh (&call_lock);atomic_set (&scf_started,0 );atomic_set (&scf_finished,0 );
arch/x86_64/kernel/smp.c +3 -0
@@ -404,6 +404,9 @@if (!cpus)return 0 ; +/* Can deadlock when called with interrupts disabled */ +WARN_ON (irqs_disabled ()); + data.func = func; data.info = info;atomic_set (&data.started,0 );