===== arch/i386/kernel/apm.c 1.67 vs edited ===== --- 1.67/arch/i386/kernel/apm.c 2004-08-24 17:08:47 +08:00 +++ edited/arch/i386/kernel/apm.c 2004-09-09 10:57:16 +08:00 @@ -2362,8 +2362,15 @@ static void __exit apm_exit(void) { int error; - if (set_pm_idle) + if (set_pm_idle) { pm_idle = original_pm_idle; + /* + * We are about to unload the current idle thread pm callback + * (pm_idle), Wait for all processors to update cached/local + * copies of pm_idle before proceeding. + */ + synchronize_kernel(); + } if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) && (apm_info.connection_version > 0x0100)) { error = apm_engage_power_management(APM_DEVICE_ALL, 0); ===== arch/i386/kernel/process.c 1.75 vs edited ===== --- 1.75/arch/i386/kernel/process.c 2004-08-24 17:08:44 +08:00 +++ edited/arch/i386/kernel/process.c 2004-09-09 10:59:47 +08:00 @@ -142,6 +142,12 @@ void cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { + /* + * Mark this as an RCU critical section so that + * synchronize_kernel() in the unload path waits + * for our completion. + */ + rcu_read_lock(); void (*idle)(void) = pm_idle; if (!idle) @@ -149,6 +155,7 @@ void cpu_idle (void) irq_stat[smp_processor_id()].idle_timestamp = jiffies; idle(); + rcu_read_unlock(); } schedule(); } ===== arch/ia64/kernel/process.c 1.62 vs edited ===== --- 1.62/arch/ia64/kernel/process.c 2004-07-27 13:26:50 +08:00 +++ edited/arch/ia64/kernel/process.c 2004-09-09 11:01:12 +08:00 @@ -228,18 +228,26 @@ cpu_idle (void *unused) /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; - if (!idle) - idle = default_idle; - #ifdef CONFIG_SMP if (!need_resched()) min_xtp(); #endif while (!need_resched()) { + void (*idle)(void); + if (mark_idle) (*mark_idle)(1); + /* + * Mark this as an RCU critical section so that + * synchronize_kernel() in the unload path waits + * for our completion. + */ + rcu_read_lock(); + idle= pm_idle; + if (!idle) + idle = default_idle; (*idle)(); + rcu_read_unlock(); } if (mark_idle) ===== arch/x86_64/kernel/process.c 1.35 vs edited ===== --- 1.35/arch/x86_64/kernel/process.c 2004-08-24 17:08:44 +08:00 +++ edited/arch/x86_64/kernel/process.c 2004-09-09 11:01:57 +08:00 @@ -130,11 +130,20 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { - void (*idle)(void) = pm_idle; - if (!idle) - idle = default_idle; - while (!need_resched()) + while (!need_resched()) { + void (*idle)(void); + /* + * Mark this as an RCU critical section so that + * synchronize_kernel() in the unload path waits + * for our completion. + */ + rcu_read_lock(); + idle = pm_idle; + if (!idle) + idle = default_idle; idle(); + rcu_read_unlock(); + } schedule(); } } ===== drivers/acpi/processor.c 1.61 vs edited ===== --- 1.61/drivers/acpi/processor.c 2004-08-31 23:27:29 +08:00 +++ edited/drivers/acpi/processor.c 2004-09-09 11:02:56 +08:00 @@ -2419,6 +2419,11 @@ acpi_processor_remove ( /* Unregister the idle handler when processor #0 is removed. */ if (pr->id == 0) { pm_idle = pm_idle_save; + /* + * We are about to unload the current idle thread pm callback + * (pm_idle), Wait for all processors to update cached/local + * copies of pm_idle before proceeding. + */ synchronize_kernel(); }