On Tue, Apr 29, 2025 at 10:11 PM Jonathan Wakely <jwak...@redhat.com> wrote:
> Currently the GLIBCXX_ENABLE_ATOMIC_BUILTINS macro checks for a variety > of __atomic built-ins for bool, short and int. If all those checks pass, > then it defines _GLIBCXX_ATOMIC_BUILTINS and uses the definitions from > config/cpu/generic/atomicity_builtins/atomicity.h for the non-inline > versions of __exchange_and_add and __atomic_add that get compiled into > libsupc++. > > However, the config/cpu/generic/atomicity_builtins/atomicity.h > definitions only depend on __atomic_fetch_add not on > __atomic_test_and_set or __atomic_compare_exchange. And they only > operate on a variable of type _Atomic word, which is not necessarily one > of bool, short or int (e.g. for sparcv9 _Atomic_word is 64-bit long). > > This means that for a target where _Atomic_word is int but there are no > 1-byte or 2-byte atomic instructions, GLIBCXX_ENABLE_ATOMIC_BUILTINS > will fail the checks for bool and short and not define the macro > _GLIBCXX_ATOMIC_BUILTINS. That means that we will use a single global > mutex for reference counting in the COW std::string and std::locale, > even though we could use __atomic_fetch_add to do it lock-free. > > This commit removes most of the GLIBCXX_ENABLE_ATOMIC_BUILTINS checks, > so that it only checks __atomic_fetch_add on _Atomic_word. This will > enable the atomic versions of __exchange_and_add and __atomic_add for > more targets. This is not an ABI change, because for targets which > didn't previously use the atomic definitions of those function, they > always make a non-inlined call to the functions in the library. If the > definition of those functions now start using atomics, that doesn't > change the semantics for the code calling those functions. > > On affected targets, new code compiled after this change will see the > _GLIBCXX_ATOMIC_BUILTINS macro and so will use the always-inline > versions of __exchange_and_add and __atomic_add, which use > __atomic_fetch_add directly. That is also compatible with older code > which calls the non-inline definitions, because those non-inline > definitions now also use __atomic_fetch_add. > > The only configuration where this could be an ABI change is for a target > which currently defines _GLIBCXX_ATOMIC_BUILTINS (because all the atomic > built-ins for bool, short and int are supported), but which defines > _Atomic_word to some other type for which __atomic_fetch_add is _not_ > supported. For such a target, we would previously have used inline calls > to __atomic_fetch_add, which would have dependend on libatomic. After > this commit, we would make non-inline calls into the library where > __exchange_and_add and __atomic_add would use the global mutex. That > would be an ABI break. I don't consider that a realistic scenario, > because it wouldn't have made any sense to define _Atomic_word to a > wider type than int, when doing so would have required libatomic to make > libstdc++.so work. Surely such a target would have just used int for its > _Atomic_word type. > > The GLIBCXX_ENABLE_BACKTRACE macro currently uses the > glibcxx_ac_atomic_int macro defined by the checks that this commit > removes from GLIBCXX_ENABLE_ATOMIC_BUILTINS. That wasn't a good check > anyway, because libbacktrace actually depends on atomic loads+stores for > pointers as well as int, and for atomic stores for size_t. This commit > replaces the glibcxx_ac_atomic_int check with a proper test for all the > required atomic operations on all three of int, void* and size_t. This > ensures that the libbacktrace code used for std::stacktrace will either > use native atomics, or implement those loads and stores only in terms of > __sync_bool_compare_and_swap (possibly requiring that to come from > libatomic or elsewhere). > > libstdc++-v3/ChangeLog: > > PR libstdc++/70560 > PR libstdc++/119667 > * acinclude.m4 (GLIBCXX_ENABLE_ATOMIC_BUILTINS): Only check for > __atomic_fetch_add on _Atomic_word. > (GLIBCXX_ENABLE_BACKTRACE): Check for __atomic_load_n and > __atomic_store_n on int, void* and size_t. > * config.h.in: Regenerate. > * configure: Regenerate. > * configure.host: Fix typo in comment. > --- > > Tested x86_64-linux, no changes to the c++config.h results. > I need to do more testing on other targets. > O would rename _GLIBCXX_ATOMIC_BUILTINS to _GLIBCXX_ATOMIC_WORLD_BUILTINS, to better reflect new reality. I have checked that it seems to be one libstdc++-v3/include/ext/atomicity.h file change. And if I mistaken, then the rename will show all affected files in commit. > > libstdc++-v3/acinclude.m4 | 301 +++++++++----------------- > libstdc++-v3/config.h.in | 2 +- > libstdc++-v3/configure | 418 ++++++++++++------------------------ > libstdc++-v3/configure.host | 2 +- > 4 files changed, 239 insertions(+), 484 deletions(-) > > diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 > index a0094c2dd95..8dddcada071 100644 > --- a/libstdc++-v3/acinclude.m4 > +++ b/libstdc++-v3/acinclude.m4 > @@ -3709,16 +3709,22 @@ AC_DEFUN([GLIBCXX_ENABLE_PCH], [ > AC_SUBST(glibcxx_PCHFLAGS) > ]) > > - > dnl > dnl Check for atomic builtins. > dnl See: > dnl http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html > dnl > -dnl This checks to see if the host supports the compiler-generated > -dnl builtins for atomic operations for various integral sizes. Note, this > -dnl is intended to be an all-or-nothing switch, so all the atomic > operations > -dnl that are used should be checked. > +dnl This checks to see if the host supports __atomic_fetch_add on > _Atomic_word. > +dnl > +dnl We don't want libstdc++.so to depend on libatomic.so for basic > +dnl functionality like library-internal reference counting. This means we > +dnl should not use atomics for reference counting unless it can be done > +dnl using native instructions and not by calling into libatomic. > +dnl This policy could change if linking to libatomic.so becomes implicit. > +dnl > +dnl Defines: > +dnl GLIBCXX_ATOMIC_BUILTINS - if atomic builtins should be used for > +dnl increments and decrements of _Atomic_word. > dnl > dnl Note: > dnl libgomp and libgfortran use a link test, see CHECK_SYNC_FETCH_AND_ADD. > @@ -3728,7 +3734,7 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [ > AC_LANG_CPLUSPLUS > old_CXXFLAGS="$CXXFLAGS" > > - # Do link tests if possible, instead asm tests, limited to some > platforms > + # Do link tests if possible, otherwise asm tests. Limited to some > platforms > # see discussion in PR target/40134, PR libstdc++/40133 and the thread > # starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html > atomic_builtins_link_tests=no > @@ -3741,223 +3747,59 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [ > esac > fi > > - if test x$atomic_builtins_link_tests = xyes; then > + if test "$atomic_builtins_link_tests" = yes; then > > - # Do link tests. > + # Do link tests. > > - CXXFLAGS="$CXXFLAGS -fno-exceptions" > + CXXFLAGS="$CXXFLAGS -fno-exceptions" > > - AC_CACHE_CHECK([for atomic builtins for bool], > - glibcxx_cv_atomic_bool, [ > - AC_TRY_LINK( > - [ ], > - [typedef bool atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - // N.B. __atomic_fetch_add is not supported for bool. > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - ], > - [glibcxx_cv_atomic_bool=yes], > - [glibcxx_cv_atomic_bool=no]) > - ]) > - > - AC_CACHE_CHECK([for atomic builtins for short], > - glibcxx_cv_atomic_short, [ > - AC_TRY_LINK( > - [ ], > - [typedef short atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - ], > - [glibcxx_cv_atomic_short=yes], > - [glibcxx_cv_atomic_short=no]) > - ]) > - > - AC_CACHE_CHECK([for atomic builtins for int], > - glibcxx_cv_atomic_int, [ > - AC_TRY_LINK( > - [ ], > - [typedef int atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - ], > - [glibcxx_cv_atomic_int=yes], > - [glibcxx_cv_atomic_int=no]) > - ]) > - > - AC_CACHE_CHECK([for atomic builtins for long long], > - glibcxx_cv_atomic_long_long, [ > - AC_TRY_LINK( > - [ ], > - [typedef long long atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - ], > - [glibcxx_cv_atomic_long_long=yes], > - [glibcxx_cv_atomic_long_long=no]) > - ]) > + AC_CACHE_CHECK([for atomic builtins for _Atomic_word], > + glibcxx_cv_atomic_word, > + [AC_TRY_LINK([#include > "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"], > + [_Atomic_word a = 0, b; > + b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);], > + [glibcxx_cv_atomic_word=yes], > + [glibcxx_cv_atomic_word=no])]) > > else > + # Do asm tests. > > - # Do asm tests. > + # Compile unoptimized. > + CXXFLAGS='-O0 -S' > > - # Compile unoptimized. > - CXXFLAGS='-O0 -S' > - > - # Fake what AC_TRY_COMPILE does. > + # Fake what AC_TRY_COMPILE does. > > cat > conftest.$ac_ext << EOF > [#]line __oline__ "configure" > +[#]include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h" > int main() > { > - typedef bool atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - // N.B. __atomic_fetch_add is not supported for bool. > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > + _Atomic_word a = 0, b; > + b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL); > } > EOF > > - AC_MSG_CHECKING([for atomic builtins for bool]) > + AC_MSG_CHECKING([for atomic builtins for _Atomic_word]) > if AC_TRY_EVAL(ac_compile); then > if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_bool=no > + glibcxx_cv_atomic_word=no > else > - glibcxx_cv_atomic_bool=yes > + glibcxx_cv_atomic_word=yes > fi > fi > - AC_MSG_RESULT($glibcxx_cv_atomic_bool) > + AC_MSG_RESULT($glibcxx_cv_atomic_word) > rm -f conftest* > - > - cat > conftest.$ac_ext << EOF > -[#]line __oline__ "configure" > -int main() > -{ > - typedef short atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > -} > -EOF > - > - AC_MSG_CHECKING([for atomic builtins for short]) > - if AC_TRY_EVAL(ac_compile); then > - if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_short=no > - else > - glibcxx_cv_atomic_short=yes > - fi > - fi > - AC_MSG_RESULT($glibcxx_cv_atomic_short) > - rm -f conftest* > - > - cat > conftest.$ac_ext << EOF > -[#]line __oline__ "configure" > -int main() > -{ > - // NB: _Atomic_word not necessarily int. > - typedef int atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > -} > -EOF > - > - AC_MSG_CHECKING([for atomic builtins for int]) > - if AC_TRY_EVAL(ac_compile); then > - if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_int=no > - else > - glibcxx_cv_atomic_int=yes > - fi > - fi > - AC_MSG_RESULT($glibcxx_cv_atomic_int) > - rm -f conftest* > - > - cat > conftest.$ac_ext << EOF > -[#]line __oline__ "configure" > -int main() > -{ > - typedef long long atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > -} > -EOF > - > - AC_MSG_CHECKING([for atomic builtins for long long]) > - if AC_TRY_EVAL(ac_compile); then > - if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_long_long=no > - else > - glibcxx_cv_atomic_long_long=yes > - fi > - fi > - AC_MSG_RESULT($glibcxx_cv_atomic_long_long) > - rm -f conftest* > - > fi > > CXXFLAGS="$old_CXXFLAGS" > AC_LANG_RESTORE > > - # Set atomicity_dir to builtins if all but the long long test above > passes, > + # Set atomicity_dir to builtins if the test above passes, > # or if the builtins were already chosen (e.g. by configure.host). > - if { test "$glibcxx_cv_atomic_bool" = yes \ > - && test "$glibcxx_cv_atomic_short" = yes \ > - && test "$glibcxx_cv_atomic_int" = yes; } \ > + if test "$glibcxx_cv_atomic_word" = yes \ > || test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then > AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS, 1, > - [Define if the compiler supports C++11 atomics.]) > + [Define if the compiler supports native atomics for _Atomic_word.]) > atomicity_dir=cpu/generic/atomicity_builtins > fi > > @@ -5448,8 +5290,75 @@ AC_DEFUN([GLIBCXX_ENABLE_BACKTRACE], [ > > BACKTRACE_CPPFLAGS="-D_GNU_SOURCE" > > - # libbacktrace only needs atomics for int, which we've already tested > - if test "$glibcxx_cv_atomic_int" = "yes"; then > + GLIBCXX_LANG_PUSH > + > + # libbacktrace's own configure.ac only tests atomics for int, > + # but the code actually uses atomics for size_t and pointers as well. > + if test "$atomic_builtins_link_tests" = yes; then > + > + CXXFLAGS='-O0' > + > + AC_CACHE_CHECK([for atomic builtins for libbacktrace], > + glibcxx_cv_libbacktrace_atomics, > + [AC_TRY_LINK([], [ > + int i = 0; > + int* p = &i; > + size_t s = 0; > + // backtrace_atomic_load_pointer > + void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE); > + // backtrace_atomic_load_int > + int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE); > + // backtrace_atomic_store_pointer > + __atomic_store_n(&p, &i, __ATOMIC_RELEASE); > + // backtrace_atomic_store_size_t > + __atomic_store_n(&s, s, __ATOMIC_RELEASE); > + // backtrace_atomic_store_int > + __atomic_store_n(&i, i, __ATOMIC_RELEASE); > + ], > + [glibcxx_cv_libbacktrace_atomics=yes], > + [glibcxx_cv_libbacktrace_atomics=no])]) > + > + else > + # Do asm tests. > + > + CXXFLAGS='-O0 -S' > + > + cat > conftest.$ac_ext << EOF > +[#]line __oline__ "configure" > +[#]include <stddef.h> > +int main() > +{ > + int i = 0; > + int* p = &i; > + size_t s = 0; > + // backtrace_atomic_load_pointer > + void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE); > + // backtrace_atomic_load_int > + int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE); > + // backtrace_atomic_store_pointer > + __atomic_store_n(&p, &i, __ATOMIC_RELEASE); > + // backtrace_atomic_store_size_t > + __atomic_store_n(&s, s, __ATOMIC_RELEASE); > + // backtrace_atomic_store_int > + __atomic_store_n(&i, i, __ATOMIC_RELEASE); > +} > +EOF > + > + AC_MSG_CHECKING([for atomic builtins for libbacktrace]) > + if AC_TRY_EVAL(ac_compile); then > + if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > + glibcxx_cv_libbacktrace_atomics=no > + else > + glibcxx_cv_libbacktrace_atomics=yes > + fi > + fi > + AC_MSG_RESULT($glibcxx_cv_libbacktrace_atomics) > + rm -f conftest* > + fi > + > + GLIBCXX_LANG_POP > + > + if test "$glibcxx_cv_libbacktrace_atomics" = yes; then > BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1" > fi > > diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in > index 77bbaf1beaa..ed067717a20 100644 > --- a/libstdc++-v3/config.h.in > +++ b/libstdc++-v3/config.h.in > @@ -643,7 +643,7 @@ > <cwchar> in namespace std for C++98. */ > #undef _GLIBCXX98_USE_C99_WCHAR > > -/* Define if the compiler supports C++11 atomics. */ > +/* Define if the compiler supports native atomics for _Atomic_word. */ > #undef _GLIBCXX_ATOMIC_BUILTINS > > /* Define if global objects can be aligned to > diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure > index 819a1d82876..e084c59742f 100755 > --- a/libstdc++-v3/configure > +++ b/libstdc++-v3/configure > @@ -15989,7 +15989,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu > > old_CXXFLAGS="$CXXFLAGS" > > - # Do link tests if possible, instead asm tests, limited to some > platforms > + # Do link tests if possible, otherwise asm tests. Limited to some > platforms > # see discussion in PR target/40134, PR libstdc++/40133 and the thread > # starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html > atomic_builtins_link_tests=no > @@ -16002,326 +16002,77 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu > esac > fi > > - if test x$atomic_builtins_link_tests = xyes; then > + if test "$atomic_builtins_link_tests" = yes; then > > - # Do link tests. > + # Do link tests. > > - CXXFLAGS="$CXXFLAGS -fno-exceptions" > + CXXFLAGS="$CXXFLAGS -fno-exceptions" > > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for bool" >&5 > -$as_echo_n "checking for atomic builtins for bool... " >&6; } > -if ${glibcxx_cv_atomic_bool+:} false; then : > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for _Atomic_word" >&5 > +$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; } > +if ${glibcxx_cv_atomic_word+:} false; then : > $as_echo_n "(cached) " >&6 > else > - > - if test x$gcc_no_link = xyes; then > + if test x$gcc_no_link = xyes; then > as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." > "$LINENO" 5 > fi > cat confdefs.h - <<_ACEOF >conftest.$ac_ext > /* end confdefs.h. */ > - > +#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h" > int > main () > { > -typedef bool atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - // N.B. __atomic_fetch_add is not supported for bool. > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > +_Atomic_word a = 0, b; > + b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL); > ; > return 0; > } > _ACEOF > if ac_fn_cxx_try_link "$LINENO"; then : > - glibcxx_cv_atomic_bool=yes > + glibcxx_cv_atomic_word=yes > else > - glibcxx_cv_atomic_bool=no > + glibcxx_cv_atomic_word=no > fi > rm -f core conftest.err conftest.$ac_objext \ > conftest$ac_exeext conftest.$ac_ext > - > fi > -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool" > >&5 > -$as_echo "$glibcxx_cv_atomic_bool" >&6; } > - > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for short" >&5 > -$as_echo_n "checking for atomic builtins for short... " >&6; } > -if ${glibcxx_cv_atomic_short+:} false; then : > - $as_echo_n "(cached) " >&6 > -else > - > - if test x$gcc_no_link = xyes; then > - as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." > "$LINENO" 5 > -fi > -cat confdefs.h - <<_ACEOF >conftest.$ac_ext > -/* end confdefs.h. */ > - > -int > -main () > -{ > -typedef short atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - ; > - return 0; > -} > -_ACEOF > -if ac_fn_cxx_try_link "$LINENO"; then : > - glibcxx_cv_atomic_short=yes > -else > - glibcxx_cv_atomic_short=no > -fi > -rm -f core conftest.err conftest.$ac_objext \ > - conftest$ac_exeext conftest.$ac_ext > - > -fi > -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_atomic_short" >&5 > -$as_echo "$glibcxx_cv_atomic_short" >&6; } > - > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for int" >&5 > -$as_echo_n "checking for atomic builtins for int... " >&6; } > -if ${glibcxx_cv_atomic_int+:} false; then : > - $as_echo_n "(cached) " >&6 > -else > - > - if test x$gcc_no_link = xyes; then > - as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." > "$LINENO" 5 > -fi > -cat confdefs.h - <<_ACEOF >conftest.$ac_ext > -/* end confdefs.h. */ > - > -int > -main () > -{ > -typedef int atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - ; > - return 0; > -} > -_ACEOF > -if ac_fn_cxx_try_link "$LINENO"; then : > - glibcxx_cv_atomic_int=yes > -else > - glibcxx_cv_atomic_int=no > -fi > -rm -f core conftest.err conftest.$ac_objext \ > - conftest$ac_exeext conftest.$ac_ext > - > -fi > -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_int" > >&5 > -$as_echo "$glibcxx_cv_atomic_int" >&6; } > - > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for long long" >&5 > -$as_echo_n "checking for atomic builtins for long long... " >&6; } > -if ${glibcxx_cv_atomic_long_long+:} false; then : > - $as_echo_n "(cached) " >&6 > -else > - > - if test x$gcc_no_link = xyes; then > - as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." > "$LINENO" 5 > -fi > -cat confdefs.h - <<_ACEOF >conftest.$ac_ext > -/* end confdefs.h. */ > - > -int > -main () > -{ > -typedef long long atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - ; > - return 0; > -} > -_ACEOF > -if ac_fn_cxx_try_link "$LINENO"; then : > - glibcxx_cv_atomic_long_long=yes > -else > - glibcxx_cv_atomic_long_long=no > -fi > -rm -f core conftest.err conftest.$ac_objext \ > - conftest$ac_exeext conftest.$ac_ext > - > -fi > -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_atomic_long_long" >&5 > -$as_echo "$glibcxx_cv_atomic_long_long" >&6; } > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_word" > >&5 > +$as_echo "$glibcxx_cv_atomic_word" >&6; } > > else > + # Do asm tests. > > - # Do asm tests. > + # Compile unoptimized. > + CXXFLAGS='-O0 -S' > > - # Compile unoptimized. > - CXXFLAGS='-O0 -S' > - > - # Fake what AC_TRY_COMPILE does. > + # Fake what AC_TRY_COMPILE does. > > cat > conftest.$ac_ext << EOF > -#line 16185 "configure" > +#line 16051 "configure" > +#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h" > int main() > { > - typedef bool atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - // N.B. __atomic_fetch_add is not supported for bool. > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > + _Atomic_word a = 0, b; > + b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL); > } > EOF > > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for bool" >&5 > -$as_echo_n "checking for atomic builtins for bool... " >&6; } > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for _Atomic_word" >&5 > +$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; } > if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; > } >&5 > (eval $ac_compile) 2>&5 > ac_status=$? > $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 > test $ac_status = 0; }; then > if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_bool=no > + glibcxx_cv_atomic_word=no > else > - glibcxx_cv_atomic_bool=yes > + glibcxx_cv_atomic_word=yes > fi > fi > - { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_atomic_bool" >&5 > -$as_echo "$glibcxx_cv_atomic_bool" >&6; } > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_atomic_word" >&5 > +$as_echo "$glibcxx_cv_atomic_word" >&6; } > rm -f conftest* > - > - cat > conftest.$ac_ext << EOF > -#line 16220 "configure" > -int main() > -{ > - typedef short atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > -} > -EOF > - > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for short" >&5 > -$as_echo_n "checking for atomic builtins for short... " >&6; } > - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; > } >&5 > - (eval $ac_compile) 2>&5 > - ac_status=$? > - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 > - test $ac_status = 0; }; then > - if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_short=no > - else > - glibcxx_cv_atomic_short=yes > - fi > - fi > - { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_atomic_short" >&5 > -$as_echo "$glibcxx_cv_atomic_short" >&6; } > - rm -f conftest* > - > - cat > conftest.$ac_ext << EOF > -#line 16255 "configure" > -int main() > -{ > - // NB: _Atomic_word not necessarily int. > - typedef int atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > -} > -EOF > - > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for int" >&5 > -$as_echo_n "checking for atomic builtins for int... " >&6; } > - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; > } >&5 > - (eval $ac_compile) 2>&5 > - ac_status=$? > - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 > - test $ac_status = 0; }; then > - if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_int=no > - else > - glibcxx_cv_atomic_int=yes > - fi > - fi > - { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_atomic_int" >&5 > -$as_echo "$glibcxx_cv_atomic_int" >&6; } > - rm -f conftest* > - > - cat > conftest.$ac_ext << EOF > -#line 16291 "configure" > -int main() > -{ > - typedef long long atomic_type; > - atomic_type c1; > - atomic_type c2; > - atomic_type c3(0); > - __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED); > - __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL, > - __ATOMIC_RELAXED); > - __atomic_test_and_set(&c1, __ATOMIC_RELAXED); > - __atomic_load_n(&c1, __ATOMIC_RELAXED); > - > - return 0; > -} > -EOF > - > - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for long long" >&5 > -$as_echo_n "checking for atomic builtins for long long... " >&6; } > - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; > } >&5 > - (eval $ac_compile) 2>&5 > - ac_status=$? > - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 > - test $ac_status = 0; }; then > - if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > - glibcxx_cv_atomic_long_long=no > - else > - glibcxx_cv_atomic_long_long=yes > - fi > - fi > - { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_atomic_long_long" >&5 > -$as_echo "$glibcxx_cv_atomic_long_long" >&6; } > - rm -f conftest* > - > fi > > CXXFLAGS="$old_CXXFLAGS" > @@ -16332,11 +16083,9 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS > $CPPFLAGS $LDFLAGS conftest.$ac_ext $ > ac_compiler_gnu=$ac_cv_c_compiler_gnu > > > - # Set atomicity_dir to builtins if all but the long long test above > passes, > + # Set atomicity_dir to builtins if the test above passes, > # or if the builtins were already chosen (e.g. by configure.host). > - if { test "$glibcxx_cv_atomic_bool" = yes \ > - && test "$glibcxx_cv_atomic_short" = yes \ > - && test "$glibcxx_cv_atomic_int" = yes; } \ > + if test "$glibcxx_cv_atomic_word" = yes \ > || test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then > > $as_echo "#define _GLIBCXX_ATOMIC_BUILTINS 1" >>confdefs.h > @@ -16445,7 +16194,7 @@ $as_echo "mutex" >&6; } > # unnecessary for this test. > > cat > conftest.$ac_ext << EOF > -#line 16448 "configure" > +#line 16197 "configure" > int main() > { > _Decimal32 d1; > @@ -16487,7 +16236,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu > # unnecessary for this test. > > cat > conftest.$ac_ext << EOF > -#line 16490 "configure" > +#line 16239 "configure" > template<typename T1, typename T2> > struct same > { typedef T2 type; }; > @@ -53788,8 +53537,105 @@ fi > > BACKTRACE_CPPFLAGS="-D_GNU_SOURCE" > > - # libbacktrace only needs atomics for int, which we've already tested > - if test "$glibcxx_cv_atomic_int" = "yes"; then > + GLIBCXX_LANG_PUSH > + > + # libbacktrace's own configure.ac only tests atomics for int, > + # but the code actually uses atomics for size_t and pointers as well. > + if test "$atomic_builtins_link_tests" = yes; then > + > + CXXFLAGS='-O0' > + > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for libbacktrace" >&5 > +$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; } > +if ${glibcxx_cv_libbacktrace_atomics+:} false; then : > + $as_echo_n "(cached) " >&6 > +else > + if test x$gcc_no_link = xyes; then > + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." > "$LINENO" 5 > +fi > +cat confdefs.h - <<_ACEOF >conftest.$ac_ext > +/* end confdefs.h. */ > + > +int > +main () > +{ > + > + int i = 0; > + int* p = &i; > + size_t s = 0; > + // backtrace_atomic_load_pointer > + void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE); > + // backtrace_atomic_load_int > + int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE); > + // backtrace_atomic_store_pointer > + __atomic_store_n(&p, &i, __ATOMIC_RELEASE); > + // backtrace_atomic_store_size_t > + __atomic_store_n(&s, s, __ATOMIC_RELEASE); > + // backtrace_atomic_store_int > + __atomic_store_n(&i, i, __ATOMIC_RELEASE); > + > + ; > + return 0; > +} > +_ACEOF > +if ac_fn_c_try_link "$LINENO"; then : > + glibcxx_cv_libbacktrace_atomics=yes > +else > + glibcxx_cv_libbacktrace_atomics=no > +fi > +rm -f core conftest.err conftest.$ac_objext \ > + conftest$ac_exeext conftest.$ac_ext > +fi > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_libbacktrace_atomics" >&5 > +$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; } > + > + else > + # Do asm tests. > + > + CXXFLAGS='-O0 -S' > + > + cat > conftest.$ac_ext << EOF > +#line 53598 "configure" > +#include <stddef.h> > +int main() > +{ > + int i = 0; > + int* p = &i; > + size_t s = 0; > + // backtrace_atomic_load_pointer > + void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE); > + // backtrace_atomic_load_int > + int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE); > + // backtrace_atomic_store_pointer > + __atomic_store_n(&p, &i, __ATOMIC_RELEASE); > + // backtrace_atomic_store_size_t > + __atomic_store_n(&s, s, __ATOMIC_RELEASE); > + // backtrace_atomic_store_int > + __atomic_store_n(&i, i, __ATOMIC_RELEASE); > +} > +EOF > + > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins > for libbacktrace" >&5 > +$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; } > + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; > } >&5 > + (eval $ac_compile) 2>&5 > + ac_status=$? > + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 > + test $ac_status = 0; }; then > + if grep __atomic_ conftest.s >/dev/null 2>&1 ; then > + glibcxx_cv_libbacktrace_atomics=no > + else > + glibcxx_cv_libbacktrace_atomics=yes > + fi > + fi > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $glibcxx_cv_libbacktrace_atomics" >&5 > +$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; } > + rm -f conftest* > + fi > + > + GLIBCXX_LANG_POP > + > + if test "$glibcxx_cv_libbacktrace_atomics" = yes; then > BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1" > fi > > diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host > index 253e5a9ad0d..3cd1bb1c6ee 100644 > --- a/libstdc++-v3/configure.host > +++ b/libstdc++-v3/configure.host > @@ -180,7 +180,7 @@ esac > > > # Set specific CPU overrides for atomicity_dir. > -# This can be over-ridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS. > +# This can be overridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS. > # THIS TABLE IS SORTED. KEEP IT THAT WAY. > if test -f ${glibcxx_srcdir}/config/${cpu_include_dir}/atomicity.h ; then > atomicity_dir=$cpu_include_dir > -- > 2.49.0 > >