sched: Avoid double preemption in __cond_resched_*lock*()
For PREEMPT/DYNAMIC_PREEMPT the *_unlock() will already trigger a preemption, no point in then calling preempt_schedule_common() *again*. Use _cond_resched() instead, since this is a NOP for the preemptible configs while it provide a preemption point for the others. Reported-by: xuhaifeng <xuhaifeng@oppo.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/YcGnvDEYBwOiV0cR@hirez.programming.kicks-ass.net
This commit is contained in:
@@ -8218,9 +8218,7 @@ int __cond_resched_lock(spinlock_t *lock)
|
|||||||
|
|
||||||
if (spin_needbreak(lock) || resched) {
|
if (spin_needbreak(lock) || resched) {
|
||||||
spin_unlock(lock);
|
spin_unlock(lock);
|
||||||
if (resched)
|
if (!_cond_resched())
|
||||||
preempt_schedule_common();
|
|
||||||
else
|
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
ret = 1;
|
ret = 1;
|
||||||
spin_lock(lock);
|
spin_lock(lock);
|
||||||
@@ -8238,9 +8236,7 @@ int __cond_resched_rwlock_read(rwlock_t *lock)
|
|||||||
|
|
||||||
if (rwlock_needbreak(lock) || resched) {
|
if (rwlock_needbreak(lock) || resched) {
|
||||||
read_unlock(lock);
|
read_unlock(lock);
|
||||||
if (resched)
|
if (!_cond_resched())
|
||||||
preempt_schedule_common();
|
|
||||||
else
|
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
ret = 1;
|
ret = 1;
|
||||||
read_lock(lock);
|
read_lock(lock);
|
||||||
@@ -8258,9 +8254,7 @@ int __cond_resched_rwlock_write(rwlock_t *lock)
|
|||||||
|
|
||||||
if (rwlock_needbreak(lock) || resched) {
|
if (rwlock_needbreak(lock) || resched) {
|
||||||
write_unlock(lock);
|
write_unlock(lock);
|
||||||
if (resched)
|
if (!_cond_resched())
|
||||||
preempt_schedule_common();
|
|
||||||
else
|
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
ret = 1;
|
ret = 1;
|
||||||
write_lock(lock);
|
write_lock(lock);
|
||||||
|
|||||||
Reference in New Issue
Block a user