[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: Zwane Mwaikambo <zwane@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Tony Luck <tony.luck@intel.com>
This commit is contained in:
parent
de7548d0e2
commit
7d5f9c0f10
@ -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)
|
|||||||
}
|
}
|
||||||
#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;
|
||||||
|
|
||||||
for_each_online_cpu(cpu)
|
set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
|
||||||
cpu_set(cpu, cpu_idle_map);
|
put_cpu();
|
||||||
|
|
||||||
wmb();
|
cpus_clear(map);
|
||||||
do {
|
for_each_online_cpu(cpu) {
|
||||||
ssleep(1);
|
per_cpu(cpu_idle_state, cpu) = 1;
|
||||||
cpus_and(map, cpu_idle_map, cpu_online_map);
|
cpu_set(cpu, map);
|
||||||
} while (!cpus_empty(map));
|
}
|
||||||
|
|
||||||
|
__get_cpu_var(cpu_idle_state) = 0;
|
||||||
|
|
||||||
|
wmb();
|
||||||
|
do {
|
||||||
|
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))
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user