From d1ac0f0dfba9d04bcf38132b3ae45db572e7f1ea Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 30 Sep 2020 21:14:43 +0100 Subject: [PATCH] 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 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h b/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h index 4eb43c8373c..4fb34869f8a 100644 --- a/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h +++ b/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h @@ -39,7 +39,7 @@ namespace __cxxabiv1 #ifdef __ARM_EABI__ // The ARM EABI uses the least significant bit of a 32-bit - // guard variable. */ + // guard variable. #define _GLIBCXX_GUARD_TEST(x) ((*(x) & 1) != 0) #define _GLIBCXX_GUARD_SET(x) *(x) = 1 #define _GLIBCXX_GUARD_BIT 1 @@ -47,6 +47,11 @@ namespace __cxxabiv1 #define _GLIBCXX_GUARD_WAITING_BIT __guard_test_bit (2, 1) typedef int __guard; +#define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(x) \ + _GLIBCXX_GUARD_TEST(__atomic_load_n(x, __ATOMIC_ACQUIRE)) +#define _GLIBCXX_GUARD_SET_AND_RELEASE(x) \ + __atomic_store_n(x, 1, __ATOMIC_RELEASE) + // We also want the element size in array cookies. #define _GLIBCXX_ELTSIZE_IN_COOKIE 1 -- 2.30.2