summary refs log tree commit diff
path: root/arch/m68knommu/kernel/process.c
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@snapgear.com>2005-06-03 11:35:20 +1000
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-03 08:16:17 -0700
commitb05a720b374ac6af05b2fd4c70bb2c61a9f461ca (patch)
tree12de6955d12cd3c5660dd3411a50b125073688fa /arch/m68knommu/kernel/process.c
parentf4d340cf869b2b63e1043eed72aa2eab6fa2cb2c (diff)
downloadlinux-b05a720b374ac6af05b2fd4c70bb2c61a9f461ca.tar.gz
[PATCH] m68knommu: fix scheduling and race problems in idle loop
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>
Diffstat (limited to 'arch/m68knommu/kernel/process.c')
-rw-r--r--arch/m68knommu/kernel/process.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 2b6c9d32b7a6..c4a33f265dc0 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -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)