Messages in this thread Patch in this message | | | Date | Mon, 23 Aug 2004 04:41:49 -0400 (EDT) | From | Zwane Mwaikambo <> | Subject | [PATCH] Hotplug cpu: Fix APIC queued timer vector race #2 |
| |
On Mon, 23 Aug 2004, Rusty Russell wrote:
> On Mon, 2004-08-23 at 00:47, Zwane Mwaikambo wrote: > > On Sun, 22 Aug 2004, Rusty Russell wrote: > > > > > On Sun, 2004-08-22 at 00:10, Zwane Mwaikambo wrote: > > > > Some timer interrupt vectors were queued on the Local APIC and were being > > > > serviced when we enabled interrupts again in fixup_irqs(), so we need to > > > > mask the APIC timer, enable interrupts so that any queued interrupts get > > > > processed whilst the processor is still on the online map and then clear > > > > ourselves from the online map. 1ms is a nice safe number even under heavy > > > > interrupt load with higher priority vectors queued. Andrew this is > > > > the patch i promised, Rusty, i'm not sure if you find > > > > __attribute__((weak)) offensive... > > > > > > It's horrible. Please move the unsetting of the cpu_online bit into the > > > arch-specific __cpu_disable() code for each arch, which is consistent > > > and also simplifies things.
Ok this should be the last one, against 2.6.8.1-mm4.
arch/i386/kernel/smpboot.c | 21 +++++++++------------ arch/ia64/kernel/smpboot.c | 3 ++- arch/ppc64/kernel/smp.c | 4 +++- arch/s390/kernel/smp.c | 4 +++- kernel/cpu.c | 21 +++++---------------- 5 files changed, 22 insertions(+), 31 deletions(-)
Signed-off-by: Zwane Mwaikambo <zwane@linuxpower.ca>
Index: linux-2.6.8.1-mm4/kernel/cpu.c =================================================================== RCS file: /home/cvsroot/linux-2.6.8.1-mm4/kernel/cpu.c,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 cpu.c --- linux-2.6.8.1-mm4/kernel/cpu.c 23 Aug 2004 08:24:54 -0000 1.1.1.1 +++ linux-2.6.8.1-mm4/kernel/cpu.c 23 Aug 2004 08:32:01 -0000 @@ -84,31 +84,20 @@ static int cpu_run_sbin_hotplug(unsigned return call_usermodehelper(argv[0], argv, envp, 0); }
-void __attribute__((weak)) __cpu_prep_disable(void) -{ -} - /* Take this CPU down. */ static int take_cpu_down(void *unused) { int err;
- /* Prepatory work before clearing the cpu off the online map */ - __cpu_prep_disable(); - - /* Take offline: makes arch_cpu_down somewhat easier. */ - cpu_clear(smp_processor_id(), cpu_online_map); - /* Ensure this CPU doesn't handle any more interrupts. */ err = __cpu_disable(); if (err < 0) - cpu_set(smp_processor_id(), cpu_online_map); - else - /* Force idle task to run as soon as we yield: it should - immediately notice cpu is offline and die quickly. */ - sched_idle_next(); + return err;
- return err; + /* Force idle task to run as soon as we yield: it should + immediately notice cpu is offline and die quickly. */ + sched_idle_next(); + return 0; }
int cpu_down(unsigned int cpu) Index: linux-2.6.8.1-mm4/arch/i386/kernel/smpboot.c =================================================================== RCS file: /home/cvsroot/linux-2.6.8.1-mm4/arch/i386/kernel/smpboot.c,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 smpboot.c --- linux-2.6.8.1-mm4/arch/i386/kernel/smpboot.c 23 Aug 2004 08:23:22 -0000 1.1.1.1 +++ linux-2.6.8.1-mm4/arch/i386/kernel/smpboot.c 23 Aug 2004 08:32:01 -0000 @@ -1159,18 +1159,6 @@ static int __devinit cpu_enable(unsigned return 0; }
-void __cpu_prep_disable(void) -{ - /* We enable the timer again on the exit path of the death loop */ - if (smp_processor_id() != 0) { - disable_APIC_timer(); - /* Allow any queued timer interrupts to get serviced */ - local_irq_enable(); - mdelay(1); - local_irq_disable(); - } -} - int __cpu_disable(void) { /* @@ -1184,6 +1172,15 @@ int __cpu_disable(void) if (smp_processor_id() == 0) return -EBUSY;
+ /* We enable the timer again on the exit path of the death loop */ + disable_APIC_timer(); + /* Allow any queued timer interrupts to get serviced */ + local_irq_enable(); + mdelay(1); + local_irq_disable(); + + /* It's now safe to remove this processor from the online map */ + cpu_clear(smp_processor_id(), cpu_online_map); fixup_irqs(); return 0; } Index: linux-2.6.8.1-mm4/arch/ia64/kernel/smpboot.c =================================================================== RCS file: /home/cvsroot/linux-2.6.8.1-mm4/arch/ia64/kernel/smpboot.c,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 smpboot.c --- linux-2.6.8.1-mm4/arch/ia64/kernel/smpboot.c 23 Aug 2004 08:23:31 -0000 1.1.1.1 +++ linux-2.6.8.1-mm4/arch/ia64/kernel/smpboot.c 23 Aug 2004 08:32:01 -0000 @@ -591,9 +591,10 @@ int __cpu_disable(void) if (cpu == 0) return -EBUSY;
+ cpu_clear(cpu, cpu_online_map); fixup_irqs(); local_flush_tlb_all(); - printk ("Disabled cpu %u\n", smp_processor_id()); + printk("Disabled cpu %u\n", cpu); return 0; }
Index: linux-2.6.8.1-mm4/arch/ppc64/kernel/smp.c =================================================================== RCS file: /home/cvsroot/linux-2.6.8.1-mm4/arch/ppc64/kernel/smp.c,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 smp.c --- linux-2.6.8.1-mm4/arch/ppc64/kernel/smp.c 23 Aug 2004 08:23:34 -0000 1.1.1.1 +++ linux-2.6.8.1-mm4/arch/ppc64/kernel/smp.c 23 Aug 2004 08:32:01 -0000 @@ -254,11 +254,13 @@ int __cpu_disable(void) { /* FIXME: go put this in a header somewhere */ extern void xics_migrate_irqs_away(void); + int cpu = smp_processor_id();
+ cpu_clear(cpu, cpu_online_map); systemcfg->processorCount--;
/*fix boot_cpuid here*/ - if (smp_processor_id() == boot_cpuid) + if (cpu == boot_cpuid) boot_cpuid = any_online_cpu(cpu_online_map);
/* FIXME: abstract this to not be platform specific later on */ Index: linux-2.6.8.1-mm4/arch/s390/kernel/smp.c =================================================================== RCS file: /home/cvsroot/linux-2.6.8.1-mm4/arch/s390/kernel/smp.c,v retrieving revision 1.1.1.1 diff -u -p -B -r1.1.1.1 smp.c --- linux-2.6.8.1-mm4/arch/s390/kernel/smp.c 23 Aug 2004 08:23:39 -0000 1.1.1.1 +++ linux-2.6.8.1-mm4/arch/s390/kernel/smp.c 23 Aug 2004 08:32:01 -0000 @@ -682,13 +682,15 @@ __cpu_disable(void) { unsigned long flags; ec_creg_mask_parms cr_parms; + int cpu = smp_processor_id();
spin_lock_irqsave(&smp_reserve_lock, flags); - if (smp_cpu_reserved[smp_processor_id()] != 0) { + if (smp_cpu_reserved[cpu] != 0) { spin_unlock_irqrestore(&smp_reserve_lock, flags); return -EBUSY; }
+ cpu_clear(cpu, cpu_online_map); /* disable all external interrupts */
cr_parms.start_ctl = 0; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |