Commit 72690a21 authored by Andi Kleen's avatar Andi Kleen Committed by Andi Kleen

[PATCH] x86: Don't use nested idle loops

Currently the idle loop has two nested loops -- one high level
in cpu_idle and in some low level idle functions another one.

Looping in the low level idle functions breaks the idle notifiers
because interrupts waking up sleep states need to execute
exit_idle() which is only in cpu_idle().

So don't do that, only loop in cpu_idle(). This only removes
code.

In some cases e.g. poll_idle the idle loop is a little longer
now because cpu_idle checks more things. I hope that isn't a problem
ACPI idle doesn't change behaviour because it never looped anyways.

Cc: len.brown@intel.com
Cc: eranian@hpl.hp.com
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent 63cb683c
...@@ -100,21 +100,17 @@ EXPORT_SYMBOL(enable_hlt); ...@@ -100,21 +100,17 @@ EXPORT_SYMBOL(enable_hlt);
*/ */
void default_idle(void) void default_idle(void)
{ {
local_irq_enable();
if (!hlt_counter && boot_cpu_data.hlt_works_ok) { if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
current_thread_info()->status &= ~TS_POLLING; current_thread_info()->status &= ~TS_POLLING;
smp_mb__after_clear_bit(); smp_mb__after_clear_bit();
while (!need_resched()) {
local_irq_disable(); local_irq_disable();
if (!need_resched()) if (!need_resched())
safe_halt(); safe_halt(); /* enables interrupts racelessly */
else else
local_irq_enable(); local_irq_enable();
}
current_thread_info()->status |= TS_POLLING; current_thread_info()->status |= TS_POLLING;
} else { } else {
while (!need_resched()) /* loop is done by the caller */
cpu_relax(); cpu_relax();
} }
} }
...@@ -129,14 +125,7 @@ EXPORT_SYMBOL(default_idle); ...@@ -129,14 +125,7 @@ EXPORT_SYMBOL(default_idle);
*/ */
static void poll_idle (void) static void poll_idle (void)
{ {
local_irq_enable(); cpu_relax();
asm volatile(
"2:"
"testl %0, %1;"
"rep; nop;"
"je 2b;"
: : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
...@@ -257,7 +246,6 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) ...@@ -257,7 +246,6 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
static void mwait_idle(void) static void mwait_idle(void)
{ {
local_irq_enable(); local_irq_enable();
while (!need_resched())
mwait_idle_with_hints(0, 0); mwait_idle_with_hints(0, 0);
} }
......
...@@ -108,17 +108,15 @@ void exit_idle(void) ...@@ -108,17 +108,15 @@ void exit_idle(void)
*/ */
static void default_idle(void) static void default_idle(void)
{ {
local_irq_enable();
current_thread_info()->status &= ~TS_POLLING; current_thread_info()->status &= ~TS_POLLING;
smp_mb__after_clear_bit(); smp_mb__after_clear_bit();
while (!need_resched()) {
local_irq_disable(); local_irq_disable();
if (!need_resched()) if (!need_resched()) {
/* Enables interrupts one instruction before HLT.
x86 special cases this so there is no race. */
safe_halt(); safe_halt();
else } else
local_irq_enable(); local_irq_enable();
}
current_thread_info()->status |= TS_POLLING; current_thread_info()->status |= TS_POLLING;
} }
...@@ -129,16 +127,7 @@ static void default_idle(void) ...@@ -129,16 +127,7 @@ static void default_idle(void)
*/ */
static void poll_idle (void) static void poll_idle (void)
{ {
local_irq_enable(); cpu_relax();
asm volatile(
"2:"
"testl %0,%1;"
"rep; nop;"
"je 2b;"
: :
"i" (_TIF_NEED_RESCHED),
"m" (current_thread_info()->flags));
} }
void cpu_idle_wait(void) void cpu_idle_wait(void)
...@@ -257,7 +246,6 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) ...@@ -257,7 +246,6 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
static void mwait_idle(void) static void mwait_idle(void)
{ {
local_irq_enable(); local_irq_enable();
while (!need_resched())
mwait_idle_with_hints(0,0); mwait_idle_with_hints(0,0);
} }
......
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