linux-mips
[Top] [All Lists]

cpu_idle and cpu_wait

To: linux-mips@linux-mips.org
Subject: cpu_idle and cpu_wait
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Thu, 17 Nov 2005 01:19:06 +0900 (JST)
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
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

<Prev in Thread] Current Thread [Next in Thread>