summaryrefslogtreecommitdiffstats
path: root/arch/m68knommu
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@snapgear.com>2005-06-03 03:35:20 +0200
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-03 17:16:17 +0200
commitb05a720b374ac6af05b2fd4c70bb2c61a9f461ca (patch)
tree12de6955d12cd3c5660dd3411a50b125073688fa /arch/m68knommu
parent[PATCH] USB: resolve Zaurus problem (diff)
downloadlinux-b05a720b374ac6af05b2fd4c70bb2c61a9f461ca.tar.xz
linux-b05a720b374ac6af05b2fd4c70bb2c61a9f461ca.zip
[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')
-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)