sched/preempt: Fix cond_resched_lock() and cond_resched_softirq()
These functions check should_resched() before unlocking spinlock/bh-enable:
preempt_count always non-zero => should_resched() always returns false.
cond_resched_lock() worked iff spin_needbreak is set.
This patch adds argument "preempt_offset" to should_resched().
preempt_count offset constants for that:
PREEMPT_DISABLE_OFFSET - offset after preempt_disable()
PREEMPT_LOCK_OFFSET - offset after spin_lock()
SOFTIRQ_DISABLE_OFFSET - offset after local_bh_distable()
SOFTIRQ_LOCK_OFFSET - offset after spin_lock_bh()
Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Graf <agraf@suse.de>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: bdb4380658
("sched: Extract the basic add/sub preempt_count modifiers")
Link: http://lkml.kernel.org/r/20150715095204.12246.98268.stgit@buzz
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:

committed by
Ingo Molnar

parent
c56dadf397
commit
fe32d3cd5e
@@ -4496,7 +4496,7 @@ SYSCALL_DEFINE0(sched_yield)
|
||||
|
||||
int __sched _cond_resched(void)
|
||||
{
|
||||
if (should_resched()) {
|
||||
if (should_resched(0)) {
|
||||
preempt_schedule_common();
|
||||
return 1;
|
||||
}
|
||||
@@ -4514,7 +4514,7 @@ EXPORT_SYMBOL(_cond_resched);
|
||||
*/
|
||||
int __cond_resched_lock(spinlock_t *lock)
|
||||
{
|
||||
int resched = should_resched();
|
||||
int resched = should_resched(PREEMPT_LOCK_OFFSET);
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(lock);
|
||||
@@ -4536,7 +4536,7 @@ int __sched __cond_resched_softirq(void)
|
||||
{
|
||||
BUG_ON(!in_softirq());
|
||||
|
||||
if (should_resched()) {
|
||||
if (should_resched(SOFTIRQ_DISABLE_OFFSET)) {
|
||||
local_bh_enable();
|
||||
preempt_schedule_common();
|
||||
local_bh_disable();
|
||||
|
Reference in New Issue
Block a user