Skip to content

Commit

Permalink
[PATCH] x86: Don't use nested idle loops
Browse files Browse the repository at this point in the history
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: Andi Kleen <ak@suse.de>
  • Loading branch information
Andi Kleen authored and Andi Kleen committed Dec 7, 2006
1 parent 63cb683 commit 72690a2
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 42 deletions.
30 changes: 9 additions & 21 deletions arch/i386/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,18 @@ EXPORT_SYMBOL(enable_hlt);
*/
void default_idle(void)
{
local_irq_enable();

if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
current_thread_info()->status &= ~TS_POLLING;
smp_mb__after_clear_bit();
while (!need_resched()) {
local_irq_disable();
if (!need_resched())
safe_halt();
else
local_irq_enable();
}
local_irq_disable();
if (!need_resched())
safe_halt(); /* enables interrupts racelessly */
else
local_irq_enable();
current_thread_info()->status |= TS_POLLING;
} else {
while (!need_resched())
cpu_relax();
/* loop is done by the caller */
cpu_relax();
}
}
#ifdef CONFIG_APM_MODULE
Expand All @@ -129,14 +125,7 @@ EXPORT_SYMBOL(default_idle);
*/
static void poll_idle (void)
{
local_irq_enable();

asm volatile(
"2:"
"testl %0, %1;"
"rep; nop;"
"je 2b;"
: : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
cpu_relax();
}

#ifdef CONFIG_HOTPLUG_CPU
Expand Down Expand Up @@ -257,8 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
static void mwait_idle(void)
{
local_irq_enable();
while (!need_resched())
mwait_idle_with_hints(0, 0);
mwait_idle_with_hints(0, 0);
}

void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
Expand Down
30 changes: 9 additions & 21 deletions arch/x86_64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,15 @@ void exit_idle(void)
*/
static void default_idle(void)
{
local_irq_enable();

current_thread_info()->status &= ~TS_POLLING;
smp_mb__after_clear_bit();
while (!need_resched()) {
local_irq_disable();
if (!need_resched())
safe_halt();
else
local_irq_enable();
}
local_irq_disable();
if (!need_resched()) {
/* Enables interrupts one instruction before HLT.
x86 special cases this so there is no race. */
safe_halt();
} else
local_irq_enable();
current_thread_info()->status |= TS_POLLING;
}

Expand All @@ -129,16 +127,7 @@ static void default_idle(void)
*/
static void poll_idle (void)
{
local_irq_enable();

asm volatile(
"2:"
"testl %0,%1;"
"rep; nop;"
"je 2b;"
: :
"i" (_TIF_NEED_RESCHED),
"m" (current_thread_info()->flags));
cpu_relax();
}

void cpu_idle_wait(void)
Expand Down Expand Up @@ -257,8 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
static void mwait_idle(void)
{
local_irq_enable();
while (!need_resched())
mwait_idle_with_hints(0,0);
mwait_idle_with_hints(0,0);
}

void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
Expand Down

0 comments on commit 72690a2

Please sign in to comment.