Diagnosis from Christian Vogel <vogel@skunk.physik.uni-erlangen.de>
cpu_idle() tests pm_idle() just once then falls into the
while (!need_resched())
idle();
loop.
Problem is, that loop never terminates (need_resched() always returns false
on preemptive kernels).
The other problem is that ACPI updates pm_idle _after_ cpu_idle() has taken a
local copy. So we always call default_idle(), even when pm_idle is pointing
at a new idle handler.
So fix it to pick up changed values of pm_idle() each time around the inner
loop.
{
/* endless idle loop with no priority at all */
while (1) {
- void (*idle)(void) = pm_idle;
- if (!idle)
- idle = default_idle;
- irq_stat[smp_processor_id()].idle_timestamp = jiffies;
- while (!need_resched())
+ while (!need_resched()) {
+ void (*idle)(void) = pm_idle;
+
+ if (!idle)
+ idle = default_idle;
+
+ irq_stat[smp_processor_id()].idle_timestamp = jiffies;
idle();
+ }
schedule();
}
}