Messages in this thread Patch in this message | | | Date | Mon, 20 Dec 2004 10:27:11 -0800 | From | Nishanth Aravamudan <> | Subject | Re: [PATCH] Remove RCU abuse in cpu_idle() |
| |
On Sun, Dec 19, 2004 at 07:10:31PM -0700, Zwane Mwaikambo wrote: > On Mon, 20 Dec 2004, Nick Piggin wrote: > > > On Sun, 2004-12-19 at 18:44 -0700, Zwane Mwaikambo wrote: > > > On Mon, 20 Dec 2004, Nick Piggin wrote: > > > > > > > This thread can possibly be stalled forever if there is a CPU hog > > > > running, right? > > > > > > Yep. > > > > > > > In which case, you will want to use ssleep rather than a busy loop. > > > > > > Well ssleep essentially does the same thing as the schedule_timeout. > > > > > > > Yes - so long as you set ->state when using schedule_timeout ;) > > Nish could you please submit something to switch it to ssleep?
I believe the only files/patches that needed to be changed were the process.c changes. Here they are re-worked to use ssleep(1) instead of schedule_timeout(HZ).
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
--- 2.6.10-rc3-v/arch/i386/kernel/process.c 2004-12-08 13:38:42.000000000 -0800 +++ 2.6.10-rc3/arch/i386/kernel/process.c 2004-12-20 10:15:54.000000000 -0800 @@ -72,6 +72,7 @@ unsigned long thread_saved_pc(struct tas * Powermanagement idle function, if any.. */ void (*pm_idle)(void); +static cpumask_t cpu_idle_map; void disable_hlt(void) { @@ -142,16 +143,16 @@ static void poll_idle (void) */ void cpu_idle (void) { + int cpu = smp_processor_id(); + /* endless idle loop with no priority at all */ while (1) { 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(); + + if (cpu_isset(cpu, cpu_idle_map)) + cpu_clear(cpu, cpu_idle_map); + rmb(); idle = pm_idle; if (!idle) @@ -159,12 +160,24 @@ void cpu_idle (void) irq_stat[smp_processor_id()].idle_timestamp = jiffies; idle(); - rcu_read_unlock(); } schedule(); } } +void cpu_idle_wait(void) +{ + int cpu; + + for_each_online_cpu(cpu) + cpu_set(cpu, cpu_idle_map); + + wmb(); + while (cpus_equal(cpu_idle_map, cpu_online_map)) + ssleep(1); +} +EXPORT_SYMBOL_GPL(cpu_idle_wait); + /* * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, * which can obviate IPI to trigger checking of need_resched. --- 2.6.10-rc3-v/arch/ia64/kernel/process.c 2004-12-08 13:38:43.000000000 -0800 +++ 2.6.10-rc3/arch/ia64/kernel/process.c 2004-12-20 10:16:18.000000000 -0800 @@ -46,6 +46,7 @@ #include "sigframe.h" void (*ia64_mark_idle)(int); +static cpumask_t cpu_idle_map; unsigned long boot_option_idle_override = 0; EXPORT_SYMBOL(boot_option_idle_override); @@ -225,10 +226,24 @@ static inline void play_dead(void) } #endif /* CONFIG_HOTPLUG_CPU */ +void cpu_idle_wait(void) +{ + int cpu; + + for_each_online_cpu(cpu) + cpu_set(cpu, cpu_idle_map); + + wmb(); + while (cpus_equal(cpu_idle_map, cpu_online_map)) + ssleep(1); +} +EXPORT_SYMBOL_GPL(cpu_idle_wait); + void __attribute__((noreturn)) cpu_idle (void *unused) { void (*mark_idle)(int) = ia64_mark_idle; + int cpu = smp_processor_id(); /* endless idle loop with no priority at all */ while (1) { @@ -241,17 +256,14 @@ cpu_idle (void *unused) 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(); + + if (cpu_isset(cpu, cpu_idle_map)) + cpu_clear(cpu, cpu_idle_map); + rmb(); idle = pm_idle; if (!idle) idle = default_idle; (*idle)(); - rcu_read_unlock(); } if (mark_idle) --- 2.6.10-rc3-v/arch/x86_64/kernel/process.c 2004-12-08 13:38:45.000000000 -0800 +++ 2.6.10-rc3/arch/x86_64/kernel/process.c 2004-12-20 10:16:59.000000000 -0800 @@ -61,6 +61,7 @@ EXPORT_SYMBOL(boot_option_idle_override) * Powermanagement idle function, if any.. */ void (*pm_idle)(void); +static cpumask_t cpu_idle_map; void disable_hlt(void) { @@ -123,6 +124,19 @@ static void poll_idle (void) } } +void cpu_idle_wait(void) +{ + int cpu; + + for_each_online_cpu(cpu) + cpu_set(cpu, cpu_idle_map); + + wmb(); + while (cpus_equal(cpu_idle_map, cpu_online_map)) + ssleep(1); +} +EXPORT_SYMBOL_GPL(cpu_idle_wait); + /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a @@ -131,21 +145,20 @@ static void poll_idle (void) */ void cpu_idle (void) { + int cpu = smp_processor_id(); + /* endless idle loop with no priority at all */ while (1) { 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(); + + if (cpu_isset(cpu, cpu_idle_map)) + cpu_clear(cpu, cpu_idle_map); + rmb(); idle = pm_idle; if (!idle) idle = default_idle; idle(); - rcu_read_unlock(); } schedule(); } - 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/
| |