From 3b1916ad06eb336a24371666890e3da8dfbd95b0 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Mon, 3 Feb 2025 16:02:32 +0700 Subject: [PATCH] fix(newlib): fix __atomic_test_and_set to ensure atomicity Before the change described in https://gcc.gnu.org/pipermail/gcc-patches/2023-September/631393.html it appeared that inlining built-in GCC function __atomic_test_and_set() was incorrect. It resulted in a non-atomic write. For GCC toolchains which do not have such patch yet, this commit fixes __atomic_test_and_set to be atomic in IDF's builds. --- .../newlib/platform_include/stdatomic.h | 24 +++++++++++++++++++ .../test_apps/newlib/main/test_stdatomic.c | 16 +++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 components/newlib/platform_include/stdatomic.h diff --git a/components/newlib/platform_include/stdatomic.h b/components/newlib/platform_include/stdatomic.h new file mode 100644 index 0000000000..8ba259d527 --- /dev/null +++ b/components/newlib/platform_include/stdatomic.h @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include_next "stdatomic.h" +#ifndef __clang__ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline bool __atomic_test_and_set(volatile void *ptr, int memorder) +{ + return __atomic_exchange_1((bool *)ptr, true, memorder); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/newlib/test_apps/newlib/main/test_stdatomic.c b/components/newlib/test_apps/newlib/main/test_stdatomic.c index 602dc45c03..6a7b734f8b 100644 --- a/components/newlib/test_apps/newlib/main/test_stdatomic.c +++ b/components/newlib/test_apps/newlib/main/test_stdatomic.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -21,6 +21,18 @@ atomic_ushort g_atomic16; atomic_uchar g_atomic8; +TEST_CASE("stdatomic - test_atomic_flag", "[newlib_stdatomic]") +{ + bool x8 = 0; + g_atomic8 = 0; + + x8 = atomic_flag_test_and_set(&g_atomic8); + TEST_ASSERT_EQUAL_HEX8(0x00, x8); + TEST_ASSERT_EQUAL_HEX8(0x01, g_atomic8); + atomic_flag_clear(&g_atomic8); + TEST_ASSERT_EQUAL_HEX8(0x00, g_atomic8); +} + TEST_CASE("stdatomic - test_64bit_atomics", "[newlib_stdatomic]") { unsigned long long x64 = 0; @@ -248,7 +260,7 @@ TEST_CASE("stdatomic - test_" #NAME, "[newlib_stdatomic]") TEST_ASSERT_EQUAL##ASSERT_SUFFIX((FINAL), var_##NAME); \ } -// Note that the assert at the end is doing an excat bitwise comparison. +// Note that the assert at the end is doing an exact bitwise comparison. // This easily can fail due to rounding errors. However, there is currently // no corresponding Unity assert macro for long double. USE THIS WITH CARE! #define TEST_RACE_OPERATION_LONG_DOUBLE(NAME, LHSTYPE, PRE, POST, INIT, FINAL) \