git: 054ce2b03710 - main - atomic: add stub atomic_load_consume_ptr

Mark Millard marklmi at yahoo.com
Tue Feb 2 21:54:28 UTC 2021


Jessica Clarke jrtc27 at freebsd.org wrote on
Mon Jan 25 23:56:41 UTC 2021 :

> On 25 Jan 2021, at 22:42, Mateusz Guzik <mjg at FreeBSD.org> wrote:
> > 
> > The branch main has been updated by mjg:
> > 
> > URL: https://cgit.FreeBSD.org/src/commit/?id=054ce2b0371042c0dbc4b3ab1d7e7795ad75d51e
> > 
> > commit 054ce2b0371042c0dbc4b3ab1d7e7795ad75d51e
> > Author:     Mateusz Guzik <mjg at FreeBSD.org>
> > AuthorDate: 2021-01-25 20:09:41 +0000
> > Commit:     Mateusz Guzik <mjg at FreeBSD.org>
> > CommitDate: 2021-01-25 22:40:15 +0000
> > 
> >    atomic: add stub atomic_load_consume_ptr
> 
> Consume semantics is a waste of time, it's basically impossible to
> implement in an optimising compiler as, in order to not emit the same
> fences as an acquire, you need the source dependencies to be mapped to
> data dependencies in the output assembly, but all manner of
> transformations can cause that to break. And that's before you get to
> hand-written atomic implementations where it is impossible for you to
> ensure that, as you're not even telling the compiler what you're doing.
> For example:
> 
>   int x = atomic_load_consume_int(p);
>   int y = q[x - x];
> 
> This looks like stupid code, but the `x - x` cannot be constant-folded
> without inserting a barrier, as currently there is data dependence at
> the source level. If you use language-level atomics then it "works" by
> virtue of compilers just turning consumes into acquires so the later
> constant folding is safe. But if your atomic_load_consume_int is
> hand-rolled magic assembly then the compiler has no clue and will
> blindly go and constant fold that subtraction for you, completely
> breaking your synchronisation.
> 
> Providing consume loads just doesn't make sense for FreeBSD's atomics
> except for documenting the exact requirements of the code being written;
> they can never be implemented as anything other than acquire loads
> unless we migrate to using actual C11 atomics, but even then you won't
> get any code generation difference and likely never will.

My understanding that the language standards defined the
consume semantics, relative to release sequences and such,
such that too much could be inferred, for example on armv8,
in absence of extra code that consume was intended to avoid.
For example, armv8 can do speculative consume loads across
conditional branches and the dependent load can return a
stale value.

So the release sequence implications are being backed-off and
happens-before splits into simple-happens-before (allows 
consume to be involved) and strong-happens-before (that does
not allow consume to be involved) and possibly more.

This suggests to me that great care is needed in deciding to
use a consume operation (not just via a specific language or
language family's formal notation), probably to the point
of requiring explicitly well-commenting on the guarantees in
the context that allow consume to be safe and on what needs
to be maintained to avoid having future changes implicit
break the consume behavior.

Or, may be, FreeBSD needs to more globally document just what
only-minimal types inferences are to be allowed to be put to
use for any FreeBSD consume use, possibly less than what the
adjusted language standards are attempting. That might make
such code less easy to accidentally break.

===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)



More information about the dev-commits-src-main mailing list