diff options
author | Greg Ungerer <gerg@snapgear.com> | 2005-06-02 21:35:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-03 11:16:17 -0400 |
commit | b05a720b374ac6af05b2fd4c70bb2c61a9f461ca (patch) | |
tree | 12de6955d12cd3c5660dd3411a50b125073688fa | |
parent | f4d340cf869b2b63e1043eed72aa2eab6fa2cb2c (diff) |
[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>
-rw-r--r-- | arch/m68knommu/kernel/process.c | 17 |
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); | |||
45 | */ | 45 | */ |
46 | void default_idle(void) | 46 | void default_idle(void) |
47 | { | 47 | { |
48 | while(1) { | 48 | local_irq_disable(); |
49 | if (need_resched()) | 49 | while (!need_resched()) { |
50 | __asm__("stop #0x2000" : : : "cc"); | 50 | /* This stop will re-enable interrupts */ |
51 | schedule(); | 51 | __asm__("stop #0x2000" : : : "cc"); |
52 | local_irq_disable(); | ||
52 | } | 53 | } |
54 | local_irq_enable(); | ||
53 | } | 55 | } |
54 | 56 | ||
55 | void (*idle)(void) = default_idle; | 57 | void (*idle)(void) = default_idle; |
@@ -63,7 +65,12 @@ void (*idle)(void) = default_idle; | |||
63 | void cpu_idle(void) | 65 | void cpu_idle(void) |
64 | { | 66 | { |
65 | /* endless idle loop with no priority at all */ | 67 | /* endless idle loop with no priority at all */ |
66 | idle(); | 68 | while (1) { |
69 | idle(); | ||
70 | preempt_enable_no_resched(); | ||
71 | schedule(); | ||
72 | preempt_disable(); | ||
73 | } | ||
67 | } | 74 | } |
68 | 75 | ||
69 | void machine_restart(char * __unused) | 76 | void machine_restart(char * __unused) |