From 88bbf875bd90ad21c0486113a757895bbc66635c 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 | 17 +++++++++++-- 2 files changed, 39 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 56d7db55a0..50c33846ba 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-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -26,6 +26,19 @@ atomic_uint *g_atomic32; atomic_ushort *g_atomic16; atomic_uchar *g_atomic8; +TEST_CASE("stdatomic - test_atomic_flag", "[newlib_stdatomic]") +{ + bool x8 = 0; + g_atomic8 = heap_caps_calloc(sizeof(*g_atomic8), 1, MALLOC_CAP_DEFAULT); + + 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); + free(g_atomic8); +} + TEST_CASE("stdatomic - test_64bit_atomics", "[newlib_stdatomic]") { unsigned long long x64 = 0; @@ -262,7 +275,7 @@ TEST_CASE("stdatomic - test_" #NAME, "[newlib_stdatomic]") free(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) \