From: Peter Hurley <peter@hurleysoftware.com>
To: Waiman Long <waiman.long@hpe.com>
Cc: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
linux-kernel@vger.kernel.org, Davidlohr Bueso <dave@stgolabs.net>,
Jason Low <jason.low2@hp.com>, Dave Chinner <david@fromorbit.com>,
Scott J Norton <scott.norton@hpe.com>,
Douglas Hatch <doug.hatch@hpe.com>
Subject: Re: [PATCH v2] locking/rwsem: Add reader-owned state to the owner field
Date: Thu, 12 May 2016 14:27:37 -0700 [thread overview]
Message-ID: <5734F549.7080009@hurleysoftware.com> (raw)
In-Reply-To: <5734E45A.4030904@hpe.com>
On 05/12/2016 01:15 PM, Waiman Long wrote:
> On 05/11/2016 06:04 PM, Peter Hurley wrote:
[...]
>>
>>> @@ -328,8 +329,6 @@ done:
>>> static noinline
>>> bool rwsem_spin_on_owner(struct rw_semaphore *sem, struct task_struct *owner)
>>> {
>>> - long count;
>>> -
>>> rcu_read_lock();
>>> while (sem->owner == owner) {
>>> /*
>>> @@ -350,16 +349,11 @@ bool rwsem_spin_on_owner(struct rw_semaphore *sem, struct task_struct *owner)
>>> }
>>> rcu_read_unlock();
>>>
>>> - if (READ_ONCE(sem->owner))
>>> - return true; /* new owner, continue spinning */
>>> -
>>> /*
>>> - * When the owner is not set, the lock could be free or
>>> - * held by readers. Check the counter to verify the
>>> - * state.
>>> + * If there is a new owner or the owner is not set, we continue
>>> + * spinning.
>>> */
>>> - count = READ_ONCE(sem->count);
>>> - return (count == 0 || count == RWSEM_WAITING_BIAS);
>>> + return !rwsem_is_reader_owned(READ_ONCE(sem->owner));
>> It doesn't make sense to force reload sem->owner here; if sem->owner
>> is not being reloaded then the loop above will execute forever.
>
> I agree that we don't actually need to use READ_ONCE() here for sem->owner as the barrier() call will force the reloading. It is more like a habit to use it for public variable or we will have to think a bit harder to make sure that we are doing the right thing.
I look at that code and I think "what am I missing that it needs to reload at exit"
Extra cruft is just as misleading.
What matters while spinning on owner is that the reload is forced as part of the
loop, not at exit time. The whole point of rwsem_spin_on_owner() is to spin
until the owner _changes_; there's no need to get a more recent owner value
than the one that caused the loop to break.
>> Arguably, this check should be bumped out to the optimistic spin and
>> reload/check the owner there?
>>
>> Or better yet; don't pass the owner in as a parameter at all, but
>> instead snapshot the owner and check its ownership on entry.
>
> That will make the main optimistic spinning loop more complex.
??
Simpler.
while (rwsem_spin_on_owner(sem)) {
if (rwsem_try_write_lock_unqueued(sem)) {
taken = true;
break;
}
if (!sem->owner && (need_resched() || rt_task(current)))
break;
cpu_relax_lowlatency();
}
bool rwsem_spin_on_owner(struct rw_semaphore *sem)
{
struct task_struct *owner = READ_ONCE(sem->owner);
if (!rwsem_is_writer_owned(owner))
return false;
rcu_read_lock();
while (sem->owner == owner) {
....
}
rcu_read_unlock();
return !rwsem_is_reader_owned(sem->owner);
}
>>
>> Because see below...
>>
>>> }
>>>
>>> static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
>>> @@ -378,7 +372,8 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
>>>
>>> while (true) {
>>> owner = READ_ONCE(sem->owner);
>>> - if (owner&& !rwsem_spin_on_owner(sem, owner))
>>> + if (rwsem_is_writer_owned(owner)&&
>>> + !rwsem_spin_on_owner(sem, owner))
>>> break;
>>>
>>> /* wait_lock will be acquired if write_lock is obtained */
>>> @@ -391,9 +386,11 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
>>> * When there's no owner, we might have preempted between the
>>> * owner acquiring the lock and setting the owner field. If
>>> * we're an RT task that will live-lock because we won't let
>>> - * the owner complete.
>>> + * the owner complete. We also quit if the lock is owned by
>>> + * readers.
>>> */
>>> - if (!owner&& (need_resched() || rt_task(current)))
>>> + if (rwsem_is_reader_owned(owner) ||
>>> + (!owner&& (need_resched() || rt_task(current))))
>> This is using the stale owner value that was cached before spinning on the owner;
>> That can't be right.
>
> The code is going to loop back and reload the new owner value anyway. It is just a bit of additional latency. I will move the is_reader check up after loading sem->owner to clear any confusion.
Well, why do it at all then? Just before attempting the lock, rwsem_spin_on_owner()
determined that the owner was not a reader. If a reader became the new owner after
that, the loop will discover that the lock is no longer writer owned anyway.
Either way, the check here should be to sem->owner (ie., like I wrote above),
but there's no need to force reload here either.
Regards,
Peter Hurley
next prev parent reply other threads:[~2016-05-12 21:27 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-07 0:20 [PATCH v2] locking/rwsem: Add reader-owned state to the owner field Waiman Long
2016-05-07 4:56 ` Ingo Molnar
2016-05-08 3:04 ` Waiman Long
2016-05-09 8:27 ` Peter Zijlstra
2016-05-10 2:24 ` Waiman Long
2016-05-10 7:02 ` Peter Zijlstra
2016-05-09 18:44 ` Jason Low
2016-05-10 13:03 ` Davidlohr Bueso
2016-05-11 22:04 ` Peter Hurley
2016-05-12 20:15 ` Waiman Long
2016-05-12 21:27 ` Peter Hurley [this message]
2016-05-12 23:13 ` Waiman Long
2016-05-13 15:07 ` Peter Zijlstra
2016-05-13 17:58 ` Peter Hurley
2016-05-15 14:47 ` Waiman Long
2016-05-16 11:09 ` Peter Zijlstra
2016-05-16 12:17 ` Paul E. McKenney
2016-05-16 14:17 ` Peter Hurley
2016-05-16 17:22 ` Paul E. McKenney
2016-05-17 19:46 ` Peter Hurley
2016-05-17 19:53 ` Peter Hurley
2016-05-16 17:50 ` Peter Zijlstra
2016-05-17 19:15 ` Peter Hurley
2016-05-17 19:46 ` Paul E. McKenney
2016-05-18 11:05 ` Peter Zijlstra
2016-05-18 15:56 ` Waiman Long
2016-05-18 17:28 ` Paul E. McKenney
2016-05-18 17:26 ` Paul E. McKenney
2016-05-19 9:00 ` Peter Zijlstra
2016-05-19 13:43 ` Paul E. McKenney
2016-05-19 1:37 ` Dave Chinner
2016-05-19 8:32 ` Peter Zijlstra
2016-05-20 22:56 ` Waiman Long
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5734F549.7080009@hurleysoftware.com \
--to=peter@hurleysoftware.com \
--cc=dave@stgolabs.net \
--cc=david@fromorbit.com \
--cc=doug.hatch@hpe.com \
--cc=jason.low2@hp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=scott.norton@hpe.com \
--cc=waiman.long@hpe.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).