https://gcc.gnu.org/g:86627faec10da53d7532805019e5296fcf15ac09

commit r16-427-g86627faec10da53d7532805019e5296fcf15ac09
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Fri Apr 25 21:09:18 2025 +0100

    libstdc++: Rewrite atomic builtin checks [PR70560]
    
    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. The macro
    defined by GLIBCXX_ENABLE_ATOMIC_BUILTINS is renamed from
    _GLIBCXX_ATOMIC_BUILTINS to _GLIBCXX_ATOMIC_WORD_BUILTINS to better
    reflect what it really means. This will enable the inline versions of
    __exchange_and_add and __atomic_add for more targets. This is not an ABI
    change, because targets which didn't previously use the inline
    definitions of those functions made non-inlined calls to the functions
    in the library. If the definitions 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_WORD_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 still 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 previously defined _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. Such a target would have called the inline functions
    using __atomic_fetch_add, which would actually have depended on
    libatomic (which is what the configure checks were supposed to
    prevent!).  After this change, that target would not define the new
    macro, _GLIBCXX_ATOMIC_WORD_BUILTINS, and so 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 variable 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. Define new macro
            _GLIBCXX_ATOMIC_WORD_BUILTINS and stop defining macro
            _GLIBCXX_ATOMIC_BUILTINS.
            (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.
            * include/ext/atomicity.h (__exchange_and_add, __atomic_add):
            Depend on _GLIBCXX_ATOMIC_WORD_BUILTINS macro instead of old
            _GLIBCXX_ATOMIC_BUILTINS macro.

Diff:
---
 libstdc++-v3/acinclude.m4            | 303 +++++++++----------------
 libstdc++-v3/config.h.in             |   4 +-
 libstdc++-v3/configure               | 420 +++++++++++------------------------
 libstdc++-v3/configure.host          |   2 +-
 libstdc++-v3/include/ext/atomicity.h |   4 +-
 5 files changed, 244 insertions(+), 489 deletions(-)

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index a0094c2dd95b..0fc74d00a98f 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_WORD_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
-
-  # Do link tests.
+  if test "$atomic_builtins_link_tests" = yes; then
 
-  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])
-  ])
+    # Do link tests.
 
-  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])
-  ])
+    CXXFLAGS="$CXXFLAGS -fno-exceptions"
 
-  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'
-
-  # Fake what AC_TRY_COMPILE does.
-
-    cat > conftest.$ac_ext << EOF
-[#]line __oline__ "configure"
-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;
-}
-EOF
-
-    AC_MSG_CHECKING([for atomic builtins for bool])
-    if AC_TRY_EVAL(ac_compile); then
-      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
-       glibcxx_cv_atomic_bool=no
-      else
-       glibcxx_cv_atomic_bool=yes
-      fi
-    fi
-    AC_MSG_RESULT($glibcxx_cv_atomic_bool)
-    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);
+    # Compile unoptimized.
+    CXXFLAGS='-O0 -S'
 
-  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*
+    # 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 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;
+  _Atomic_word a = 0, b;
+  b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
 }
 EOF
 
-    AC_MSG_CHECKING([for atomic builtins for long long])
+    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_long_long=no
+       glibcxx_cv_atomic_word=no
       else
-       glibcxx_cv_atomic_long_long=yes
+       glibcxx_cv_atomic_word=yes
       fi
     fi
-    AC_MSG_RESULT($glibcxx_cv_atomic_long_long)
+    AC_MSG_RESULT($glibcxx_cv_atomic_word)
     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.])
+    AC_DEFINE(_GLIBCXX_ATOMIC_WORD_BUILTINS, 1,
+    [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 77bbaf1beaa5..3dbe00bae508 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -643,8 +643,8 @@
    <cwchar> in namespace std for C++98. */
 #undef _GLIBCXX98_USE_C99_WCHAR
 
-/* Define if the compiler supports C++11 atomics. */
-#undef _GLIBCXX_ATOMIC_BUILTINS
+/* Define if the compiler supports native atomics for _Atomic_word. */
+#undef _GLIBCXX_ATOMIC_WORD_BUILTINS
 
 /* Define if global objects can be aligned to
    std::hardware_destructive_interference_size. */
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 819a1d82876a..3fd03b8a95d6 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"
-
-  { $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_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 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;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
-  glibcxx_cv_atomic_bool=yes
-else
-  glibcxx_cv_atomic_bool=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; }
+    CXXFLAGS="$CXXFLAGS -fno-exceptions"
 
-  { $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 "$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 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);
-
+_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_long_long=yes
+  glibcxx_cv_atomic_word=yes
 else
-  glibcxx_cv_atomic_long_long=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_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'
-
-  # Fake what AC_TRY_COMPILE does.
-
-    cat > conftest.$ac_ext << EOF
-#line 16185 "configure"
-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;
-}
-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; }
-    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
-      else
-       glibcxx_cv_atomic_bool=yes
-      fi
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool" 
>&5
-$as_echo "$glibcxx_cv_atomic_bool" >&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
+    # Compile unoptimized.
+    CXXFLAGS='-O0 -S'
 
-    { $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*
+    # Fake what AC_TRY_COMPILE does.
 
     cat > conftest.$ac_ext << EOF
-#line 16291 "configure"
+#line 16051 "configure"
+#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.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;
+  _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 
long long" >&5
-$as_echo_n "checking for atomic builtins for long long... " >&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_long_long=no
+       glibcxx_cv_atomic_word=no
       else
-       glibcxx_cv_atomic_long_long=yes
+       glibcxx_cv_atomic_word=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; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_word" 
>&5
+$as_echo "$glibcxx_cv_atomic_word" >&6; }
     rm -f conftest*
-
   fi
 
   CXXFLAGS="$old_CXXFLAGS"
@@ -16332,14 +16083,12 @@ 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
+$as_echo "#define _GLIBCXX_ATOMIC_WORD_BUILTINS 1" >>confdefs.h
 
     atomicity_dir=cpu/generic/atomicity_builtins
   fi
@@ -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 253e5a9ad0db..3cd1bb1c6eed 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
diff --git a/libstdc++-v3/include/ext/atomicity.h 
b/libstdc++-v3/include/ext/atomicity.h
index 98f745c4f703..650b786cd8e6 100644
--- a/libstdc++-v3/include/ext/atomicity.h
+++ b/libstdc++-v3/include/ext/atomicity.h
@@ -61,7 +61,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // To abstract locking primitives across all thread policies, use:
   // __exchange_and_add_dispatch
   // __atomic_add_dispatch
-#ifdef _GLIBCXX_ATOMIC_BUILTINS
+#ifdef _GLIBCXX_ATOMIC_WORD_BUILTINS
   inline _Atomic_word
   __attribute__((__always_inline__))
   __exchange_and_add(volatile _Atomic_word* __mem, int __val)
@@ -71,7 +71,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __attribute__((__always_inline__))
   __atomic_add(volatile _Atomic_word* __mem, int __val)
   { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
-#else
+#else // Defined in config/cpu/.../atomicity.h
   _Atomic_word
   __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;

Reply via email to