locking/mutex: Don't hog RCU read lock while optimistically spinning

There's no reason to hold an RCU read lock the entire time while
optimistically spinning for a mutex lock. This can needlessly lengthen
RCU grace periods and slow down synchronize_rcu() when it doesn't brute
force the RCU grace period via rcupdate.rcu_expedited=1.

Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
Signed-off-by: Ruchit <ruchitmarathe@gmail.com>
fourteen
Sultan Alsawaf 5 years ago committed by Jenna
parent 1809f0e739
commit adad23165c
  1. 25
      kernel/locking/mutex.c

@ -426,21 +426,31 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner,
{
bool ret = true;
rcu_read_lock();
while (__mutex_owner(lock) == owner) {
for (;;) {
unsigned int cpu;
bool same_owner;
/*
* Ensure we emit the owner->on_cpu, dereference _after_
* checking lock->owner still matches owner. If that fails,
* Ensure lock->owner still matches owner. If that fails,
* owner might point to freed memory. If it still matches,
* the rcu_read_lock() ensures the memory stays valid.
*/
barrier();
rcu_read_lock();
same_owner = __mutex_owner(lock) == owner;
if (same_owner) {
ret = owner->on_cpu;
if (ret)
cpu = task_cpu(owner);
}
rcu_read_unlock();
if (!ret || !same_owner)
break;
/*
* Use vcpu_is_preempted to detect lock holder preemption issue.
*/
if (!owner->on_cpu || need_resched() ||
vcpu_is_preempted(task_cpu(owner))) {
if (need_resched() || vcpu_is_preempted(cpu)) {
ret = false;
break;
}
@ -452,7 +462,6 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner,
cpu_relax();
}
rcu_read_unlock();
return ret;
}

Loading…
Cancel
Save