aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2025-04-25 21:09:18 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2025-05-06 17:19:26 +0100
commit86627faec10da53d7532805019e5296fcf15ac09 (patch)
treed221f50f319ef8d45217bfc762f16464547f40bf
parentdf1d436d17c8280bd835b045bd7babf5058a7154 (diff)
downloadgcc-86627faec10da53d7532805019e5296fcf15ac09.zip
gcc-86627faec10da53d7532805019e5296fcf15ac09.tar.gz
gcc-86627faec10da53d7532805019e5296fcf15ac09.tar.bz2
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.
-rw-r--r--libstdc++-v3/acinclude.m4303
-rw-r--r--libstdc++-v3/config.h.in4
-rwxr-xr-xlibstdc++-v3/configure420
-rw-r--r--libstdc++-v3/configure.host2
-rw-r--r--libstdc++-v3/include/ext/atomicity.h4
5 files changed, 244 insertions, 489 deletions
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index a0094c2..0fc74d0 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 77bbaf1..3dbe00b 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 819a1d82..3fd03b8 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 253e5a9..3cd1bb1 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 98f745c..650b786 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;