x86: cpu-hotplug: Prevent softirq wakeup on wrong CPU
commit28223659e8b6af5d7303849f64cc3e7a4003bcbc
authorThomas Gleixner <tglx@linutronix.de>
Tue, 20 Jul 2010 12:34:50 +0000 (20 14:34 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 23 Jun 2011 22:05:40 +0000 (23 15:05 -0700)
treea47a33715a6024c24600399d633a63fcee355627
parent9441ac93bbff3c5759058f26999f26002d99e82b
x86: cpu-hotplug: Prevent softirq wakeup on wrong CPU

commit fd8a7de177b6f56a0fc59ad211c197a7df06b1ad upstream.

After a newly plugged CPU sets the cpu_online bit it enables
interrupts and goes idle. The cpu which brought up the new cpu waits
for the cpu_online bit and when it observes it, it sets the cpu_active
bit for this cpu. The cpu_active bit is the relevant one for the
scheduler to consider the cpu as a viable target.

With forced threaded interrupt handlers which imply forced threaded
softirqs we observed the following race:

cpu 0                         cpu 1

bringup(cpu1);
                              set_cpu_online(smp_processor_id(), true);
              local_irq_enable();
while (!cpu_online(cpu1));
                              timer_interrupt()
                                -> wake_up(softirq_thread_cpu1);
                                     -> enqueue_on(softirq_thread_cpu1, cpu0);

                                                                        ^^^^

cpu_notify(CPU_ONLINE, cpu1);
  -> sched_cpu_active(cpu1)
     -> set_cpu_active((cpu1, true);

When an interrupt happens before the cpu_active bit is set by the cpu
which brought up the newly onlined cpu, then the scheduler refuses to
enqueue the woken thread which is bound to that newly onlined cpu on
that newly onlined cpu due to the not yet set cpu_active bit and
selects a fallback runqueue. Not really an expected and desirable
behaviour.

So far this has only been observed with forced hard/softirq threading,
but in theory this could happen without forced threaded hard/softirqs
as well. It's probably unobservable as it would take a massive
interrupt storm on the newly onlined cpu which causes the softirq loop
to wake up the softirq thread and an even longer delay of the cpu
which waits for the cpu_online bit.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/x86/kernel/smpboot.c