Skip to content

Commit a15da49

Browse files
Andi KleenAndi Kleen
authored andcommitted
[PATCH] Fix idle notifiers
Previously exit_idle would be called more often than enter_idle Now instead of using complicated tests just keep track of it using the per CPU variable as a flip flop. I moved the idle state into the PDA to make the access more efficient. Original bug report and an initial patch from Stephane Eranian, but redone by AK. Cc: Stephane Eranian <eranian@hpl.hp.com> Signed-off-by: Andi Kleen <ak@suse.de>
1 parent 1c9c0a6 commit a15da49

File tree

2 files changed

+11
-7
lines changed

2 files changed

+11
-7
lines changed

arch/x86_64/kernel/process.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,25 +80,25 @@ void idle_notifier_unregister(struct notifier_block *n)
8080
}
8181
EXPORT_SYMBOL(idle_notifier_unregister);
8282

83-
enum idle_state { CPU_IDLE, CPU_NOT_IDLE };
84-
static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
85-
8683
void enter_idle(void)
8784
{
88-
__get_cpu_var(idle_state) = CPU_IDLE;
85+
write_pda(isidle, 1);
8986
atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
9087
}
9188

9289
static void __exit_idle(void)
9390
{
94-
__get_cpu_var(idle_state) = CPU_NOT_IDLE;
91+
if (read_pda(isidle) == 0)
92+
return;
93+
write_pda(isidle, 0);
9594
atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
9695
}
9796

9897
/* Called from interrupts to signify idle end */
9998
void exit_idle(void)
10099
{
101-
if (current->pid | read_pda(irqcount))
100+
/* idle loop has pid 0 */
101+
if (current->pid)
102102
return;
103103
__exit_idle();
104104
}
@@ -220,6 +220,9 @@ void cpu_idle (void)
220220
play_dead();
221221
enter_idle();
222222
idle();
223+
/* In many cases the interrupt that ended idle
224+
has already called exit_idle. But some idle
225+
loops can be woken up without interrupt. */
223226
__exit_idle();
224227
}
225228

include/asm-x86_64/pda.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ struct x8664_pda {
2525
int nodenumber; /* number of current node */
2626
unsigned int __softirq_pending;
2727
unsigned int __nmi_count; /* number of NMI on this CPUs */
28-
int mmu_state;
28+
short mmu_state;
29+
short isidle;
2930
struct mm_struct *active_mm;
3031
unsigned apic_timer_irqs;
3132
} ____cacheline_aligned_in_smp;

0 commit comments

Comments
 (0)