From cc47810d36f6dab28ff1a8977d4a5c5996f6b815 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 30 Jun 2019 23:26:16 -0700 Subject: [PATCH] Fixed bug 4683 - SDL_atomic infinite recursion on armv6/armv5 w/ thumb The real problem is that SDL_atomic.c was built in thumb mode instead of ARM mode, which is required to use the mcr instruction on ARM platforms. Added a compiler error to catch this case so we don't generate code that does infinite recursion. I also added a potentially better way to handle things on Linux ARM platforms, based on comments in the Chromium headers, which we can try out after 2.0.10 ships. --- include/SDL_atomic.h | 17 +++++++++++++++++ src/atomic/SDL_atomic.c | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/include/SDL_atomic.h b/include/SDL_atomic.h index 687455f1fae5c..bea071c67d93a 100644 --- a/include/SDL_atomic.h +++ b/include/SDL_atomic.h @@ -162,6 +162,22 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__GNUC__) && defined(__arm__) +#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */ +/* Information from: + https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19 + + The Linux kernel provides a helper function which provides the right code for a memory barrier, + hard-coded at address 0xffff0fa0 +*/ +typedef void (*SDL_KernelMemoryBarrierFunc)(); +#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#elif 0 /* defined(__QNXNTO__) */ +#include + +#define SDL_MemoryBarrierRelease() __cpu_membarrier() +#define SDL_MemoryBarrierAcquire() __cpu_membarrier() +#else #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") @@ -177,6 +193,7 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #else #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") +#endif /* __LINUX__ || __ANDROID__ */ #endif /* __GNUC__ && __arm__ */ #else #if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c index d0c915dd96e38..a368e305e54af 100644 --- a/src/atomic/SDL_atomic.c +++ b/src/atomic/SDL_atomic.c @@ -289,6 +289,10 @@ SDL_AtomicGetPtr(void **a) #endif } +#ifdef __thumb__ +#error This file should be built in arm mode so the mcr instruction is available for memory barriers +#endif + void SDL_MemoryBarrierReleaseFunction(void) {