[Bug libstdc++/111077] atomic_ref compare_exchange_strong doesn't properly ignore padding bits

2024-05-21 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111077

Jakub Jelinek  changed:

   What|Removed |Added

   Target Milestone|13.3|13.4

--- Comment #9 from Jakub Jelinek  ---
GCC 13.3 is being released, retargeting bugs to GCC 13.4.

[Bug libstdc++/111077] atomic_ref compare_exchange_strong doesn't properly ignore padding bits

2023-08-19 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111077

Andrew Pinski  changed:

   What|Removed |Added

  Component|c++ |libstdc++

--- Comment #3 from Andrew Pinski  ---
https://lists.llvm.org/pipermail/cfe-dev/2018-December/060605.html

[Bug libstdc++/111077] atomic_ref compare_exchange_strong doesn't properly ignore padding bits

2023-08-19 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111077

--- Comment #4 from Andrew Pinski  ---
reading through all of these discussions almost want to say the paper on
atomic_ref and padding bits of compare_and_exchange still missed the point of
this issue. Maybe this is undefined and maybe this is defect in the library
part of C++ standard even ...

[Bug libstdc++/111077] atomic_ref compare_exchange_strong doesn't properly ignore padding bits

2023-08-19 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111077

--- Comment #5 from Andrew Pinski  ---
See 
https://gcc.gnu.org/pipermail/libstdc++/2022-October/054899.html

Also

[Bug libstdc++/111077] atomic_ref compare_exchange_strong doesn't properly ignore padding bits

2023-08-20 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111077

--- Comment #6 from Jonathan Wakely  ---
(In reply to Andrew Pinski from comment #5)
> See 
> https://gcc.gnu.org/pipermail/libstdc++/2022-October/054899.html
> 
> Also

This is just a buggy test.

[Bug libstdc++/111077] atomic_ref compare_exchange_strong doesn't properly ignore padding bits

2023-08-20 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111077

Jonathan Wakely  changed:

   What|Removed |Added

   Assignee|unassigned at gcc dot gnu.org  |redi at gcc dot gnu.org
   Last reconfirmed||2023-08-20
 Ever confirmed|0   |1
   Target Milestone|--- |13.3
 Status|UNCONFIRMED |ASSIGNED

--- Comment #7 from Jonathan Wakely  ---
(In reply to comexk from comment #0)
> [See also:
> https://github.com/rust-lang/unsafe-code-guidelines/issues/449#issuecomment-
> 1677985851, which has a comparison of different compilers.]

"GCC does nothing to handle this" is incorrect. Only the case of an initial
value with non-zero padding is not handled, because atomic_ref doesn't control
the variable's initial value. atomic_ref::store and atomic_ref::exchange clear
padding bits, and so does a successful compare_exchange_{weak,strong}.

But we do have a bug here, because if that initial value has non-zero padding
bits even a compare_exchange_strong loop won't eventually settle, because we
keep zeroing the padding in the 'expected' value, which means it never matches.
We return the current value (with padding bits preserved), but then the next
call using that exact value will get the padding zeroed again, and fail to
match.

[Bug libstdc++/111077] atomic_ref compare_exchange_strong doesn't properly ignore padding bits

2023-09-01 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111077

--- Comment #8 from CVS Commits  ---
The master branch has been updated by Jonathan Wakely :

https://gcc.gnu.org/g:dcbec954fcba42d97760c6bd98a4c5618473ec93

commit r14-3625-gdcbec954fcba42d97760c6bd98a4c5618473ec93
Author: Jonathan Wakely 
Date:   Wed Aug 23 12:23:37 2023 +0100

libstdc++: Use a loop in atomic_ref::compare_exchange_strong [PR111077]

We need to use a loop in std::atomic_ref::compare_exchange_strong in
order to properly implement the C++20 requirement that padding bits do
not participate when checking the value for equality. The variable being
modified by a std::atomic_ref might have an initial value with non-zero
padding bits, so when the __atomic_compare_exchange built-in returns
false we need to check whether that was only because of non-equal
padding bits that are not part of the value representation. If the value
bits differ, it's just a failed compare-exchange. If the value bits are
the same, we need to retry the __atomic_compare_exchange using the value
that was just read by the previous failed call. As noted in the
comments, it's possible for that second try to also fail due to another
thread storing the same value but with differences in padding.

Because it's undefined to access a variable directly while it's held by
a std::atomic_ref, and because std::atomic_ref will only ever store
values with zeroed padding, we know that padding bits will never go from
zero to non-zero during the lifetime of a std::atomic_ref. They can only
go from an initial non-zero state to zero. This means the loop will
terminate, rather than looping indefinitely as padding bits flicker on
and off. In theory users could call __atomic_store etc. directly and
write a value with non-zero padding bits, but we don't need to support
that. Users doing that should ensure they do not write non-zero padding,
to be compatibile with our std::atomic_ref's invariants.

This isn't a problem for std::atomic::compare_exchange_strong because
the initial value (and all later stores to the variable) are performed
by the library, so we ensure that stored values always have padding bits
cleared. That means we can simply clear the padding bits of the
'expected' value and we will be comparing two values with equal padding
bits. This means we don't need the loop for std::atomic, so update the
__atomic_impl::__compare_exchange function to take a bool parameter that
says whether it's being used by std::atomic_ref. If not, we can use a
simpler, non-looping implementation.

libstdc++-v3/ChangeLog:

PR libstdc++/111077
* include/bits/atomic_base.h (__atomic_impl::__compare_exchange):
Add _AtomicRef non-type template parameter and use a loop if it
is true.
(__atomic_impl::compare_exchange_weak): Add _AtomicRef NTTP.
(__atomic_impl::compare_exchange_strong): Likewise.
(atomic_ref::compare_exchange_weak): Use true for NTTP.
(atomic_ref::compare_exchange_strong): Use true for NTTP.
* testsuite/29_atomics/atomic_ref/compare_exchange_padding.cc:
Fix test to not rely on atomic_ref::load() to return an object
with padding preserved.