linux/arch
Thomas Gleixner fd8a7de177 x86: cpu-hotplug: Prevent softirq wakeup on wrong CPU
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>
Cc: stable@kernel.org # 2.6.39
2011-06-08 11:21:19 +02:00
..
alpha Merge branch 'setns' 2011-05-28 10:51:01 -07:00
arm Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6 2011-06-07 18:46:37 -07:00
avr32 Merge branch 'setns' 2011-05-28 10:51:01 -07:00
blackfin Blackfin: strncpy: fix handling of zero lengths 2011-06-03 11:05:36 -04:00
cris Merge branch 'setns' 2011-05-28 10:51:01 -07:00
frv Merge branch 'setns' 2011-05-28 10:51:01 -07:00
h8300 Merge branch 'setns' 2011-05-28 10:51:01 -07:00
ia64 [IA64] wire up sendmmsg() syscall for Itanium 2011-05-31 10:09:24 -07:00
m32r Merge branch 'setns' 2011-05-28 10:51:01 -07:00
m68k Merge branch 'setns' 2011-05-28 10:51:01 -07:00
microblaze Merge branch 'setns' 2011-05-28 10:51:01 -07:00
mips Merge branch 'setns' 2011-05-28 10:51:01 -07:00
mn10300 MN10300: Add missing _sdata declaration 2011-06-07 19:03:53 -07:00
parisc Merge branch 'setns' 2011-05-28 10:51:01 -07:00
powerpc powerpc/pmac: Don't register pmac PIC syscore ops when HW not present 2011-05-31 20:30:20 +09:00
s390 [S390] fix kvm defines for 31 bit compile 2011-06-06 14:14:56 +02:00
score arch: remove CONFIG_GENERIC_FIND_{NEXT_BIT,BIT_LE,LAST_BIT} 2011-05-26 17:12:38 -07:00
sh sh: Fix up asm-generic/ptrace.h fallout. 2011-05-31 14:39:49 +09:00
sparc Merge branch 'setns' 2011-05-28 10:51:01 -07:00
tile Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile 2011-05-29 11:29:28 -07:00
um arch: remove CONFIG_GENERIC_FIND_{NEXT_BIT,BIT_LE,LAST_BIT} 2011-05-26 17:12:38 -07:00
unicore32 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6 2011-05-27 14:27:34 -07:00
x86 x86: cpu-hotplug: Prevent softirq wakeup on wrong CPU 2011-06-08 11:21:19 +02:00
xtensa Merge branch 'setns' 2011-05-28 10:51:01 -07:00
.gitignore
Kconfig mm, powerpc: move the RCU page-table freeing into generic code 2011-05-25 08:39:16 -07:00