Re: [PATCH 1/2] locking/mutex: Don't hog RCU read lock while optimistically spinning

From: Will Deacon
Date: Mon Sep 07 2020 - 12:21:06 EST


On Fri, Aug 07, 2020 at 12:16:35PM -0700, Sultan Alsawaf wrote:
> From: Sultan Alsawaf <sultan@xxxxxxxxxxxxxxx>
>
> 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.

Would be good to demonstrate this with numbers if you can.

> Signed-off-by: Sultan Alsawaf <sultan@xxxxxxxxxxxxxxx>
> ---
> kernel/locking/mutex.c | 25 +++++++++++++++++--------
> 1 file changed, 17 insertions(+), 8 deletions(-)
>
> diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
> index 5352ce50a97e..cc5676712458 100644
> --- a/kernel/locking/mutex.c
> +++ b/kernel/locking/mutex.c
> @@ -552,21 +552,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();

Are you sure this doesn't break the ww mutex spinning? That thing also goes
and looks at the owner, but now it's called outside of the read-side
critical section.

Will