[PATCH] m68knommu: fix scheduling and race problems in idle loop
Greg Ungerer [Fri, 3 Jun 2005 01:35:20 +0000 (11:35 +1000)]
Re-work the m68knommu specific idle code according to suggestions
from Nick Piggin <nickpiggin@yahoo.com.au>.

A couple of rules that we need to follow:

1. Preempt should now disabled over idle routines. Should only be enabled
to call schedule() then disabled again.

3. When cpu_idle finds (need_resched() == 'true'), it should call schedule().
It should not call schedule() otherwise.

Also fix interrupt locking around the need_resched() and cpu stop state
so that there is no race condition.

Signed-off-by: Greg Ungerer <gerg@snapgear.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

arch/m68knommu/kernel/process.c

index 2b6c9d3..c4a33f2 100644 (file)
@@ -45,11 +45,13 @@ asmlinkage void ret_from_fork(void);
  */
 void default_idle(void)
 {
-       while(1) {
-               if (need_resched())
-                       __asm__("stop #0x2000" : : : "cc");
-               schedule();
+       local_irq_disable();
+       while (!need_resched()) {
+               /* This stop will re-enable interrupts */
+               __asm__("stop #0x2000" : : : "cc");
+               local_irq_disable();
        }
+       local_irq_enable();
 }
 
 void (*idle)(void) = default_idle;
@@ -63,7 +65,12 @@ void (*idle)(void) = default_idle;
 void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
-       idle();
+       while (1) {
+               idle();
+               preempt_enable_no_resched();
+               schedule();
+               preempt_disable();
+       }
 }
 
 void machine_restart(char * __unused)