Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1311370 > unrolled thread
| Started by | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| First post | 2016-01-18 09:30 +0100 |
| Last post | 2016-01-26 23:10 +0100 |
| Articles | 14 — 5 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Herbert Xu <herbert@gondor.apana.org.au> - 2016-01-18 09:30 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-01-18 16:50 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Boqun Feng <boqun.feng@gmail.com> - 2016-01-26 18:00 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Peter Zijlstra <peterz@infradead.org> - 2016-01-26 18:30 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Linus Torvalds <torvalds@linux-foundation.org> - 2016-01-26 20:50 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-01-26 23:10 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Linus Torvalds <torvalds@linux-foundation.org> - 2016-01-26 23:20 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Linus Torvalds <torvalds@linux-foundation.org> - 2016-01-26 23:40 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-01-27 00:30 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Linus Torvalds <torvalds@linux-foundation.org> - 2016-01-27 00:50 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-01-27 02:00 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Boqun Feng <boqun.feng@gmail.com> - 2016-01-27 03:10 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h Peter Zijlstra <peterz@infradead.org> - 2016-01-27 09:00 +0100
Re: [v3,11/41] mips: reuse asm-generic/barrier.h "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> - 2016-01-26 23:10 +0100
| From | Herbert Xu <herbert@gondor.apana.org.au> |
|---|---|
| Date | 2016-01-18 09:30 +0100 |
| Subject | Re: [v3,11/41] mips: reuse asm-generic/barrier.h |
| Message-ID | <qSdmi-6qu-9@gated-at.bofh.it> |
Paul E. McKenney <paulmck@linux.vnet.ibm.com> wrote: > > You could use SYNC_ACQUIRE() to implement read_barrier_depends() and > smp_read_barrier_depends(), but SYNC_RMB probably does not suffice. > The reason for this is that smp_read_barrier_depends() must order the > pointer load against any subsequent read or write through a dereference > of that pointer. For example: > > p = READ_ONCE(gp); > smp_rmb(); > r1 = p->a; /* ordered by smp_rmb(). */ > p->b = 42; /* NOT ordered by smp_rmb(), BUG!!! */ > r2 = x; /* ordered by smp_rmb(), but doesn't need to be. */ > > In contrast: > > p = READ_ONCE(gp); > smp_read_barrier_depends(); > r1 = p->a; /* ordered by smp_read_barrier_depends(). */ > p->b = 42; /* ordered by smp_read_barrier_depends(). */ > r2 = x; /* not ordered by smp_read_barrier_depends(), which is OK. */ > > Again, if your hardware maintains local ordering for address > and data dependencies, you can have read_barrier_depends() and > smp_read_barrier_depends() be no-ops like they are for most > architectures. > > Does that help? This is crazy! smp_rmb started out being strictly stronger than smp_read_barrier_depends, when did this stop being the case? -- Email: Herbert Xu <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[toc] | [next] | [standalone]
| From | "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-18 16:50 +0100 |
| Message-ID | <qSke6-2DG-11@gated-at.bofh.it> |
| In reply to | #1311370 |
On Mon, Jan 18, 2016 at 04:19:29PM +0800, Herbert Xu wrote: > Paul E. McKenney <paulmck@linux.vnet.ibm.com> wrote: > > > > You could use SYNC_ACQUIRE() to implement read_barrier_depends() and > > smp_read_barrier_depends(), but SYNC_RMB probably does not suffice. > > The reason for this is that smp_read_barrier_depends() must order the > > pointer load against any subsequent read or write through a dereference > > of that pointer. For example: > > > > p = READ_ONCE(gp); > > smp_rmb(); > > r1 = p->a; /* ordered by smp_rmb(). */ > > p->b = 42; /* NOT ordered by smp_rmb(), BUG!!! */ > > r2 = x; /* ordered by smp_rmb(), but doesn't need to be. */ > > > > In contrast: > > > > p = READ_ONCE(gp); > > smp_read_barrier_depends(); > > r1 = p->a; /* ordered by smp_read_barrier_depends(). */ > > p->b = 42; /* ordered by smp_read_barrier_depends(). */ > > r2 = x; /* not ordered by smp_read_barrier_depends(), which is OK. */ > > > > Again, if your hardware maintains local ordering for address > > and data dependencies, you can have read_barrier_depends() and > > smp_read_barrier_depends() be no-ops like they are for most > > architectures. > > > > Does that help? > > This is crazy! smp_rmb started out being strictly stronger than > smp_read_barrier_depends, when did this stop being the case? Hello, Herbert! It is true that most Linux kernel code relies only on the read-read properties of dependencies, but the read-write properties are useful. Admittedly relatively rarely, but useful. The better comparison for smp_read_barrier_depends(), especially in its rcu_dereference*() form, is smp_load_acquire(). Thanx, Paul
[toc] | [prev] | [next] | [standalone]
| From | Boqun Feng <boqun.feng@gmail.com> |
|---|---|
| Date | 2016-01-26 18:00 +0100 |
| Message-ID | <qVf8f-6St-27@gated-at.bofh.it> |
| In reply to | #1311621 |
[Multipart message — attachments visible in raw view] — view raw
Hi Paul, On Mon, Jan 18, 2016 at 07:46:29AM -0800, Paul E. McKenney wrote: > On Mon, Jan 18, 2016 at 04:19:29PM +0800, Herbert Xu wrote: > > Paul E. McKenney <paulmck@linux.vnet.ibm.com> wrote: > > > > > > You could use SYNC_ACQUIRE() to implement read_barrier_depends() and > > > smp_read_barrier_depends(), but SYNC_RMB probably does not suffice. > > > The reason for this is that smp_read_barrier_depends() must order the > > > pointer load against any subsequent read or write through a dereference > > > of that pointer. For example: > > > > > > p = READ_ONCE(gp); > > > smp_rmb(); > > > r1 = p->a; /* ordered by smp_rmb(). */ > > > p->b = 42; /* NOT ordered by smp_rmb(), BUG!!! */ > > > r2 = x; /* ordered by smp_rmb(), but doesn't need to be. */ > > > > > > In contrast: > > > > > > p = READ_ONCE(gp); > > > smp_read_barrier_depends(); > > > r1 = p->a; /* ordered by smp_read_barrier_depends(). */ > > > p->b = 42; /* ordered by smp_read_barrier_depends(). */ > > > r2 = x; /* not ordered by smp_read_barrier_depends(), which is OK. */ > > > > > > Again, if your hardware maintains local ordering for address > > > and data dependencies, you can have read_barrier_depends() and > > > smp_read_barrier_depends() be no-ops like they are for most > > > architectures. > > > > > > Does that help? > > > > This is crazy! smp_rmb started out being strictly stronger than > > smp_read_barrier_depends, when did this stop being the case? > > Hello, Herbert! > > It is true that most Linux kernel code relies only on the read-read > properties of dependencies, but the read-write properties are useful. > Admittedly relatively rarely, but useful. > > The better comparison for smp_read_barrier_depends(), especially in > its rcu_dereference*() form, is smp_load_acquire(). > Confused.. I recall that last time you and Linus came into a conclusion that even on Alpha, a barrier for read->write with data dependency is unnecessary: http://article.gmane.org/gmane.linux.kernel/2077661 And in an earlier mail of that thread, Linus made his point that smp_read_barrier_depends() should only be used to order read->read. So right now, are we going to extend the semantics of smp_read_barrier_depends()? Can we just make smp_read_barrier_depends() still only work for read->read, and assume all the architectures won't reorder read->write with data dependency, so that the code above having a smp_rmb() also works? Regards, Boqun
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2016-01-26 18:30 +0100 |
| Message-ID | <qVfBh-7mT-23@gated-at.bofh.it> |
| In reply to | #1318145 |
On Wed, Jan 27, 2016 at 12:52:07AM +0800, Boqun Feng wrote: > I recall that last time you and Linus came into a conclusion that even > on Alpha, a barrier for read->write with data dependency is unnecessary: > > http://article.gmane.org/gmane.linux.kernel/2077661 > > And in an earlier mail of that thread, Linus made his point that > smp_read_barrier_depends() should only be used to order read->read. > > So right now, are we going to extend the semantics of > smp_read_barrier_depends()? Can we just make smp_read_barrier_depends() > still only work for read->read, and assume all the architectures won't > reorder read->write with data dependency, so that the code above having > a smp_rmb() also works? That discussions was about control dependencies. So writes that _depend_ on a prior read having an explicit value. So something like: struct foo *x = READ_ONCE(*ptr); smp_read_barrier_depends() if (x->val == 5) x->bar = 5; In that case, the load of x->val must be complete and its value determined _before_ the store to x->bar can happen. This is distinct from: struct foo *x = READ_ONCE(*ptr); smp_read_barrier_depends(); x->bar = 5; And its the second case where smp_read_barrier_depends() read->write order matters.
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-01-26 20:50 +0100 |
| Message-ID | <qVhMK-qV-7@gated-at.bofh.it> |
| In reply to | #1318193 |
On Tue, Jan 26, 2016 at 9:22 AM, Peter Zijlstra <peterz@infradead.org> wrote:
>
> This is distinct from:
That may be distinct, but:
> struct foo *x = READ_ONCE(*ptr);
> smp_read_barrier_depends();
> x->bar = 5;
This case is complete BS. Stop perpetuating it. I already removed a
number of bogus cases of it, and I removed the incorrect documentation
that had this crap.
It's called "smp_READ_barrier_depends()" for a reason.
Alpha is the only one that needs it, and alpha needs it only for
dependent READS.
It's not called smp_read_write_barrier_depends(). It's not called
"smp_mb_depends()". It's a weaker form of "smp_rmb()", nothing else.
So alpha does have an implied dependency chain from a read to a
subsequent dependent write, and does not need any extra barriers.
Alpha does *not* have a dependency chain from a read to a subsequent
read, which is why we need that horrible crappy
smp_read_barrier_depends(). But it's the only reason.
This is the alpha reference manual wrt read-to-write dependency:
5.6.1.7 Definition of Dependence Constraint
The depends relation (DP) is defined as follows. Given u and v
issued by processor Pi, where u
is a read or an instruction fetch and v is a write, u precedes v
in DP order (written u DP v, that
is, v depends on u) in either of the following situations:
• u determines the execution of v, the location accessed by v, or
the value written by v.
• u determines the execution or address or value of another
memory access z that precedes
v or might precede v (that is, would precede v in some execution
path depending
on the value read by u) by processor issue constraint (see Section 5.6.1.3).
Note that the dependence barrier honors not only control flow, but
address and data values too. This is a different syntax than we use,
but 'u' is the READ_ONCE, and 'v' is the write. Any data, address or
conditional dependency between the two implies an ordering.
So no, "smp_read_barrier_depends()" is *ONLY* about two reads, where
the second read is data-dependent on the first. Nothing else.
So if you _ever_ see a "smp_read_barrier_depends()" that isn't about a
barrier between two reads, then that is a bug.
The above code is crap. It's exactly as much crap as
a = READ_ONCE(x);
smp_rmb();
WRITE_ONCE(b, y);
because a "rmb()" simply doesn't have anything to do with
read-vs-subsequent-write ordering.
Linus
[toc] | [prev] | [next] | [standalone]
| From | "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-26 23:10 +0100 |
| Message-ID | <qVjYf-2hg-31@gated-at.bofh.it> |
| In reply to | #1318319 |
On Tue, Jan 26, 2016 at 11:44:46AM -0800, Linus Torvalds wrote: > On Tue, Jan 26, 2016 at 9:22 AM, Peter Zijlstra <peterz@infradead.org> wrote: > > > > This is distinct from: > > That may be distinct, but: > > > struct foo *x = READ_ONCE(*ptr); > > smp_read_barrier_depends(); > > x->bar = 5; > > This case is complete BS. Stop perpetuating it. I already removed a > number of bogus cases of it, and I removed the incorrect documentation > that had this crap. If I understand your objection correctly, you want the above pattern expressed either like this: struct foo *x = rcu_dereference(*ptr); x->bar = 5; Or like this: struct foo *x = lockless_dereference(*ptr); x->bar = 5; Or am I missing your point? > It's called "smp_READ_barrier_depends()" for a reason. > > Alpha is the only one that needs it, and alpha needs it only for > dependent READS. > > It's not called smp_read_write_barrier_depends(). It's not called > "smp_mb_depends()". It's a weaker form of "smp_rmb()", nothing else. > > So alpha does have an implied dependency chain from a read to a > subsequent dependent write, and does not need any extra barriers. > > Alpha does *not* have a dependency chain from a read to a subsequent > read, which is why we need that horrible crappy > smp_read_barrier_depends(). But it's the only reason. > > This is the alpha reference manual wrt read-to-write dependency: > > 5.6.1.7 Definition of Dependence Constraint > > The depends relation (DP) is defined as follows. Given u and v > issued by processor Pi, where u > is a read or an instruction fetch and v is a write, u precedes v > in DP order (written u DP v, that > is, v depends on u) in either of the following situations: > > • u determines the execution of v, the location accessed by v, or > the value written by v. > • u determines the execution or address or value of another > memory access z that precedes > > v or might precede v (that is, would precede v in some execution > path depending > on the value read by u) by processor issue constraint (see Section 5.6.1.3). > > Note that the dependence barrier honors not only control flow, but > address and data values too. This is a different syntax than we use, > but 'u' is the READ_ONCE, and 'v' is the write. Any data, address or > conditional dependency between the two implies an ordering. > > So no, "smp_read_barrier_depends()" is *ONLY* about two reads, where > the second read is data-dependent on the first. Nothing else. > > So if you _ever_ see a "smp_read_barrier_depends()" that isn't about a > barrier between two reads, then that is a bug. And the smp_read_barrier_depends() in both rcu_dereference() and in lockless_dereference() is ordering the read-to-read case and the underlying hardware is ordering the read-to-write case on weakly ordered hardware. Or, again, am I missing your point? Thanx, Paul > The above code is crap. It's exactly as much crap as > > a = READ_ONCE(x); > smp_rmb(); > WRITE_ONCE(b, y); > > because a "rmb()" simply doesn't have anything to do with > read-vs-subsequent-write ordering. > > Linus >
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-01-26 23:20 +0100 |
| Message-ID | <qVk7U-2la-9@gated-at.bofh.it> |
| In reply to | #1318439 |
On Tue, Jan 26, 2016 at 12:10 PM, Paul E. McKenney
<paulmck@linux.vnet.ibm.com> wrote:
> On Tue, Jan 26, 2016 at 11:44:46AM -0800, Linus Torvalds wrote:
>>
>> > struct foo *x = READ_ONCE(*ptr);
>> > smp_read_barrier_depends();
>> > x->bar = 5;
>>
>> This case is complete BS. Stop perpetuating it. I already removed a
>> number of bogus cases of it, and I removed the incorrect documentation
>> that had this crap.
>
> If I understand your objection correctly, you want the above pattern
> expressed either like this:
>
> struct foo *x = rcu_dereference(*ptr);
> x->bar = 5;
>
> Or like this:
>
> struct foo *x = lockless_dereference(*ptr);
> x->bar = 5;
>
> Or am I missing your point?
You are entirely missing the point.
You might as well just write it as
struct foo x = READ_ONCE(*ptr);
x->bar = 5;
because that "smp_read_barrier_depends()" does NOTHING wrt the second write.
So what I am saying is simple: anybody who writes that
"smp_read_barrier_depends()" in there is just ttoally and completely
WRONG, and the fact that Peter wrote it out after I removed several
instances of that bloody f*cking idiocy is disturbing.
Don't do it. It's BS. It's wrong. Don't make excuses for it.
Linus
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-01-26 23:40 +0100 |
| Message-ID | <qVkrg-2uO-25@gated-at.bofh.it> |
| In reply to | #1318442 |
On Tue, Jan 26, 2016 at 2:15 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> You might as well just write it as
>
> struct foo x = READ_ONCE(*ptr);
> x->bar = 5;
>
> because that "smp_read_barrier_depends()" does NOTHING wrt the second write.
Just to clarify: on alpha it adds a memory barrier, but that memory
barrier is useless.
On non-alpha, it is a no-op, and obviously does nothing simply because
it generates no code.
So if anybody believes that the "smp_read_barrier_depends()" does
something, they are *wrong*.
And if anybody sends out an email with that smp_read_barrier_depends()
in an example, they are actively just confusing other people, which is
even worse than just being wrong. Which is why I jumped in.
So stop perpetuating the myth that smp_read_barrier_depends() does
something here. It does not. It's a bug, and it has become this "mind
virus" for some people that seem to believe that it does something.
I had to remove this crap once from the kernel already, see commit
105ff3cbf225 ("atomic: remove all traces of READ_ONCE_CTRL() and
atomic*_read_ctrl()").
I don't want to ever see that broken construct again. And I want to
make sure that everybody is educated about how broken it was. I'm
extremely unhappy that it came up again.
If it turns out that some architecture does actually need a barrier
between a read and a dependent write, then that will mean that
(a) we'll have to make up a _new_ barrier, because
"smp_read_barrier_depends()" is not that barrier. We'll presumably
then have to make that new barrier part of "rcu_derefence()" and
friends.
(b) we will have found an architecture with even worse memory
ordering semantics than alpha, and we'll have to stop castigating
alpha for being the worst memory ordering ever.
but I sincerely hope that we'll never find that kind of broken architecture.
Linus
[toc] | [prev] | [next] | [standalone]
| From | "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-27 00:30 +0100 |
| Message-ID | <qVldF-33s-19@gated-at.bofh.it> |
| In reply to | #1318448 |
On Tue, Jan 26, 2016 at 02:33:40PM -0800, Linus Torvalds wrote:
> On Tue, Jan 26, 2016 at 2:15 PM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> >
> > You might as well just write it as
> >
> > struct foo x = READ_ONCE(*ptr);
> > x->bar = 5;
> >
> > because that "smp_read_barrier_depends()" does NOTHING wrt the second write.
>
> Just to clarify: on alpha it adds a memory barrier, but that memory
> barrier is useless.
No trailing data-dependent read, so agreed, no smp_read_barrier_depends()
needed. That said, I believe that we should encourage rcu_dereference*()
or lockless_dereference() instead of READ_ONCE() for documentation
reasons, though.
> On non-alpha, it is a no-op, and obviously does nothing simply because
> it generates no code.
>
> So if anybody believes that the "smp_read_barrier_depends()" does
> something, they are *wrong*.
The other problem with smp_read_barrier_depends() is that it is often
a pain figuring out which prior load it is supposed to apply to.
Hence my preference for rcu_dereference*() and lockless_dereference().
> And if anybody sends out an email with that smp_read_barrier_depends()
> in an example, they are actively just confusing other people, which is
> even worse than just being wrong. Which is why I jumped in.
>
> So stop perpetuating the myth that smp_read_barrier_depends() does
> something here. It does not. It's a bug, and it has become this "mind
> virus" for some people that seem to believe that it does something.
It looks like I should add words to memory-barriers.txt de-emphasizing
smp_read_barrier_depends(). I will take a look at that.
> I had to remove this crap once from the kernel already, see commit
> 105ff3cbf225 ("atomic: remove all traces of READ_ONCE_CTRL() and
> atomic*_read_ctrl()").
>
> I don't want to ever see that broken construct again. And I want to
> make sure that everybody is educated about how broken it was. I'm
> extremely unhappy that it came up again.
Well, if it makes you feel better, that was control dependencies and this
was data dependencies. So it was not -exactly- the same. ;-)
(Sorry, couldn't resist...)
> If it turns out that some architecture does actually need a barrier
> between a read and a dependent write, then that will mean that
>
> (a) we'll have to make up a _new_ barrier, because
> "smp_read_barrier_depends()" is not that barrier. We'll presumably
> then have to make that new barrier part of "rcu_derefence()" and
> friends.
Agreed. We can worry about whether or not we replace the current
smp_read_barrier_depends() with that new barrier when and if such
hardware appears.
> (b) we will have found an architecture with even worse memory
> ordering semantics than alpha, and we'll have to stop castigating
> alpha for being the worst memory ordering ever.
;-) ;-) ;-)
> but I sincerely hope that we'll never find that kind of broken architecture.
Apparently at least some hardware vendors are reading memory-barriers.txt,
so perhaps the odds of that kind of breakage have reduced.
Thanx, Paul
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-01-27 00:50 +0100 |
| Message-ID | <qVlwZ-3bN-3@gated-at.bofh.it> |
| In reply to | #1318467 |
On Tue, Jan 26, 2016 at 3:29 PM, Paul E. McKenney
<paulmck@linux.vnet.ibm.com> wrote:
>
> No trailing data-dependent read, so agreed, no smp_read_barrier_depends()
> needed. That said, I believe that we should encourage rcu_dereference*()
> or lockless_dereference() instead of READ_ONCE() for documentation
> reasons, though.
I agree that that is likely the right thing to do in pretty much all situations.
In theory, there might be performance situations where we'd want to
actively avoid the smp_read_barrier_depends() inherent in those, but
considering that it's only a performance issue on alpha, and we
probably have all of two or three people using Linux on alpha, it's a
pretty theoretical performance worry.
Linus
[toc] | [prev] | [next] | [standalone]
| From | "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-27 02:00 +0100 |
| Message-ID | <qVmCK-3UC-5@gated-at.bofh.it> |
| In reply to | #1318476 |
On Tue, Jan 26, 2016 at 03:45:23PM -0800, Linus Torvalds wrote: > On Tue, Jan 26, 2016 at 3:29 PM, Paul E. McKenney > <paulmck@linux.vnet.ibm.com> wrote: > > > > No trailing data-dependent read, so agreed, no smp_read_barrier_depends() > > needed. That said, I believe that we should encourage rcu_dereference*() > > or lockless_dereference() instead of READ_ONCE() for documentation > > reasons, though. > > I agree that that is likely the right thing to do in pretty much all situations. > > In theory, there might be performance situations where we'd want to > actively avoid the smp_read_barrier_depends() inherent in those, but > considering that it's only a performance issue on alpha, and we > probably have all of two or three people using Linux on alpha, it's a > pretty theoretical performance worry. Agreed! Thanx, Paul
[toc] | [prev] | [next] | [standalone]
| From | Boqun Feng <boqun.feng@gmail.com> |
|---|---|
| Date | 2016-01-27 03:10 +0100 |
| Message-ID | <qVnIu-4QH-11@gated-at.bofh.it> |
| In reply to | #1318467 |
[Multipart message — attachments visible in raw view] — view raw
On Tue, Jan 26, 2016 at 03:29:21PM -0800, Paul E. McKenney wrote:
> On Tue, Jan 26, 2016 at 02:33:40PM -0800, Linus Torvalds wrote:
> > On Tue, Jan 26, 2016 at 2:15 PM, Linus Torvalds
> > <torvalds@linux-foundation.org> wrote:
> > >
> > > You might as well just write it as
> > >
> > > struct foo x = READ_ONCE(*ptr);
> > > x->bar = 5;
> > >
> > > because that "smp_read_barrier_depends()" does NOTHING wrt the second write.
> >
> > Just to clarify: on alpha it adds a memory barrier, but that memory
> > barrier is useless.
>
> No trailing data-dependent read, so agreed, no smp_read_barrier_depends()
> needed. That said, I believe that we should encourage rcu_dereference*()
> or lockless_dereference() instead of READ_ONCE() for documentation
> reasons, though.
>
> > On non-alpha, it is a no-op, and obviously does nothing simply because
> > it generates no code.
> >
> > So if anybody believes that the "smp_read_barrier_depends()" does
> > something, they are *wrong*.
>
> The other problem with smp_read_barrier_depends() is that it is often
> a pain figuring out which prior load it is supposed to apply to.
> Hence my preference for rcu_dereference*() and lockless_dereference().
>
Because semantically speaking, rcu_derefence*() and
lockless_dereference() are CONSUME(i.e. data/address dependent
read->read and read->write pairs are ordered), whereas
smp_read_barrier_depends() only guarantees read->read pairs with data
dependency are ordered, right?
If so, maybe we need to call it out in memory-barriers.txt, for example:
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 904ee42..6b262c2 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1703,8 +1703,8 @@ There are some more advanced barrier functions:
(*) lockless_dereference();
- This can be thought of as a pointer-fetch wrapper around the
- smp_read_barrier_depends() data-dependency barrier.
+ This is a load, and any load or store that has a data dependency on the
+ value returned by this load won't be reordered before this load.
This is also similar to rcu_dereference(), but in cases where
object lifetime is handled by some mechanism other than RCU, for
Regards,
Boqun
> > And if anybody sends out an email with that smp_read_barrier_depends()
> > in an example, they are actively just confusing other people, which is
> > even worse than just being wrong. Which is why I jumped in.
> >
> > So stop perpetuating the myth that smp_read_barrier_depends() does
> > something here. It does not. It's a bug, and it has become this "mind
> > virus" for some people that seem to believe that it does something.
>
> It looks like I should add words to memory-barriers.txt de-emphasizing
> smp_read_barrier_depends(). I will take a look at that.
>
> > I had to remove this crap once from the kernel already, see commit
> > 105ff3cbf225 ("atomic: remove all traces of READ_ONCE_CTRL() and
> > atomic*_read_ctrl()").
> >
> > I don't want to ever see that broken construct again. And I want to
> > make sure that everybody is educated about how broken it was. I'm
> > extremely unhappy that it came up again.
>
> Well, if it makes you feel better, that was control dependencies and this
> was data dependencies. So it was not -exactly- the same. ;-)
>
> (Sorry, couldn't resist...)
>
> > If it turns out that some architecture does actually need a barrier
> > between a read and a dependent write, then that will mean that
> >
> > (a) we'll have to make up a _new_ barrier, because
> > "smp_read_barrier_depends()" is not that barrier. We'll presumably
> > then have to make that new barrier part of "rcu_derefence()" and
> > friends.
>
> Agreed. We can worry about whether or not we replace the current
> smp_read_barrier_depends() with that new barrier when and if such
> hardware appears.
>
> > (b) we will have found an architecture with even worse memory
> > ordering semantics than alpha, and we'll have to stop castigating
> > alpha for being the worst memory ordering ever.
>
> ;-) ;-) ;-)
>
> > but I sincerely hope that we'll never find that kind of broken architecture.
>
> Apparently at least some hardware vendors are reading memory-barriers.txt,
> so perhaps the odds of that kind of breakage have reduced.
>
> Thanx, Paul
>
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2016-01-27 09:00 +0100 |
| Message-ID | <qVtbc-cl-3@gated-at.bofh.it> |
| In reply to | #1318448 |
On Tue, Jan 26, 2016 at 02:33:40PM -0800, Linus Torvalds wrote: > If it turns out that some architecture does actually need a barrier > between a read and a dependent write, then that will mean that > > (a) we'll have to make up a _new_ barrier, because > "smp_read_barrier_depends()" is not that barrier. We'll presumably > then have to make that new barrier part of "rcu_derefence()" and > friends. > > (b) we will have found an architecture with even worse memory > ordering semantics than alpha, and we'll have to stop castigating > alpha for being the worst memory ordering ever. > > but I sincerely hope that we'll never find that kind of broken architecture. So for a moment it looked like MIPS wanted to equal or surpass Alpha in this respect. And Paul made the point that smp_read_barrier_depends() really should be smp_aquire_barrier_depends() in that we rely on both dependent reads and writes to be ordered against the initial pointer load. Now, as you've made abundantly clear, Alpha does this, although it needs the little extra help in the dependent read department. The 'problem' is that someone seemed to have used our Documentation/memory-barriers.txt as a specification for what hardware is permitted and we require. And in that light Paul noted that read_barrier_depends really should be considered an acquire_barrier_depends and order both dependent reads and writes against the (prior) read (if nothing else already does). Now clearly, any sane architecture doesn't need anything like this, but again our document doesn't seem to judge. That is, from reading the document one can get the impression is a perfectly fine thing to do. Nowhere does our disdain for this thing show.
[toc] | [prev] | [next] | [standalone]
| From | "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
|---|---|
| Date | 2016-01-26 23:10 +0100 |
| Message-ID | <qVjYf-2hg-35@gated-at.bofh.it> |
| In reply to | #1318145 |
On Wed, Jan 27, 2016 at 12:52:07AM +0800, Boqun Feng wrote: > Hi Paul, > > On Mon, Jan 18, 2016 at 07:46:29AM -0800, Paul E. McKenney wrote: > > On Mon, Jan 18, 2016 at 04:19:29PM +0800, Herbert Xu wrote: > > > Paul E. McKenney <paulmck@linux.vnet.ibm.com> wrote: > > > > > > > > You could use SYNC_ACQUIRE() to implement read_barrier_depends() and > > > > smp_read_barrier_depends(), but SYNC_RMB probably does not suffice. > > > > The reason for this is that smp_read_barrier_depends() must order the > > > > pointer load against any subsequent read or write through a dereference > > > > of that pointer. For example: > > > > > > > > p = READ_ONCE(gp); > > > > smp_rmb(); > > > > r1 = p->a; /* ordered by smp_rmb(). */ > > > > p->b = 42; /* NOT ordered by smp_rmb(), BUG!!! */ > > > > r2 = x; /* ordered by smp_rmb(), but doesn't need to be. */ > > > > > > > > In contrast: > > > > > > > > p = READ_ONCE(gp); > > > > smp_read_barrier_depends(); > > > > r1 = p->a; /* ordered by smp_read_barrier_depends(). */ > > > > p->b = 42; /* ordered by smp_read_barrier_depends(). */ > > > > r2 = x; /* not ordered by smp_read_barrier_depends(), which is OK. */ > > > > > > > > Again, if your hardware maintains local ordering for address > > > > and data dependencies, you can have read_barrier_depends() and > > > > smp_read_barrier_depends() be no-ops like they are for most > > > > architectures. > > > > > > > > Does that help? > > > > > > This is crazy! smp_rmb started out being strictly stronger than > > > smp_read_barrier_depends, when did this stop being the case? > > > > Hello, Herbert! > > > > It is true that most Linux kernel code relies only on the read-read > > properties of dependencies, but the read-write properties are useful. > > Admittedly relatively rarely, but useful. > > > > The better comparison for smp_read_barrier_depends(), especially in > > its rcu_dereference*() form, is smp_load_acquire(). > > Confused.. > > I recall that last time you and Linus came into a conclusion that even > on Alpha, a barrier for read->write with data dependency is unnecessary: > > http://article.gmane.org/gmane.linux.kernel/2077661 > > And in an earlier mail of that thread, Linus made his point that > smp_read_barrier_depends() should only be used to order read->read. Those examples involved read-to-write with conditionals, as in: if (READ_ONCE(a)) WRITE_ONCE(b, 1); Without the "if", no ordering is guaranteed on weakly ordered CPUs. (The volatile accesses keep ordering within the compiler for once... > So right now, are we going to extend the semantics of > smp_read_barrier_depends()? Can we just make smp_read_barrier_depends() > still only work for read->read, and assume all the architectures won't > reorder read->write with data dependency, so that the code above having > a smp_rmb() also works? The semantics of smp_read_barrier_depends() has been both read-to-write and read-to-read for some time now, this patch just catches the documentation up with reality. Thanx, Paul
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web