libstdc++: Fix test_and_acquire / set_and_release for EABI guard variables
authorJonathan Wakely <jwakely@redhat.com>
Wed, 30 Sep 2020 20:14:43 +0000 (21:14 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Wed, 30 Sep 2020 20:14:43 +0000 (21:14 +0100)
commitd1ac0f0dfba9d04bcf38132b3ae45db572e7f1ea
treee5b59a47dd1ec16e2f9c89e881c82f3b54455aac
parent7dbc7ad524a540e34ce25d120d0968f36c571bbb
libstdc++: Fix test_and_acquire / set_and_release for EABI guard variables

The default definitions of _GLIBCXX_GUARD_TEST_AND_ACQUIRE and
_GLIBCXX_GUARD_SET_AND_RELEASE in libsupc++/guard.cc only work for the
generic (IA64) ABI, because they test/set the first byte of the guard
variable. For EABI we need to use the least significant bit, which means
using the first byte is wrong for big endian targets.

This has been wrong since r224411, but previously it only caused poor
performance. The _GLIBCXX_GUARD_TEST_AND_ACQUIRE at the very start of
__cxa_guard_acquire would always return false even if the initialization
was actually complete. Before my r11-3484 change the atomic compare
exchange would have loaded the correct value, and then returned 0 as
expected when the initialization is complete. After my change, in the
single-threaded case there is no redundant check for init being
complete, because I foolishly assumed that the check at the start of the
function actually worked.

The default definition of _GLIBCXX_GUARD_SET_AND_RELEASE is also wrong
for big endian EABI, but appears to work because it sets the wrong bit
but then the buggy TEST_AND_ACQUIRE tests that wrong bit as well. Also,
the buggy SET_AND_RELEASE macro is only used for targets with threads
enabled but no futex syscalls.

This should fix the regressions introduced by my patch, by defining
custom versions of the TEST_AND_ACQUIRE and SET_AND_RELEASE macros that
are correct for EABI.

libstdc++-v3/ChangeLog:

* config/cpu/arm/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST_AND_ACQUIRE):
(_GLIBCXX_GUARD_SET_AND_RELEASE): Define for EABI.
libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h