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. 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