path: root/kernel
diff options
authorKirill Korotaev <>2005-11-13 16:07:30 -0800
committerLinus Torvalds <>2005-11-13 18:14:16 -0800
commit4557398f8cbaf9f254cff747534b4724c7f75c4f (patch)
tree052b59279b1312a4fde83a76feb4a7a0c5cf7df1 /kernel
parentc5b609797b8e212dbfaf23944da8bf8c53233d5c (diff)
[PATCH] stop_machine() vs. synchronous IPI send deadlock
This fixes deadlock of stop_machine() vs. synchronous IPI send. The problem is that stop_machine() disables interrupts before disabling preemption on other CPUs. So if another CPU is preempted and then calls something like flush_tlb_all() it will deadlock with CPU doing stop_machine() and which can't process IPI due to disabled IRQs. I changed stop_machine() to do the same things exactly as it does on other CPUs, i.e. it should disable preemption first on _all_ CPUs including itself and only after that disable IRQs. Signed-off-by: Kirill Korotaev <> Cc: Rusty Russell <> Cc: "Andrey Savochkin" <> Signed-off-by: Andrew Morton <> Signed-off-by: Linus Torvalds <>
Diffstat (limited to 'kernel')
1 files changed, 3 insertions, 3 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 84a9d18aa8da..b3d4dc858e35 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -119,13 +119,12 @@ static int stop_machine(void)
return ret;
- /* Don't schedule us away at this point, please. */
- local_irq_disable();
/* Now they are all started, make them hold the CPUs, ready. */
+ preempt_disable();
/* Make them disable irqs. */
+ local_irq_disable();
return 0;
@@ -135,6 +134,7 @@ static void restart_machine(void)
+ preempt_enable_no_resched();
struct stop_machine_data