From afb474f1ec0b874cfd400beadc9ead95f11d6a03 Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Thu, 20 Oct 2022 16:36:41 +0800 Subject: [PATCH 1/4] [GNUC] Use __sync builtin instead of MSVC intrinsic The _InterlockedCompareExchange128 intrinsic is missing in mingw-w64, so instead use the __sync_bool_compare_and_swap builtin in GCC-compatible compilers. --- strings/base_activation.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index 8d8eb5e92..80c4215e4 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -281,7 +281,12 @@ namespace winrt::impl object_and_count current_value{ pointer_value, 0 }; #if defined _WIN64 - if (1 == _InterlockedCompareExchange128((int64_t*)this, 0, 0, (int64_t*)¤t_value)) +#if defined(__GNUC__) + bool exchanged = __sync_bool_compare_and_swap((__int128*)this, *(__int128*)¤t_value, (__int128)0); +#else + bool exchanged = 1 == _InterlockedCompareExchange128((int64_t*)this, 0, 0, (int64_t*)¤t_value); +#endif + if (exchanged) { pointer_value->Release(); } From d10e798b2ffb23a6607190bc5d7a5cb60821768d Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Thu, 20 Oct 2022 16:46:16 +0800 Subject: [PATCH 2/4] [GNUC][ARM] Assemble `dmb ish` instead of using __dmb intrinsic The constants _ARM_BARRIER_ISH and _ARM64_BARRIER_ISH are missing in mingw-w64. Use inline assembly to insert the instruction instead. --- strings/base_activation.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index 80c4215e4..d63f167f7 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -128,7 +128,9 @@ WINRT_EXPORT namespace winrt #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#if defined _M_ARM +#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) +#define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER __asm__ __volatile__ ("dmb ish"); +#elif defined _M_ARM #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM_BARRIER_ISH)); #elif defined _M_ARM64 #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM64_BARRIER_ISH)); From 61875088e49aeaf933deb0bc55d52011c1803b09 Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Thu, 20 Oct 2022 16:52:15 +0800 Subject: [PATCH 3/4] [GNUC] Don't use __iso_volatile_load32/64 These intrinsics are missing in mingw-w64 and GCC-compatible compilers. The __iso_volatile_load intrinsics is intended to tell MSVC to use the ISO standard C++ non-atomic volatile load, instead of the MSVC extension which adds other guarantees. For GCC-compatible compilers, the ISO standard volatile load is already the default, so there is no need to use these intrinsics. --- strings/base_activation.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/strings/base_activation.h b/strings/base_activation.h index d63f167f7..351de04ce 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -145,7 +145,11 @@ namespace winrt::impl _ReadWriteBarrier(); return result; #elif defined _M_ARM || defined _M_ARM64 +#if defined(__GNUC__) + int32_t const result = *target; +#else int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); +#endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; #else @@ -161,7 +165,11 @@ namespace winrt::impl _ReadWriteBarrier(); return result; #elif defined _M_ARM64 +#if defined(__GNUC__) + int32_t const result = *target; +#else int64_t const result = __iso_volatile_load64(target); +#endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; #else From dae26a4cb1b41b99dcbf1bbd3706f224a331fb6c Mon Sep 17 00:00:00 2001 From: Alvin Wong Date: Fri, 21 Oct 2022 17:43:56 +0800 Subject: [PATCH 4/4] Fix copy-and-paste error --- strings/base_activation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index 351de04ce..d77b8f5d8 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -166,7 +166,7 @@ namespace winrt::impl return result; #elif defined _M_ARM64 #if defined(__GNUC__) - int32_t const result = *target; + int64_t const result = *target; #else int64_t const result = __iso_volatile_load64(target); #endif