https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119667

--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <r...@gcc.gnu.org>:

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

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

    libstdc++: Rewrite atomic builtin checks [PR70560]

    Currently the GLIBCXX_ENABLE_ATOMIC_BUILTINS macro checks for a variety
    of __atomic built-ins for bool, short and int. If all those checks pass,
    then it defines _GLIBCXX_ATOMIC_BUILTINS and uses the definitions from
    config/cpu/generic/atomicity_builtins/atomicity.h for the non-inline
    versions of __exchange_and_add and __atomic_add that get compiled into
    libsupc++.

    However, the config/cpu/generic/atomicity_builtins/atomicity.h
    definitions only depend on __atomic_fetch_add not on
    __atomic_test_and_set or __atomic_compare_exchange. And they only
    operate on a variable of type _Atomic word, which is not necessarily one
    of bool, short or int (e.g. for sparcv9 _Atomic_word is 64-bit long).

    This means that for a target where _Atomic_word is int but there are no
    1-byte or 2-byte atomic instructions, GLIBCXX_ENABLE_ATOMIC_BUILTINS
    will fail the checks for bool and short and not define the macro
    _GLIBCXX_ATOMIC_BUILTINS. That means that we will use a single global
    mutex for reference counting in the COW std::string and std::locale,
    even though we could use __atomic_fetch_add to do it lock-free.

    This commit removes most of the GLIBCXX_ENABLE_ATOMIC_BUILTINS checks,
    so that it only checks __atomic_fetch_add on _Atomic_word. The macro
    defined by GLIBCXX_ENABLE_ATOMIC_BUILTINS is renamed from
    _GLIBCXX_ATOMIC_BUILTINS to _GLIBCXX_ATOMIC_WORD_BUILTINS to better
    reflect what it really means. This will enable the inline versions of
    __exchange_and_add and __atomic_add for more targets. This is not an ABI
    change, because targets which didn't previously use the inline
    definitions of those functions made non-inlined calls to the functions
    in the library. If the definitions of those functions now start using
    atomics, that doesn't change the semantics for the code calling those
    functions.

    On affected targets, new code compiled after this change will see the
    _GLIBCXX_ATOMIC_WORD_BUILTINS macro and so will use the always-inline
    versions of __exchange_and_add and __atomic_add, which use
    __atomic_fetch_add directly. That is also compatible with older code
    which still calls the non-inline definitions, because those non-inline
    definitions now also use __atomic_fetch_add.

    The only configuration where this could be an ABI change is for a target
    which previously defined _GLIBCXX_ATOMIC_BUILTINS (because all the
    atomic built-ins for bool, short and int are supported), but which
    defines _Atomic_word to some other type for which __atomic_fetch_add is
    /not/ supported. Such a target would have called the inline functions
    using __atomic_fetch_add, which would actually have depended on
    libatomic (which is what the configure checks were supposed to
    prevent!).  After this change, that target would not define the new
    macro, _GLIBCXX_ATOMIC_WORD_BUILTINS, and so would make non-inline calls
    into the library where __exchange_and_add and __atomic_add would use the
    global mutex. That would be an ABI break. I don't consider that a
    realistic scenario, because it wouldn't have made any sense to define
    _Atomic_word to a wider type than int, when doing so would have required
    libatomic to make libstdc++.so work. Surely such a target would have
    just used int for its _Atomic_word type.

    The GLIBCXX_ENABLE_BACKTRACE macro currently uses the
    glibcxx_ac_atomic_int variable defined by the checks that this commit
    removes from GLIBCXX_ENABLE_ATOMIC_BUILTINS. That wasn't a good check
    anyway, because libbacktrace actually depends on atomic loads+stores for
    pointers as well as int, and for atomic stores for size_t. This commit
    replaces the glibcxx_ac_atomic_int check with a proper test for all the
    required atomic operations on all three of int, void* and size_t. This
    ensures that the libbacktrace code used for std::stacktrace will either
    use native atomics, or implement those loads and stores only in terms of
    __sync_bool_compare_and_swap (possibly requiring that to come from
    libatomic or elsewhere).

    libstdc++-v3/ChangeLog:

            PR libstdc++/70560
            PR libstdc++/119667
            * acinclude.m4 (GLIBCXX_ENABLE_ATOMIC_BUILTINS): Only check for
            __atomic_fetch_add on _Atomic_word. Define new macro
            _GLIBCXX_ATOMIC_WORD_BUILTINS and stop defining macro
            _GLIBCXX_ATOMIC_BUILTINS.
            (GLIBCXX_ENABLE_BACKTRACE): Check for __atomic_load_n and
            __atomic_store_n on int, void* and size_t.
            * config.h.in: Regenerate.
            * configure: Regenerate.
            * configure.host: Fix typo in comment.
            * include/ext/atomicity.h (__exchange_and_add, __atomic_add):
            Depend on _GLIBCXX_ATOMIC_WORD_BUILTINS macro instead of old
            _GLIBCXX_ATOMIC_BUILTINS macro.

Reply via email to