From 603c9c59a5f5849a2b961fc378929b9d5efda09c Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Sat, 26 Dec 2020 12:55:02 -0800 Subject: [PATCH] locking/rwsem: 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 rwsem. 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 Signed-off-by: Ruchit --- kernel/locking/rwsem-xadd.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 350861f0da16..8917e6ceb3d0 100755 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -400,32 +400,36 @@ static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem) { struct task_struct *owner = READ_ONCE(sem->owner); - if (!is_rwsem_owner_spinnable(owner)) + if (!owner || !is_rwsem_owner_spinnable(owner)) return false; - rcu_read_lock(); - while (owner && (READ_ONCE(sem->owner) == owner)) { + while (true) { + bool on_cpu, same_owner; + /* - * Ensure we emit the owner->on_cpu, dereference _after_ - * checking sem->owner still matches owner, if that fails, + * Ensure sem->owner still matches owner. If that fails, * owner might point to free()d memory, if it still matches, * the rcu_read_lock() ensures the memory stays valid. */ - barrier(); + rcu_read_lock(); + same_owner = sem->owner == owner; + if (same_owner) + on_cpu = owner->on_cpu && + !vcpu_is_preempted(task_cpu(owner)); + rcu_read_unlock(); + + if (!same_owner) + break; /* * abort spinning when need_resched or owner is not running or * owner's cpu is preempted. */ - if (!owner->on_cpu || need_resched() || - vcpu_is_preempted(task_cpu(owner))) { - rcu_read_unlock(); + if (!on_cpu || need_resched()) return false; - } cpu_relax(); } - rcu_read_unlock(); /* * If there is a new owner or the owner is not set, we continue