diff --git a/components/newlib/stdatomic.c b/components/newlib/stdatomic.c index 993fcd1ac2..bbd2d17e80 100644 --- a/components/newlib/stdatomic.c +++ b/components/newlib/stdatomic.c @@ -75,6 +75,24 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED; #endif // SOC_CPU_CORES_NUM +#ifdef __clang__ +// Clang doesn't allow to define "__sync_*" atomics. The workaround is to define function with name "__sync_*_builtin", +// which implements "__sync_*" atomic functionality and use asm directive to set the value of symbol "__sync_*" to the name +// of defined function. + +#define CLANG_ATOMIC_SUFFIX(name_) name_ ## _builtin +#define CLANG_DECLARE_ALIAS(name_) \ +__asm__(".type " # name_ ", @function\n" \ + ".global " #name_ "\n" \ + ".equ " #name_ ", " #name_ "_builtin"); + +#else // __clang__ + +#define CLANG_ATOMIC_SUFFIX(name_) name_ +#define CLANG_DECLARE_ALIAS(name_) + +#endif // __clang__ + #define ATOMIC_LOAD(n, type) type __atomic_load_ ## n (const type* mem, int memorder) \ { \ unsigned state = _ATOMIC_ENTER_CRITICAL(); \ @@ -158,12 +176,14 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED; return ret; \ } -#define SYNC_FETCH_OP(op, n, type) type __sync_fetch_and_ ## op ##_ ## n (type* ptr, type value) \ -{ \ - return __atomic_fetch_ ## op ##_ ## n (ptr, value, __ATOMIC_SEQ_CST); \ -} -#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool __sync_bool_compare_and_swap_ ## n (type *ptr, type oldval, type newval) \ +#define SYNC_FETCH_OP(op, n, type) type CLANG_ATOMIC_SUFFIX(__sync_fetch_and_ ## op ##_ ## n) (type* ptr, type value) \ +{ \ + return __atomic_fetch_ ## op ##_ ## n (ptr, value, __ATOMIC_SEQ_CST); \ +} \ +CLANG_DECLARE_ALIAS( __sync_fetch_and_ ## op ##_ ## n ) + +#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool CLANG_ATOMIC_SUFFIX(__sync_bool_compare_and_swap_ ## n) (type *ptr, type oldval, type newval) \ { \ bool ret = false; \ unsigned state = _ATOMIC_ENTER_CRITICAL(); \ @@ -173,9 +193,10 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED; } \ _ATOMIC_EXIT_CRITICAL(state); \ return ret; \ -} +} \ +CLANG_DECLARE_ALIAS( __sync_bool_compare_and_swap_ ## n ) -#define SYNC_VAL_CMP_EXCHANGE(n, type) type __sync_val_compare_and_swap_ ## n (type *ptr, type oldval, type newval) \ +#define SYNC_VAL_CMP_EXCHANGE(n, type) type CLANG_ATOMIC_SUFFIX(__sync_val_compare_and_swap_ ## n) (type *ptr, type oldval, type newval) \ { \ unsigned state = _ATOMIC_ENTER_CRITICAL(); \ type ret = *ptr; \ @@ -184,7 +205,9 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED; } \ _ATOMIC_EXIT_CRITICAL(state); \ return ret; \ -} +} \ +CLANG_DECLARE_ALIAS( __sync_val_compare_and_swap_ ## n ) + #if !HAS_ATOMICS_32