Re: [PATCH 2/2] locking/rwsem: Use a return variable in rwsem_spin_on_owner()

Ingo Molnar
2015-04-09T07:53:17Z

* Jason Low <jason.low2@hp.com> wrote:

> On Thu, 2015-04-09 at 07:37 +0200, Ingo Molnar wrote:
>
> > The 'break' path does not seem to be equivalent, we used to do:
> >
> > > - rcu_read_unlock();
> > > - return false;
> >
> > and now we'll do:
> >
> > > + ret = false;
> > ...
> > > + if (!READ_ONCE(sem->owner)) {
> > > + long count = READ_ONCE(sem->count);
> >
> > it's harmless (we do one more round of checking), but that's not an
> > equivalent transformation and slows down the preemption trigger a
> > (tiny) bit, because the chance that we actually catch the lock when
> > breaking out early is vanishingly small. (It might in fact do the
> > wrong thing in returning true if need_resched() is set and we've
> > switched owners in that small window.)
> >
> > Given how dissimilar the return path is in this case, I'm not sure
> > it's worth sharing it. This might be one of the few cases where
> > separate return statements is the better solution.
>
> I also preferred the multiple returns for the rwsem variant to avoid
> needing to check sem->owner when it should go to slowpath, as you
> mentioned.
>
> Now that I think of it though, if we want to have just one return path,
> we can still do that if we add an "out" label.

That's the usual pattern we use, but:

> - /* abort spinning when need_resched or owner is not running */
> + /* Abort spinning when need_resched or owner is not running. */
> if (!owner->on_cpu || need_resched()) {
> rcu_read_unlock();
> - return false;
> + ret = false;
> + goto out;
> }

The point is to generally unify the 'out' paths - i.e. to merge it
with the rcu_read_unlock() as well, so that we have really simple
gotos and only a single exit path.

That's not really doable here without extra overhead AFAICS, so I'd
suggest we leave it alone ...

I have applied your other patch.

Thanks,

Ingo