On Tue, Apr 29, 2025 at 10:11 PM Jonathan Wakely <jwak...@redhat.com> wrote:

> Currently the GLIBCXX_ENABLE_ATOMIC_BUILTINS macro checks for a variety
> of __atomic built-ins for bool, short and int. If all those checks pass,
> then it defines _GLIBCXX_ATOMIC_BUILTINS and uses the definitions from
> config/cpu/generic/atomicity_builtins/atomicity.h for the non-inline
> versions of __exchange_and_add and __atomic_add that get compiled into
> libsupc++.
>
> However, the config/cpu/generic/atomicity_builtins/atomicity.h
> definitions only depend on __atomic_fetch_add not on
> __atomic_test_and_set or __atomic_compare_exchange. And they only
> operate on a variable of type _Atomic word, which is not necessarily one
> of bool, short or int (e.g. for sparcv9 _Atomic_word is 64-bit long).
>
> This means that for a target where _Atomic_word is int but there are no
> 1-byte or 2-byte atomic instructions, GLIBCXX_ENABLE_ATOMIC_BUILTINS
> will fail the checks for bool and short and not define the macro
> _GLIBCXX_ATOMIC_BUILTINS. That means that we will use a single global
> mutex for reference counting in the COW std::string and std::locale,
> even though we could use __atomic_fetch_add to do it lock-free.
>
> This commit removes most of the GLIBCXX_ENABLE_ATOMIC_BUILTINS checks,
> so that it only checks __atomic_fetch_add on _Atomic_word. This will
> enable the atomic versions of __exchange_and_add and __atomic_add for
> more targets. This is not an ABI change, because for targets which
> didn't previously use the atomic definitions of those function, they
> always make a non-inlined call to the functions in the library. If the
> definition of those functions now start using atomics, that doesn't
> change the semantics for the code calling those functions.
>
> On affected targets, new code compiled after this change will see the
> _GLIBCXX_ATOMIC_BUILTINS macro and so will use the always-inline
> versions of __exchange_and_add and __atomic_add, which use
> __atomic_fetch_add directly. That is also compatible with older code
> which calls the non-inline definitions, because those non-inline
> definitions now also use __atomic_fetch_add.
>
> The only configuration where this could be an ABI change is for a target
> which currently defines _GLIBCXX_ATOMIC_BUILTINS (because all the atomic
> built-ins for bool, short and int are supported), but which defines
> _Atomic_word to some other type for which __atomic_fetch_add is _not_
> supported. For such a target, we would previously have used inline calls
> to __atomic_fetch_add, which would have dependend on libatomic. After
> this commit, we would make non-inline calls into the library where
> __exchange_and_add and __atomic_add would use the global mutex. That
> would be an ABI break. I don't consider that a realistic scenario,
> because it wouldn't have made any sense to define _Atomic_word to a
> wider type than int, when doing so would have required libatomic to make
> libstdc++.so work. Surely such a target would have just used int for its
> _Atomic_word type.
>
> The GLIBCXX_ENABLE_BACKTRACE macro currently uses the
> glibcxx_ac_atomic_int macro defined by the checks that this commit
> removes from GLIBCXX_ENABLE_ATOMIC_BUILTINS. That wasn't a good check
> anyway, because libbacktrace actually depends on atomic loads+stores for
> pointers as well as int, and for atomic stores for size_t. This commit
> replaces the glibcxx_ac_atomic_int check with a proper test for all the
> required atomic operations on all three of int, void* and size_t. This
> ensures that the libbacktrace code used for std::stacktrace will either
> use native atomics, or implement those loads and stores only in terms of
> __sync_bool_compare_and_swap (possibly requiring that to come from
> libatomic or elsewhere).
>
> libstdc++-v3/ChangeLog:
>
>         PR libstdc++/70560
>         PR libstdc++/119667
>         * acinclude.m4 (GLIBCXX_ENABLE_ATOMIC_BUILTINS): Only check for
>         __atomic_fetch_add on _Atomic_word.
>         (GLIBCXX_ENABLE_BACKTRACE): Check for __atomic_load_n and
>         __atomic_store_n on int, void* and size_t.
>         * config.h.in: Regenerate.
>         * configure: Regenerate.
>         * configure.host: Fix typo in comment.
> ---
>
> Tested x86_64-linux, no changes to the c++config.h results.
> I need to do more testing on other targets.
>
O would rename _GLIBCXX_ATOMIC_BUILTINS to _GLIBCXX_ATOMIC_WORLD_BUILTINS,
to better reflect new reality. I have checked that it seems to be one
libstdc++-v3/include/ext/atomicity.h
file change. And if I mistaken, then the rename will show all affected
files in commit.

