Commit 7d5f9c0f authored by Zwane Mwaikambo's avatar Zwane Mwaikambo Committed by Tony Luck

[IA64] reduce cacheline bouncing in cpu_idle_wait

Andi noted that during normal runtime cpu_idle_map is bounced around a lot,
and occassionally at a higher frequency than the timer interrupt wakeup
which we normally exit pm_idle from.  So switch to a percpu variable.

I didn't move things to the slow path because it would involve adding
scheduler code to wakeup the idle thread on the cpus we're waiting for.
Signed-off-by: default avatarZwane Mwaikambo <zwane@arm.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent de7548d0
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
#include "sigframe.h" #include "sigframe.h"
void (*ia64_mark_idle)(int); void (*ia64_mark_idle)(int);
static cpumask_t cpu_idle_map; static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
unsigned long boot_option_idle_override = 0; unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override); EXPORT_SYMBOL(boot_option_idle_override);
...@@ -223,20 +223,31 @@ static inline void play_dead(void) ...@@ -223,20 +223,31 @@ static inline void play_dead(void)
} }
#endif /* CONFIG_HOTPLUG_CPU */ #endif /* CONFIG_HOTPLUG_CPU */
void cpu_idle_wait(void) void cpu_idle_wait(void)
{ {
int cpu; unsigned int cpu, this_cpu = get_cpu();
cpumask_t map; cpumask_t map;
set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
put_cpu();
for_each_online_cpu(cpu) cpus_clear(map);
cpu_set(cpu, cpu_idle_map); for_each_online_cpu(cpu) {
per_cpu(cpu_idle_state, cpu) = 1;
cpu_set(cpu, map);
}
wmb(); __get_cpu_var(cpu_idle_state) = 0;
do {
ssleep(1); wmb();
cpus_and(map, cpu_idle_map, cpu_online_map); do {
} while (!cpus_empty(map)); ssleep(1);
for_each_online_cpu(cpu) {
if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
cpu_clear(cpu, map);
}
cpus_and(map, map, cpu_online_map);
} while (!cpus_empty(map));
} }
EXPORT_SYMBOL_GPL(cpu_idle_wait); EXPORT_SYMBOL_GPL(cpu_idle_wait);
...@@ -244,7 +255,6 @@ void __attribute__((noreturn)) ...@@ -244,7 +255,6 @@ void __attribute__((noreturn))
cpu_idle (void) cpu_idle (void)
{ {
void (*mark_idle)(int) = ia64_mark_idle; void (*mark_idle)(int) = ia64_mark_idle;
int cpu = smp_processor_id();
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
while (1) { while (1) {
...@@ -255,12 +265,13 @@ cpu_idle (void) ...@@ -255,12 +265,13 @@ cpu_idle (void)
while (!need_resched()) { while (!need_resched()) {
void (*idle)(void); void (*idle)(void);
if (__get_cpu_var(cpu_idle_state))
__get_cpu_var(cpu_idle_state) = 0;
rmb();
if (mark_idle) if (mark_idle)
(*mark_idle)(1); (*mark_idle)(1);
if (cpu_isset(cpu, cpu_idle_map))
cpu_clear(cpu, cpu_idle_map);
rmb();
idle = pm_idle; idle = pm_idle;
if (!idle) if (!idle)
idle = default_idle; idle = default_idle;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment