On Mon, Sep 08, 2025 at 01:35:59PM +0100, Jonathan Wakely wrote:
> The standard requires that std::atomic<integral-type>::fetch_add does
> not have undefined behaviour for signed overflow, instead it wraps like
> unsigned integers. The compiler ensures this is true for the atomic
> built-ins that std::atomic uses, but it's not currently true for the
> __gnu_cxx::__exchange_and_add and __gnu_cxx::__atomic_add functions
> defined in libstdc++, which operate on type _Atomic_word.
> 
> For the inline __exchange_and_add_single function (used when there's
> only one thread in the process), we can copy the value to an unsigned
> long and do the addition on that, then assign it back to the
> _Atomic_word variable.
> 
> The __exchange_and_add in config/cpu/generic/atomicity_mutex/atomicity.h
> locks a mutex and then performs exactly the same steps as
> __exchange_and_add_single.  Calling __exchange_and_add_single instead of
> duplicating the code benefits from the fix just made to
> __exchange_and_add_single.
> 
> For the remaining config/cpu/$arch/atomicity.h implementations, they
> either use inline assembly which uses wrapping instructions (so no
> changes needed), or we can fix them by compiling with -fwrapv.
> 
> After ths change, UBsan no longer gives an error for:
> 
>   _Atomic_word i = INT_MAX;
>   __gnu_cxx::__exchange_and_add_dispatch(&i, 1);
> 
> /usr/include/c++/14/ext/atomicity.h:85:12: runtime error: signed integer 
> overflow: 2147483647 + 1 cannot be represented in type 'int'
> 
> libstdc++-v3/ChangeLog:
> 
>       PR libstdc++/121148
>       * config/cpu/generic/atomicity_mutex/atomicity.h
>       (__exchange_and_add): Call __exchange_and_add_single.
>       * include/ext/atomicity.h (__exchange_and_add_single): Use an
>       unsigned type for the addition.
>       * libsupc++/Makefile.am (atomicity.o): Compile with -fwrapv.
>       * libsupc++/Makefile.in: Regenerate.
> ---
> 
> v2: no changes to this first patch in the series.
> 
> Tested powerpc64le-linux.
> 
>  .../cpu/generic/atomicity_mutex/atomicity.h   |  5 +--
>  libstdc++-v3/include/ext/atomicity.h          | 35 +++++++++++++++++--
>  libstdc++-v3/libsupc++/Makefile.am            |  5 +++
>  libstdc++-v3/libsupc++/Makefile.in            |  5 +++
>  4 files changed, 44 insertions(+), 6 deletions(-)
> 
> diff --git a/libstdc++-v3/config/cpu/generic/atomicity_mutex/atomicity.h 
> b/libstdc++-v3/config/cpu/generic/atomicity_mutex/atomicity.h
> index b1328c025bcc..7d5772d54840 100644
> --- a/libstdc++-v3/config/cpu/generic/atomicity_mutex/atomicity.h
> +++ b/libstdc++-v3/config/cpu/generic/atomicity_mutex/atomicity.h
> @@ -44,10 +44,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    __exchange_and_add(volatile _Atomic_word* __mem, int __val) throw ()
>    {
>      __gnu_cxx::__scoped_lock sentry(get_atomic_mutex());
> -    _Atomic_word __result;
> -    __result = *__mem;
> -    *__mem += __val;
> -    return __result;
> +    return __gnu_cxx::__exchange_and_add_single(__mem, __val);
>    }
>  

Hi Jonathan,

This broke the build for pru-unknown-elf target.  I suspect it's either
because it uses newlib instead of glibc.  Or because this target does not
define its own atomic ops.

The error is:
  atomicity.cc: In function ‘_Atomic_word 
__gnu_cxx::__exchange_and_add(volatile _Atomic_word*, int)’:
  atomicity.cc:47:49: error: invalid conversion from ‘volatile _Atomic_word*’ 
{aka ‘volatile int*’} to ‘_Atomic_word*’ {aka ‘int*’} [-fpermissive]
     47 |     return __gnu_cxx::__exchange_and_add_single(__mem, __val);
        |                                                 ^~~~~
        |                                                 |
        |                                                 volatile 
_Atomic_word* {aka volatile int*}
  In file included from atomicity.cc:25:
  
/home/dinux/projects/pru/testbot-workspace/pru-gcc-build/pru/libstdc++-v3/include/ext/atomicity.h:95:43:
 note: initializing argument 1 of ‘_Atomic_word 
__gnu_cxx::__exchange_and_add_single(_Atomic_word*, int)’
     95 |   __exchange_and_add_single(_Atomic_word* __mem, int __val)
        |                             ~~~~~~~~~~~~~~^~~~~

Regards,
Dimitar

Reply via email to