diff options
author | Jim Houston <jim.houston@ccur.com> | 2006-07-30 06:03:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-31 16:28:40 -0400 |
commit | 2d7d253548cffdce80f4e03664686e9ccb1b0ed7 (patch) | |
tree | 08771f36c2506e39f9adfc0bb09e4a574ce196dd | |
parent | 6ea24f9ad18c65cc179593b5cc2a88cdadf8cc0c (diff) |
[PATCH] fix cond_resched() fix
In cond_resched_lock() it calls __resched_legal() before dropping the spin
lock. __resched_legal() will always finds the preempt_count non-zero and
will prevent the call to __cond_resched().
The attached patch adds a parameter to __resched_legal() with the expected
preempt_count value.
Cc: Ingo Molnar <mingo@elte.hu>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | kernel/sched.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 41a571806ce0..de440b220b4c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4456,9 +4456,9 @@ asmlinkage long sys_sched_yield(void) | |||
4456 | return 0; | 4456 | return 0; |
4457 | } | 4457 | } |
4458 | 4458 | ||
4459 | static inline int __resched_legal(void) | 4459 | static inline int __resched_legal(int expected_preempt_count) |
4460 | { | 4460 | { |
4461 | if (unlikely(preempt_count())) | 4461 | if (unlikely(preempt_count() != expected_preempt_count)) |
4462 | return 0; | 4462 | return 0; |
4463 | if (unlikely(system_state != SYSTEM_RUNNING)) | 4463 | if (unlikely(system_state != SYSTEM_RUNNING)) |
4464 | return 0; | 4464 | return 0; |
@@ -4484,7 +4484,7 @@ static void __cond_resched(void) | |||
4484 | 4484 | ||
4485 | int __sched cond_resched(void) | 4485 | int __sched cond_resched(void) |
4486 | { | 4486 | { |
4487 | if (need_resched() && __resched_legal()) { | 4487 | if (need_resched() && __resched_legal(0)) { |
4488 | __cond_resched(); | 4488 | __cond_resched(); |
4489 | return 1; | 4489 | return 1; |
4490 | } | 4490 | } |
@@ -4510,7 +4510,7 @@ int cond_resched_lock(spinlock_t *lock) | |||
4510 | ret = 1; | 4510 | ret = 1; |
4511 | spin_lock(lock); | 4511 | spin_lock(lock); |
4512 | } | 4512 | } |
4513 | if (need_resched() && __resched_legal()) { | 4513 | if (need_resched() && __resched_legal(1)) { |
4514 | spin_release(&lock->dep_map, 1, _THIS_IP_); | 4514 | spin_release(&lock->dep_map, 1, _THIS_IP_); |
4515 | _raw_spin_unlock(lock); | 4515 | _raw_spin_unlock(lock); |
4516 | preempt_enable_no_resched(); | 4516 | preempt_enable_no_resched(); |
@@ -4526,7 +4526,7 @@ int __sched cond_resched_softirq(void) | |||
4526 | { | 4526 | { |
4527 | BUG_ON(!in_softirq()); | 4527 | BUG_ON(!in_softirq()); |
4528 | 4528 | ||
4529 | if (need_resched() && __resched_legal()) { | 4529 | if (need_resched() && __resched_legal(0)) { |
4530 | raw_local_irq_disable(); | 4530 | raw_local_irq_disable(); |
4531 | _local_bh_enable(); | 4531 | _local_bh_enable(); |
4532 | raw_local_irq_enable(); | 4532 | raw_local_irq_enable(); |