Looking at recent change in cpu_idle(), I find an another potential
problem with cpu_wait (WAIT instruction).
48 ATTRIB_NORET void cpu_idle(void)
49 {
50 /* endless idle loop with no priority at all */
51 while (1) {
52 while (!need_resched())
53 if (cpu_wait)
54 (*cpu_wait)();
55 preempt_enable_no_resched();
56 schedule();
57 preempt_disable();
58 }
59 }
If an interrupt raised on line 53 and the interrupt handler woke a
sleeping thread up, the thread becomes runnable and current thread
(idle thread) is marked as NEED_RESCHED.
Since preemption is disabled, the interrupt handler just return to
current thread (idle thread) without rescheduling. The idle thread
then call cpu_wait() and execute WAIT instruction (or something
similer). The CPU will stops until next interrupt. Then the idle
task checks need_resched() and finally calls schedule(). Therefore,
wakeup-resume latency will be nearly one TICK on worst case!
If this analysis was correct, how to fix this?
Removing above preempt_enable_no_resched/preempt_disable pair would
fix it for preemptive kernel, but no point for non-preemptive kernel.
Replacing them with local_irq_enable/local_irq_disable would fix it
for both kernel, but there is an question:
The CPU can surely exit from the WAIT instruction by interrupt
even if interrupts disabled?
I know the answer is yes on TX49. Any external (or counter) interrupt
SIGNAL can break the WAIT instruction. How about others?
---
Atsushi Nemoto
|