===== 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-08 08:48:12 +08:00 @@ -2362,8 +2362,13 @@ static void __exit apm_exit(void) { int error; - if (set_pm_idle) + if (set_pm_idle) { pm_idle = original_pm_idle; + /* Wait the idle thread to read the new value, + * otherwise we Oops. + */ + 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-08 09:00:06 +08:00 @@ -142,6 +142,10 @@ void cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { while (!need_resched()) { + /* If pm_idle is in a module and is preempted, + * oops occurs. Disable preempt. + */ + rcu_read_lock(); void (*idle)(void) = pm_idle; if (!idle) @@ -149,6 +153,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-08 09:04:58 +08:00 @@ -228,18 +228,24 @@ 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); + /* If pm_idle is in a module and is preempted, + * oops occurs. Disable preempt. + */ + 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-08 09:04:31 +08:00 @@ -130,11 +130,18 @@ 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); + /* If pm_idle is in a module and is preempted, + * oops occurs. Disable preempt. + */ + 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-08 09:12:34 +08:00 @@ -2419,6 +2419,9 @@ acpi_processor_remove ( /* Unregister the idle handler when processor #0 is removed. */ if (pr->id == 0) { pm_idle = pm_idle_save; + /* Wait the idle thread to read the new value, + * otherwise we Oops. + */ synchronize_kernel(); }