aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/process.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-12-06 20:14:03 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:03 -0500
commit72690a21188586022a9e65cb6f1cc8845167555a (patch)
tree6ddd4a04307867128100dbd1906eec5a89f88662 /arch/i386/kernel/process.c
parent63cb683c6ed56a420ba60df6a5b206a44e3f85fe (diff)
[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: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r--arch/i386/kernel/process.c30
1 files changed, 9 insertions, 21 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 8749b10d3805..8f42659ef9d2 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -100,22 +100,18 @@ EXPORT_SYMBOL(enable_hlt);
100 */ 100 */
101void default_idle(void) 101void default_idle(void)
102{ 102{
103 local_irq_enable();
104
105 if (!hlt_counter && boot_cpu_data.hlt_works_ok) { 103 if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
106 current_thread_info()->status &= ~TS_POLLING; 104 current_thread_info()->status &= ~TS_POLLING;
107 smp_mb__after_clear_bit(); 105 smp_mb__after_clear_bit();
108 while (!need_resched()) { 106 local_irq_disable();
109 local_irq_disable(); 107 if (!need_resched())
110 if (!need_resched()) 108 safe_halt(); /* enables interrupts racelessly */
111 safe_halt(); 109 else
112 else 110 local_irq_enable();
113 local_irq_enable();
114 }
115 current_thread_info()->status |= TS_POLLING; 111 current_thread_info()->status |= TS_POLLING;
116 } else { 112 } else {
117 while (!need_resched()) 113 /* loop is done by the caller */
118 cpu_relax(); 114 cpu_relax();
119 } 115 }
120} 116}
121#ifdef CONFIG_APM_MODULE 117#ifdef CONFIG_APM_MODULE
@@ -129,14 +125,7 @@ EXPORT_SYMBOL(default_idle);
129 */ 125 */
130static void poll_idle (void) 126static void poll_idle (void)
131{ 127{
132 local_irq_enable(); 128 cpu_relax();
133
134 asm volatile(
135 "2:"
136 "testl %0, %1;"
137 "rep; nop;"
138 "je 2b;"
139 : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags));
140} 129}
141 130
142#ifdef CONFIG_HOTPLUG_CPU 131#ifdef CONFIG_HOTPLUG_CPU
@@ -257,8 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
257static void mwait_idle(void) 246static void mwait_idle(void)
258{ 247{
259 local_irq_enable(); 248 local_irq_enable();
260 while (!need_resched()) 249 mwait_idle_with_hints(0, 0);
261 mwait_idle_with_hints(0, 0);
262} 250}
263 251
264void __devinit select_idle_routine(const struct cpuinfo_x86 *c) 252void __devinit select_idle_routine(const struct cpuinfo_x86 *c)