diff --git a/core/lib/atomic_c11.c b/core/lib/atomic_c11.c index 0a0e0b4ca1..4f73061c2a 100644 --- a/core/lib/atomic_c11.c +++ b/core/lib/atomic_c11.c @@ -268,6 +268,7 @@ TEMPLATE_ATOMIC_OP_FETCH_N(nand, &, 8, ~) /* __atomic_nand_fetch_8 */ #pragma redefine_extname __atomic_store_c __atomic_store #pragma redefine_extname __atomic_exchange_c __atomic_exchange #pragma redefine_extname __atomic_compare_exchange_c __atomic_compare_exchange +#pragma redefine_extname __atomic_test_and_set_c __atomic_test_and_set /** * @brief Atomic generic load @@ -376,6 +377,36 @@ bool __atomic_compare_exchange_c(size_t len, void *ptr, void *expected, irq_restore(mask); return ret; } + +/** + * This built-in function performs an atomic test-and-set operation on the byte + * at *ptr. The byte is set to some implementation defined nonzero “set” value + * and the return value is true if and only if the previous contents were “set”. + * It should be only used for operands of type bool or char. For other types + * only part of the value may be set. + * + * All memory orders are valid. + * + * @see https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html#index-_005f_005fatomic_005ftest_005fand_005fset + * + * @param[in,out] ptr Value to test and then set + * @param[in] memorder Ignored + * + * @retval true The value @p ptr was already set + * @retval false The value @p ptr was previously unset + * + * @pre @p ptr points to a value of `bool` + */ +bool __atomic_test_and_set_c(void *ptr, int memorder) +{ + (void)memorder; + bool *target = ptr; + unsigned mask = irq_disable(); + bool retval = *target; + *target = true; + irq_restore(mask); + return retval; +} #if !defined(__llvm__) && !defined(__clang__) /* Memory barrier helper function, for platforms without barrier instructions */ void __sync_synchronize(void) __attribute__((__weak__));