>
>  libstdc++-v3/acinclude.m4   | 301 +++++++++-----------------
>  libstdc++-v3/config.h.in    |   2 +-
>  libstdc++-v3/configure      | 418 ++++++++++++------------------------
>  libstdc++-v3/configure.host |   2 +-
>  4 files changed, 239 insertions(+), 484 deletions(-)
>
> diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
> index a0094c2dd95..8dddcada071 100644
> --- a/libstdc++-v3/acinclude.m4
> +++ b/libstdc++-v3/acinclude.m4
> @@ -3709,16 +3709,22 @@ AC_DEFUN([GLIBCXX_ENABLE_PCH], [
>    AC_SUBST(glibcxx_PCHFLAGS)
>  ])
>
> -
>  dnl
>  dnl Check for atomic builtins.
>  dnl See:
>  dnl http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
>  dnl
> -dnl This checks to see if the host supports the compiler-generated
> -dnl builtins for atomic operations for various integral sizes. Note, this
> -dnl is intended to be an all-or-nothing switch, so all the atomic
> operations
> -dnl that are used should be checked.
> +dnl This checks to see if the host supports __atomic_fetch_add on
> _Atomic_word.
> +dnl
> +dnl We don't want libstdc++.so to depend on libatomic.so for basic
> +dnl functionality like library-internal reference counting. This means we
> +dnl should not use atomics for reference counting unless it can be done
> +dnl using native instructions and not by calling into libatomic.
> +dnl This policy could change if linking to libatomic.so becomes implicit.
> +dnl
> +dnl Defines:
> +dnl  GLIBCXX_ATOMIC_BUILTINS - if atomic builtins should be used for
> +dnl                            increments and decrements of _Atomic_word.
>  dnl
>  dnl Note:
>  dnl libgomp and libgfortran use a link test, see CHECK_SYNC_FETCH_AND_ADD.
> @@ -3728,7 +3734,7 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
>    AC_LANG_CPLUSPLUS
>    old_CXXFLAGS="$CXXFLAGS"
>
> -  # Do link tests if possible, instead asm tests, limited to some
> platforms
> +  # Do link tests if possible, otherwise asm tests. Limited to some
> platforms
>    # see discussion in PR target/40134, PR libstdc++/40133 and the thread
>    # starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
>    atomic_builtins_link_tests=no
> @@ -3741,223 +3747,59 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
>      esac
>    fi
>
> -  if test x$atomic_builtins_link_tests = xyes; then
> +  if test "$atomic_builtins_link_tests" = yes; then
>
> -  # Do link tests.
> +    # Do link tests.
>
> -  CXXFLAGS="$CXXFLAGS -fno-exceptions"
> +    CXXFLAGS="$CXXFLAGS -fno-exceptions"
>
> -  AC_CACHE_CHECK([for atomic builtins for bool],
> -    glibcxx_cv_atomic_bool, [
> -    AC_TRY_LINK(
> -      [ ],
> -      [typedef bool atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       // N.B. __atomic_fetch_add is not supported for bool.
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -      ],
> -      [glibcxx_cv_atomic_bool=yes],
> -      [glibcxx_cv_atomic_bool=no])
> -  ])
> -
> -  AC_CACHE_CHECK([for atomic builtins for short],
> -    glibcxx_cv_atomic_short, [
> -    AC_TRY_LINK(
> -      [ ],
> -      [typedef short atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -      ],
> -      [glibcxx_cv_atomic_short=yes],
> -      [glibcxx_cv_atomic_short=no])
> -  ])
> -
> -  AC_CACHE_CHECK([for atomic builtins for int],
> -    glibcxx_cv_atomic_int, [
> -    AC_TRY_LINK(
> -      [ ],
> -      [typedef int atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -      ],
> -      [glibcxx_cv_atomic_int=yes],
> -      [glibcxx_cv_atomic_int=no])
> -  ])
> -
> -  AC_CACHE_CHECK([for atomic builtins for long long],
> -    glibcxx_cv_atomic_long_long, [
> -    AC_TRY_LINK(
> -      [ ],
> -      [typedef long long atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -      ],
> -      [glibcxx_cv_atomic_long_long=yes],
> -      [glibcxx_cv_atomic_long_long=no])
> -  ])
> +    AC_CACHE_CHECK([for atomic builtins for _Atomic_word],
> +       glibcxx_cv_atomic_word,
> +       [AC_TRY_LINK([#include
> "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"],
> +                    [_Atomic_word a = 0, b;
> +                     b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);],
> +                    [glibcxx_cv_atomic_word=yes],
> +                    [glibcxx_cv_atomic_word=no])])
>
>    else
> +    # Do asm tests.
>
> -  # Do asm tests.
> +    # Compile unoptimized.
> +    CXXFLAGS='-O0 -S'
>
> -  # Compile unoptimized.
> -  CXXFLAGS='-O0 -S'
> -
> -  # Fake what AC_TRY_COMPILE does.
> +    # Fake what AC_TRY_COMPILE does.
>
>      cat > conftest.$ac_ext << EOF
>  [#]line __oline__ "configure"
> +[#]include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
>  int main()
>  {
> -  typedef bool atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  // N.B. __atomic_fetch_add is not supported for bool.
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> +  _Atomic_word a = 0, b;
> +  b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
>  }
>  EOF
>
> -    AC_MSG_CHECKING([for atomic builtins for bool])
> +    AC_MSG_CHECKING([for atomic builtins for _Atomic_word])
>      if AC_TRY_EVAL(ac_compile); then
>        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_bool=no
> +       glibcxx_cv_atomic_word=no
>        else
> -       glibcxx_cv_atomic_bool=yes
> +       glibcxx_cv_atomic_word=yes
>        fi
>      fi
> -    AC_MSG_RESULT($glibcxx_cv_atomic_bool)
> +    AC_MSG_RESULT($glibcxx_cv_atomic_word)
>      rm -f conftest*
> -
> -    cat > conftest.$ac_ext << EOF
> -[#]line __oline__ "configure"
> -int main()
> -{
> -  typedef short atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> -}
> -EOF
> -
> -    AC_MSG_CHECKING([for atomic builtins for short])
> -    if AC_TRY_EVAL(ac_compile); then
> -      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_short=no
> -      else
> -       glibcxx_cv_atomic_short=yes
> -      fi
> -    fi
> -    AC_MSG_RESULT($glibcxx_cv_atomic_short)
> -    rm -f conftest*
> -
> -    cat > conftest.$ac_ext << EOF
> -[#]line __oline__ "configure"
> -int main()
> -{
> -  // NB: _Atomic_word not necessarily int.
> -  typedef int atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> -}
> -EOF
> -
> -    AC_MSG_CHECKING([for atomic builtins for int])
> -    if AC_TRY_EVAL(ac_compile); then
> -      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_int=no
> -      else
> -       glibcxx_cv_atomic_int=yes
> -      fi
> -    fi
> -    AC_MSG_RESULT($glibcxx_cv_atomic_int)
> -    rm -f conftest*
> -
> -    cat > conftest.$ac_ext << EOF
> -[#]line __oline__ "configure"
> -int main()
> -{
> -  typedef long long atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> -}
> -EOF
> -
> -    AC_MSG_CHECKING([for atomic builtins for long long])
> -    if AC_TRY_EVAL(ac_compile); then
> -      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_long_long=no
> -      else
> -       glibcxx_cv_atomic_long_long=yes
> -      fi
> -    fi
> -    AC_MSG_RESULT($glibcxx_cv_atomic_long_long)
> -    rm -f conftest*
> -
>    fi
>
>    CXXFLAGS="$old_CXXFLAGS"
>    AC_LANG_RESTORE
>
> -  # Set atomicity_dir to builtins if all but the long long test above
> passes,
> +  # Set atomicity_dir to builtins if the test above passes,
>    # or if the builtins were already chosen (e.g. by configure.host).
> -  if { test "$glibcxx_cv_atomic_bool" = yes \
> -     && test "$glibcxx_cv_atomic_short" = yes \
> -     && test "$glibcxx_cv_atomic_int" = yes; } \
> +  if test "$glibcxx_cv_atomic_word" = yes \
>       || test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then
>      AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS, 1,
> -    [Define if the compiler supports C++11 atomics.])
> +    [Define if the compiler supports native atomics for _Atomic_word.])
>      atomicity_dir=cpu/generic/atomicity_builtins
>    fi
>
> @@ -5448,8 +5290,75 @@ AC_DEFUN([GLIBCXX_ENABLE_BACKTRACE], [
>
>    BACKTRACE_CPPFLAGS="-D_GNU_SOURCE"
>
> -  # libbacktrace only needs atomics for int, which we've already tested
> -  if test "$glibcxx_cv_atomic_int" = "yes"; then
> +  GLIBCXX_LANG_PUSH
> +
> +  # libbacktrace's own configure.ac only tests atomics for int,
> +  # but the code actually uses atomics for size_t and pointers as well.
> +  if test "$atomic_builtins_link_tests" = yes; then
> +
> +    CXXFLAGS='-O0'
> +
> +    AC_CACHE_CHECK([for atomic builtins for libbacktrace],
> +       glibcxx_cv_libbacktrace_atomics,
> +       [AC_TRY_LINK([], [
> +           int i = 0;
> +           int* p = &i;
> +           size_t s = 0;
> +           // backtrace_atomic_load_pointer
> +           void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
> +           // backtrace_atomic_load_int
> +           int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
> +           // backtrace_atomic_store_pointer
> +           __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
> +           // backtrace_atomic_store_size_t
> +           __atomic_store_n(&s, s, __ATOMIC_RELEASE);
> +           // backtrace_atomic_store_int
> +           __atomic_store_n(&i, i, __ATOMIC_RELEASE);
> +                        ],
> +                    [glibcxx_cv_libbacktrace_atomics=yes],
> +                    [glibcxx_cv_libbacktrace_atomics=no])])
> +
> +  else
> +    # Do asm tests.
> +
> +    CXXFLAGS='-O0 -S'
> +
> +    cat > conftest.$ac_ext << EOF
> +[#]line __oline__ "configure"
> +[#]include <stddef.h>
> +int main()
> +{
> +  int i = 0;
> +  int* p = &i;
> +  size_t s = 0;
> +  // backtrace_atomic_load_pointer
> +  void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
> +  // backtrace_atomic_load_int
> +  int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
> +  // backtrace_atomic_store_pointer
> +  __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
> +  // backtrace_atomic_store_size_t
> +  __atomic_store_n(&s, s, __ATOMIC_RELEASE);
> +  // backtrace_atomic_store_int
> +  __atomic_store_n(&i, i, __ATOMIC_RELEASE);
> +}
> +EOF
> +
> +    AC_MSG_CHECKING([for atomic builtins for libbacktrace])
> +    if AC_TRY_EVAL(ac_compile); then
> +      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> +       glibcxx_cv_libbacktrace_atomics=no
> +      else
> +       glibcxx_cv_libbacktrace_atomics=yes
> +      fi
> +    fi
> +    AC_MSG_RESULT($glibcxx_cv_libbacktrace_atomics)
> +    rm -f conftest*
> +  fi
> +
> +  GLIBCXX_LANG_POP
> +
> +  if test "$glibcxx_cv_libbacktrace_atomics" = yes; then
>      BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1"
>    fi
>
> diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
> index 77bbaf1beaa..ed067717a20 100644
> --- a/libstdc++-v3/config.h.in
> +++ b/libstdc++-v3/config.h.in
> @@ -643,7 +643,7 @@
>     <cwchar> in namespace std for C++98. */
>  #undef _GLIBCXX98_USE_C99_WCHAR
>
> -/* Define if the compiler supports C++11 atomics. */
> +/* Define if the compiler supports native atomics for _Atomic_word. */
>  #undef _GLIBCXX_ATOMIC_BUILTINS
>
>  /* Define if global objects can be aligned to
> diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
> index 819a1d82876..e084c59742f 100755
> --- a/libstdc++-v3/configure
> +++ b/libstdc++-v3/configure
> @@ -15989,7 +15989,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
>
>    old_CXXFLAGS="$CXXFLAGS"
>
> -  # Do link tests if possible, instead asm tests, limited to some
> platforms
> +  # Do link tests if possible, otherwise asm tests. Limited to some
> platforms
>    # see discussion in PR target/40134, PR libstdc++/40133 and the thread
>    # starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
>    atomic_builtins_link_tests=no
> @@ -16002,326 +16002,77 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
>      esac
>    fi
>
> -  if test x$atomic_builtins_link_tests = xyes; then
> +  if test "$atomic_builtins_link_tests" = yes; then
>
> -  # Do link tests.
> +    # Do link tests.
>
> -  CXXFLAGS="$CXXFLAGS -fno-exceptions"
> +    CXXFLAGS="$CXXFLAGS -fno-exceptions"
>
> -  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for bool" >&5
> -$as_echo_n "checking for atomic builtins for bool... " >&6; }
> -if ${glibcxx_cv_atomic_bool+:} false; then :
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for _Atomic_word" >&5
> +$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; }
> +if ${glibcxx_cv_atomic_word+:} false; then :
>    $as_echo_n "(cached) " >&6
>  else
> -
> -    if test x$gcc_no_link = xyes; then
> +  if test x$gcc_no_link = xyes; then
>    as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES."
> "$LINENO" 5
>  fi
>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>  /* end confdefs.h.  */
> -
> +#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
>  int
>  main ()
>  {
> -typedef bool atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       // N.B. __atomic_fetch_add is not supported for bool.
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> +_Atomic_word a = 0, b;
> +                     b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
>    ;
>    return 0;
>  }
>  _ACEOF
>  if ac_fn_cxx_try_link "$LINENO"; then :
> -  glibcxx_cv_atomic_bool=yes
> +  glibcxx_cv_atomic_word=yes
>  else
> -  glibcxx_cv_atomic_bool=no
> +  glibcxx_cv_atomic_word=no
>  fi
>  rm -f core conftest.err conftest.$ac_objext \
>      conftest$ac_exeext conftest.$ac_ext
> -
>  fi
> -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool"
> >&5
> -$as_echo "$glibcxx_cv_atomic_bool" >&6; }
> -
> -  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for short" >&5
> -$as_echo_n "checking for atomic builtins for short... " >&6; }
> -if ${glibcxx_cv_atomic_short+:} false; then :
> -  $as_echo_n "(cached) " >&6
> -else
> -
> -    if test x$gcc_no_link = xyes; then
> -  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES."
> "$LINENO" 5
> -fi
> -cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> -/* end confdefs.h.  */
> -
> -int
> -main ()
> -{
> -typedef short atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  ;
> -  return 0;
> -}
> -_ACEOF
> -if ac_fn_cxx_try_link "$LINENO"; then :
> -  glibcxx_cv_atomic_short=yes
> -else
> -  glibcxx_cv_atomic_short=no
> -fi
> -rm -f core conftest.err conftest.$ac_objext \
> -    conftest$ac_exeext conftest.$ac_ext
> -
> -fi
> -{ $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_atomic_short" >&5
> -$as_echo "$glibcxx_cv_atomic_short" >&6; }
> -
> -  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for int" >&5
> -$as_echo_n "checking for atomic builtins for int... " >&6; }
> -if ${glibcxx_cv_atomic_int+:} false; then :
> -  $as_echo_n "(cached) " >&6
> -else
> -
> -    if test x$gcc_no_link = xyes; then
> -  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES."
> "$LINENO" 5
> -fi
> -cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> -/* end confdefs.h.  */
> -
> -int
> -main ()
> -{
> -typedef int atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  ;
> -  return 0;
> -}
> -_ACEOF
> -if ac_fn_cxx_try_link "$LINENO"; then :
> -  glibcxx_cv_atomic_int=yes
> -else
> -  glibcxx_cv_atomic_int=no
> -fi
> -rm -f core conftest.err conftest.$ac_objext \
> -    conftest$ac_exeext conftest.$ac_ext
> -
> -fi
> -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_int"
> >&5
> -$as_echo "$glibcxx_cv_atomic_int" >&6; }
> -
> -  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for long long" >&5
> -$as_echo_n "checking for atomic builtins for long long... " >&6; }
> -if ${glibcxx_cv_atomic_long_long+:} false; then :
> -  $as_echo_n "(cached) " >&6
> -else
> -
> -    if test x$gcc_no_link = xyes; then
> -  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES."
> "$LINENO" 5
> -fi
> -cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> -/* end confdefs.h.  */
> -
> -int
> -main ()
> -{
> -typedef long long atomic_type;
> -       atomic_type c1;
> -       atomic_type c2;
> -       atomic_type c3(0);
> -       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                                  __ATOMIC_RELAXED);
> -       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -       __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  ;
> -  return 0;
> -}
> -_ACEOF
> -if ac_fn_cxx_try_link "$LINENO"; then :
> -  glibcxx_cv_atomic_long_long=yes
> -else
> -  glibcxx_cv_atomic_long_long=no
> -fi
> -rm -f core conftest.err conftest.$ac_objext \
> -    conftest$ac_exeext conftest.$ac_ext
> -
> -fi
> -{ $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_atomic_long_long" >&5
> -$as_echo "$glibcxx_cv_atomic_long_long" >&6; }
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_word"
> >&5
> +$as_echo "$glibcxx_cv_atomic_word" >&6; }
>
>    else
> +    # Do asm tests.
>
> -  # Do asm tests.
> +    # Compile unoptimized.
> +    CXXFLAGS='-O0 -S'
>
> -  # Compile unoptimized.
> -  CXXFLAGS='-O0 -S'
> -
> -  # Fake what AC_TRY_COMPILE does.
> +    # Fake what AC_TRY_COMPILE does.
>
>      cat > conftest.$ac_ext << EOF
> -#line 16185 "configure"
> +#line 16051 "configure"
> +#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
>  int main()
>  {
> -  typedef bool atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  // N.B. __atomic_fetch_add is not supported for bool.
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> +  _Atomic_word a = 0, b;
> +  b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
>  }
>  EOF
>
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for bool" >&5
> -$as_echo_n "checking for atomic builtins for bool... " >&6; }
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for _Atomic_word" >&5
> +$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; }
>      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\"";
> } >&5
>    (eval $ac_compile) 2>&5
>    ac_status=$?
>    $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>    test $ac_status = 0; }; then
>        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_bool=no
> +       glibcxx_cv_atomic_word=no
>        else
> -       glibcxx_cv_atomic_bool=yes
> +       glibcxx_cv_atomic_word=yes
>        fi
>      fi
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_atomic_bool" >&5
> -$as_echo "$glibcxx_cv_atomic_bool" >&6; }
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_atomic_word" >&5
> +$as_echo "$glibcxx_cv_atomic_word" >&6; }
>      rm -f conftest*
> -
> -    cat > conftest.$ac_ext << EOF
> -#line 16220 "configure"
> -int main()
> -{
> -  typedef short atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> -}
> -EOF
> -
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for short" >&5
> -$as_echo_n "checking for atomic builtins for short... " >&6; }
> -    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\"";
> } >&5
> -  (eval $ac_compile) 2>&5
> -  ac_status=$?
> -  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> -  test $ac_status = 0; }; then
> -      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_short=no
> -      else
> -       glibcxx_cv_atomic_short=yes
> -      fi
> -    fi
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_atomic_short" >&5
> -$as_echo "$glibcxx_cv_atomic_short" >&6; }
> -    rm -f conftest*
> -
> -    cat > conftest.$ac_ext << EOF
> -#line 16255 "configure"
> -int main()
> -{
> -  // NB: _Atomic_word not necessarily int.
> -  typedef int atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> -}
> -EOF
> -
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for int" >&5
> -$as_echo_n "checking for atomic builtins for int... " >&6; }
> -    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\"";
> } >&5
> -  (eval $ac_compile) 2>&5
> -  ac_status=$?
> -  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> -  test $ac_status = 0; }; then
> -      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_int=no
> -      else
> -       glibcxx_cv_atomic_int=yes
> -      fi
> -    fi
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_atomic_int" >&5
> -$as_echo "$glibcxx_cv_atomic_int" >&6; }
> -    rm -f conftest*
> -
> -    cat > conftest.$ac_ext << EOF
> -#line 16291 "configure"
> -int main()
> -{
> -  typedef long long atomic_type;
> -  atomic_type c1;
> -  atomic_type c2;
> -  atomic_type c3(0);
> -  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
> -  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
> -                             __ATOMIC_RELAXED);
> -  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
> -  __atomic_load_n(&c1, __ATOMIC_RELAXED);
> -
> -  return 0;
> -}
> -EOF
> -
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for long long" >&5
> -$as_echo_n "checking for atomic builtins for long long... " >&6; }
> -    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\"";
> } >&5
> -  (eval $ac_compile) 2>&5
> -  ac_status=$?
> -  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> -  test $ac_status = 0; }; then
> -      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> -       glibcxx_cv_atomic_long_long=no
> -      else
> -       glibcxx_cv_atomic_long_long=yes
> -      fi
> -    fi
> -    { $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_atomic_long_long" >&5
> -$as_echo "$glibcxx_cv_atomic_long_long" >&6; }
> -    rm -f conftest*
> -
>    fi
>
>    CXXFLAGS="$old_CXXFLAGS"
> @@ -16332,11 +16083,9 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS
> $CPPFLAGS $LDFLAGS conftest.$ac_ext $
>  ac_compiler_gnu=$ac_cv_c_compiler_gnu
>
>
> -  # Set atomicity_dir to builtins if all but the long long test above
> passes,
> +  # Set atomicity_dir to builtins if the test above passes,
>    # or if the builtins were already chosen (e.g. by configure.host).
> -  if { test "$glibcxx_cv_atomic_bool" = yes \
> -     && test "$glibcxx_cv_atomic_short" = yes \
> -     && test "$glibcxx_cv_atomic_int" = yes; } \
> +  if test "$glibcxx_cv_atomic_word" = yes \
>       || test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then
>
>  $as_echo "#define _GLIBCXX_ATOMIC_BUILTINS 1" >>confdefs.h
> @@ -16445,7 +16194,7 @@ $as_echo "mutex" >&6; }
>    # unnecessary for this test.
>
>      cat > conftest.$ac_ext << EOF
> -#line 16448 "configure"
> +#line 16197 "configure"
>  int main()
>  {
>    _Decimal32 d1;
> @@ -16487,7 +16236,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
>    # unnecessary for this test.
>
>    cat > conftest.$ac_ext << EOF
> -#line 16490 "configure"
> +#line 16239 "configure"
>  template<typename T1, typename T2>
>    struct same
>    { typedef T2 type; };
> @@ -53788,8 +53537,105 @@ fi
>
>    BACKTRACE_CPPFLAGS="-D_GNU_SOURCE"
>
> -  # libbacktrace only needs atomics for int, which we've already tested
> -  if test "$glibcxx_cv_atomic_int" = "yes"; then
> +  GLIBCXX_LANG_PUSH
> +
> +  # libbacktrace's own configure.ac only tests atomics for int,
> +  # but the code actually uses atomics for size_t and pointers as well.
> +  if test "$atomic_builtins_link_tests" = yes; then
> +
> +    CXXFLAGS='-O0'
> +
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for libbacktrace" >&5
> +$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; }
> +if ${glibcxx_cv_libbacktrace_atomics+:} false; then :
> +  $as_echo_n "(cached) " >&6
> +else
> +  if test x$gcc_no_link = xyes; then
> +  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES."
> "$LINENO" 5
> +fi
> +cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h.  */
> +
> +int
> +main ()
> +{
> +
> +           int i = 0;
> +           int* p = &i;
> +           size_t s = 0;
> +           // backtrace_atomic_load_pointer
> +           void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
> +           // backtrace_atomic_load_int
> +           int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
> +           // backtrace_atomic_store_pointer
> +           __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
> +           // backtrace_atomic_store_size_t
> +           __atomic_store_n(&s, s, __ATOMIC_RELEASE);
> +           // backtrace_atomic_store_int
> +           __atomic_store_n(&i, i, __ATOMIC_RELEASE);
> +
> +  ;
> +  return 0;
> +}
> +_ACEOF
> +if ac_fn_c_try_link "$LINENO"; then :
> +  glibcxx_cv_libbacktrace_atomics=yes
> +else
> +  glibcxx_cv_libbacktrace_atomics=no
> +fi
> +rm -f core conftest.err conftest.$ac_objext \
> +    conftest$ac_exeext conftest.$ac_ext
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_libbacktrace_atomics" >&5
> +$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; }
> +
> +  else
> +    # Do asm tests.
> +
> +    CXXFLAGS='-O0 -S'
> +
> +    cat > conftest.$ac_ext << EOF
> +#line 53598 "configure"
> +#include <stddef.h>
> +int main()
> +{
> +  int i = 0;
> +  int* p = &i;
> +  size_t s = 0;
> +  // backtrace_atomic_load_pointer
> +  void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
> +  // backtrace_atomic_load_int
> +  int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
> +  // backtrace_atomic_store_pointer
> +  __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
> +  // backtrace_atomic_store_size_t
> +  __atomic_store_n(&s, s, __ATOMIC_RELEASE);
> +  // backtrace_atomic_store_int
> +  __atomic_store_n(&i, i, __ATOMIC_RELEASE);
> +}
> +EOF
> +
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins
> for libbacktrace" >&5
> +$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; }
> +    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\"";
> } >&5
> +  (eval $ac_compile) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; then
> +      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
> +       glibcxx_cv_libbacktrace_atomics=no
> +      else
> +       glibcxx_cv_libbacktrace_atomics=yes
> +      fi
> +    fi
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: result:
> $glibcxx_cv_libbacktrace_atomics" >&5
> +$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; }
> +    rm -f conftest*
> +  fi
> +
> +  GLIBCXX_LANG_POP
> +
> +  if test "$glibcxx_cv_libbacktrace_atomics" = yes; then
>      BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1"
>    fi
>
> diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
> index 253e5a9ad0d..3cd1bb1c6ee 100644
> --- a/libstdc++-v3/configure.host
> +++ b/libstdc++-v3/configure.host
> @@ -180,7 +180,7 @@ esac
>
>
>  # Set specific CPU overrides for atomicity_dir.
> -# This can be over-ridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS.
> +# This can be overridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS.
>  # THIS TABLE IS SORTED.  KEEP IT THAT WAY.
>  if test -f ${glibcxx_srcdir}/config/${cpu_include_dir}/atomicity.h ; then
>    atomicity_dir=$cpu_include_dir
> --
> 2.49.0
>
>

Reply via email to