From 6319a5636170774ec4532df2d08c2f4f352261fb Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Thu, 12 Mar 2026 20:18:06 +0800 Subject: [PATCH 1/6] include/atomic: add atomic_ptr_t type and operations Add atomic_ptr_t that maps to atomic_t on 32-bit platforms and atomic64_t on 64-bit platforms based on UINTPTR_MAX. All atomic_ptr_xx operations (set, read, add, sub, and, or, xor, xchg, cmpxchg, try_cmpxchg with memory order variants) are mapped to the corresponding atomic_xx or atomic64_xx macros accordingly. Signed-off-by: Bowen Wang --- include/nuttx/atomic.h | 104 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/include/nuttx/atomic.h b/include/nuttx/atomic.h index aa381a4402ee0..dbdcfc5ea5bcc 100644 --- a/include/nuttx/atomic.h +++ b/include/nuttx/atomic.h @@ -28,6 +28,8 @@ ****************************************************************************/ #include +#include +#include /**************************************************************************** * Pre-processor Definitions @@ -155,6 +157,102 @@ #define atomic64_try_cmpxchg_relaxed(obj, expected, desired) \ atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED) +#if UINTPTR_MAX > UINT32_MAX + +#define atomic_ptr_set(obj, val) atomic64_set(obj, val) +#define atomic_ptr_set_release(obj, val) atomic64_set_release(obj, val) +#define atomic_ptr_read(obj) atomic64_read(obj) +#define atomic_ptr_read_acquire(obj) atomic64_read_acquire(obj) +#define atomic_ptr_add(obj, val) atomic64_add(obj, val) +#define atomic_ptr_add_acquire(obj, val) atomic64_add_acquire(obj, val) +#define atomic_ptr_add_release(obj, val) atomic64_add_release(obj, val) +#define atomic_ptr_add_relaxed(obj, val) atomic64_add_relaxed(obj, val) +#define atomic_ptr_sub(obj, val) atomic64_sub(obj, val) +#define atomic_ptr_sub_acquire(obj, val) atomic64_sub_acquire(obj, val) +#define atomic_ptr_sub_release(obj, val) atomic64_sub_release(obj, val) +#define atomic_ptr_sub_relaxed(obj, val) atomic64_sub_relaxed(obj, val) +#define atomic_ptr_and(obj, val) atomic64_and(obj, val) +#define atomic_ptr_and_acquire(obj, val) atomic64_and_acquire(obj, val) +#define atomic_ptr_and_release(obj, val) atomic64_and_release(obj, val) +#define atomic_ptr_and_relaxed(obj, val) atomic64_and_relaxed(obj, val) +#define atomic_ptr_or(obj, val) atomic64_or(obj, val) +#define atomic_ptr_or_acquire(obj, val) atomic64_or_acquire(obj, val) +#define atomic_ptr_or_release(obj, val) atomic64_or_release(obj, val) +#define atomic_ptr_or_relaxed(obj, val) atomic64_or_relaxed(obj, val) +#define atomic_ptr_xor(obj, val) atomic64_xor(obj, val) +#define atomic_ptr_xor_acquire(obj, val) atomic64_xor_acquire(obj, val) +#define atomic_ptr_xor_release(obj, val) atomic64_xor_release(obj, val) +#define atomic_ptr_xor_relaxed(obj, val) atomic64_xor_relaxed(obj, val) +#define atomic_ptr_xchg(obj, val) atomic64_xchg(obj, val) +#define atomic_ptr_xchg_acquire(obj, val) atomic64_xchg_acquire(obj, val) +#define atomic_ptr_xchg_release(obj, val) atomic64_xchg_release(obj, val) +#define atomic_ptr_xchg_relaxed(obj, val) atomic64_xchg_relaxed(obj, val) +#define atomic_ptr_cmpxchg(obj, expected, desired) \ + atomic64_cmpxchg(obj, expected, desired) +#define atomic_ptr_cmpxchg_acquire(obj, expected, desired) \ + atomic64_cmpxchg_acquire(obj, expected, desired) +#define atomic_ptr_cmpxchg_release(obj, expected, desired) \ + atomic64_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_cmpxchg_relaxed(obj, expected, desired) \ + atomic64_cmpxchg_relaxed(obj, expected, desired) +#define atomic_ptr_try_cmpxchg(obj, expected, desired) \ + atomic64_try_cmpxchg(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_acquire(obj, expected, desired) \ + atomic64_try_cmpxchg_acquire(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_release(obj, expected, desired) \ + atomic64_try_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_relaxed(obj, expected, desired) \ + atomic64_try_cmpxchg_relaxed(obj, expected, desired) + +#else /* UINTPTR_MAX <= UINT32_MAX */ + +#define atomic_ptr_set(obj, val) atomic_set(obj, val) +#define atomic_ptr_set_release(obj, val) atomic_set_release(obj, val) +#define atomic_ptr_read(obj) atomic_read(obj) +#define atomic_ptr_read_acquire(obj) atomic_read_acquire(obj) +#define atomic_ptr_add(obj, val) atomic_add(obj, val) +#define atomic_ptr_add_acquire(obj, val) atomic_add_acquire(obj, val) +#define atomic_ptr_add_release(obj, val) atomic_add_release(obj, val) +#define atomic_ptr_add_relaxed(obj, val) atomic_add_relaxed(obj, val) +#define atomic_ptr_sub(obj, val) atomic_sub(obj, val) +#define atomic_ptr_sub_acquire(obj, val) atomic_sub_acquire(obj, val) +#define atomic_ptr_sub_release(obj, val) atomic_sub_release(obj, val) +#define atomic_ptr_sub_relaxed(obj, val) atomic_sub_relaxed(obj, val) +#define atomic_ptr_and(obj, val) atomic_and(obj, val) +#define atomic_ptr_and_acquire(obj, val) atomic_and_acquire(obj, val) +#define atomic_ptr_and_release(obj, val) atomic_and_release(obj, val) +#define atomic_ptr_and_relaxed(obj, val) atomic_and_relaxed(obj, val) +#define atomic_ptr_or(obj, val) atomic_or(obj, val) +#define atomic_ptr_or_acquire(obj, val) atomic_or_acquire(obj, val) +#define atomic_ptr_or_release(obj, val) atomic_or_release(obj, val) +#define atomic_ptr_or_relaxed(obj, val) atomic_or_relaxed(obj, val) +#define atomic_ptr_xor(obj, val) atomic_xor(obj, val) +#define atomic_ptr_xor_acquire(obj, val) atomic_xor_acquire(obj, val) +#define atomic_ptr_xor_release(obj, val) atomic_xor_release(obj, val) +#define atomic_ptr_xor_relaxed(obj, val) atomic_xor_relaxed(obj, val) +#define atomic_ptr_xchg(obj, val) atomic_xchg(obj, val) +#define atomic_ptr_xchg_acquire(obj, val) atomic_xchg_acquire(obj, val) +#define atomic_ptr_xchg_release(obj, val) atomic_xchg_release(obj, val) +#define atomic_ptr_xchg_relaxed(obj, val) atomic_xchg_relaxed(obj, val) +#define atomic_ptr_cmpxchg(obj, expected, desired) \ + atomic_cmpxchg(obj, expected, desired) +#define atomic_ptr_cmpxchg_acquire(obj, expected, desired) \ + atomic_cmpxchg_acquire(obj, expected, desired) +#define atomic_ptr_cmpxchg_release(obj, expected, desired) \ + atomic_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_cmpxchg_relaxed(obj, expected, desired) \ + atomic_cmpxchg_relaxed(obj, expected, desired) +#define atomic_ptr_try_cmpxchg(obj, expected, desired) \ + atomic_try_cmpxchg(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_acquire(obj, expected, desired) \ + atomic_try_cmpxchg_acquire(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_release(obj, expected, desired) \ + atomic_try_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_relaxed(obj, expected, desired) \ + atomic_try_cmpxchg_relaxed(obj, expected, desired) + +#endif /* UINTPTR_MAX > UINT32_MAX */ + /**************************************************************************** * Public Types ****************************************************************************/ @@ -162,6 +260,12 @@ typedef __Atomic(int32_t) atomic_t; typedef __Atomic(int64_t) atomic64_t; +#if UINTPTR_MAX > UINT32_MAX +typedef atomic64_t atomic_ptr_t; +#else +typedef atomic_t atomic_ptr_t; +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ From 1311d1299426a1ce4a12eaf31daf0ba87db14823 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Mon, 31 Aug 2026 21:07:27 +0800 Subject: [PATCH 2/6] libc/atomic: support inline arch atomic for tricore When CONFIG_LIBC_ATOMIC_ARCH is selected, atomic.h includes arch/atomic.h which provides static inline atomic_*_4 operations using arch-specific helpers. This eliminates function call overhead for NuttX atomic API. For Tricore, the inline functions use hardware helpers (tricore_atomic_swap, tricore_atomic_cmpswap) implemented with inline assembly (swap.w, cmpswap.w), avoiding the iLLD dependency. The arch_atomic.c retains __atomic_*_4 symbols with external linkage for GCC libatomic ABI compatibility. Signed-off-by: Bowen Wang --- arch/tricore/include/atomic.h | 152 ++++++++++++++++ include/nuttx/atomic.h | 8 +- libs/libc/machine/tricore/arch_atomic.c | 230 +----------------------- 3 files changed, 162 insertions(+), 228 deletions(-) create mode 100644 arch/tricore/include/atomic.h diff --git a/arch/tricore/include/atomic.h b/arch/tricore/include/atomic.h new file mode 100644 index 0000000000000..938ddfd15b65d --- /dev/null +++ b/arch/tricore/include/atomic.h @@ -0,0 +1,152 @@ +/**************************************************************************** + * arch/tricore/include/atomic.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_TRICORE_INCLUDE_ATOMIC_H +#define __ARCH_TRICORE_INCLUDE_ATOMIC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef ARCH_ATOMIC_SPECIFIER +# define ARCH_ATOMIC_SPECIFIER static always_inline_function +#endif + +#define ARCH_ATOMIC_STORE(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + void func(volatile void *ptr, t value, int memorder) \ + { \ + tricore_atomic_swap(ptr, value); \ + } + +#define ARCH_ATOMIC_LOAD(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(const volatile void *ptr, int memorder) \ + { \ + return *(volatile t *)ptr; \ + } + +#define ARCH_ATOMIC_EXCHANGE(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(volatile void *ptr, t value, int memorder) \ + { \ + return tricore_atomic_swap(ptr, value); \ + } + +#define ARCH_ATOMIC_COMPARE_EXCHANGE(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + bool func(volatile void *ptr, volatile void *expect, \ + t desired, bool weak, int success, int failure) \ + { \ + t old; \ + \ + old = tricore_atomic_cmpswap(ptr, desired, *(t *)expect); \ + if (old == *(t *)expect) \ + { \ + return true; \ + } \ + \ + *(t *)expect = old; \ + \ + return false; \ + } + +#define ARCH_ATOMIC_FLAGS_TEST_AND_SET(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(volatile void *ptr, int memorder) \ + { \ + return tricore_atomic_swap(ptr, 1); \ + } + +#define ARCH_ATOMIC_FETCH_OP(func, t, n, op) \ + ARCH_ATOMIC_SPECIFIER \ + t func(volatile void *ptr, t value, int memorder) \ + { \ + t old_val; \ + \ + do \ + { \ + old_val = atomic_load_ ## n(ptr, memorder); \ + } \ + while (tricore_atomic_cmpswap(ptr, old_val op value, old_val) \ + != old_val); \ + \ + return old_val; \ + } + +#define ARCH_ATOMIC_DEFINE(prefix, t, n) \ + ARCH_ATOMIC_STORE(prefix ## _store_ ## n, t) \ + ARCH_ATOMIC_LOAD(prefix ## _load_ ## n, t) \ + ARCH_ATOMIC_EXCHANGE(prefix ## _exchange_ ## n, t) \ + ARCH_ATOMIC_COMPARE_EXCHANGE(prefix ## _compare_exchange_ ## n, t) \ + ARCH_ATOMIC_FLAGS_TEST_AND_SET(prefix ## _flags_test_and_set_ ## n, t) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_add_ ## n, t, n, +) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_sub_ ## n, t, n, -) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_and_ ## n, t, n, &) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_or_ ## n, t, n, |) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_xor_ ## n, t, n, ^) + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tricore_atomic_swap + ****************************************************************************/ + +always_inline_function +static uint32_t tricore_atomic_swap(volatile void *addr, uint32_t value) +{ + uint32_t res; + + __asm__ volatile ("swap.w [%1]0, %2" + : "=d"(res) : "a"(addr), "0"(value)); + return res; +} + +/**************************************************************************** + * Name: tricore_atomic_cmpswap + ****************************************************************************/ + +always_inline_function +static uint32_t tricore_atomic_cmpswap(volatile void *addr, uint32_t value, + uint32_t condition) +{ + uint64_t reg64 = value | ((uint64_t)condition << 32); + + __asm__ __volatile__ ("cmpswap.w [%1]0, %A0" + : "+d" (reg64) + : "a" (addr) + : "memory"); + return (uint32_t)reg64; +} + +ARCH_ATOMIC_DEFINE(atomic, int32_t, 4) + +#endif /* __ARCH_TRICORE_INCLUDE_ATOMIC_H */ diff --git a/include/nuttx/atomic.h b/include/nuttx/atomic.h index dbdcfc5ea5bcc..12ce9c42f7aaf 100644 --- a/include/nuttx/atomic.h +++ b/include/nuttx/atomic.h @@ -27,10 +27,16 @@ * Included Files ****************************************************************************/ +#include + #include #include #include +#ifdef CONFIG_LIBC_ATOMIC_ARCH +# include +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -279,7 +285,7 @@ extern "C" #define EXTERN extern #endif -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN +#if !defined(CONFIG_LIBC_ATOMIC_TOOLCHAIN) && !defined(CONFIG_LIBC_ATOMIC_ARCH) void atomic_store_4(FAR volatile void *ptr, int32_t value, int memorder); void atomic_store_8(FAR volatile void *ptr, int64_t value, int memorder); int32_t atomic_load_4(FAR const volatile void *ptr, int memorder); diff --git a/libs/libc/machine/tricore/arch_atomic.c b/libs/libc/machine/tricore/arch_atomic.c index dd4e83e697eb1..a834d5ad975aa 100644 --- a/libs/libc/machine/tricore/arch_atomic.c +++ b/libs/libc/machine/tricore/arch_atomic.c @@ -26,236 +26,12 @@ #include -#include -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define ARCH_ATOMIC_STORE_4(func) \ - \ - void func(volatile void *ptr, int32_t value, int memorder) \ - { \ - tricore_atomic_swap(ptr, value); \ - } - -#define ARCH_ATOMIC_LOAD_4(func) \ - \ - int32_t func(const volatile void *ptr, int memorder) \ - { \ - return *(volatile uint32_t *)ptr; \ - } - -#define ARCH_ATOMIC_EXCHANGE_4(func) \ - \ - int32_t func(volatile void *ptr, int32_t value, int memorder) \ - { \ - return tricore_atomic_swap(ptr, value); \ - } - -#define ARCH_ATOMIC_COMPARE_EXCHANGE_4(func) \ - \ - bool func(volatile void *ptr, volatile void *expect, \ - int32_t desired, bool weak, int success, int failure) \ - { \ - int32_t old; \ - \ - old = tricore_atomic_cmpswap(ptr, desired, *(int32_t *)expect); \ - if (old == *(int32_t *)expect) \ - { \ - return true; \ - } \ - \ - *(int32_t *)expect = old; \ - \ - return false; \ - } - -#define ARCH_ATOMIC_FLAGS_TEST_AND_SET_4(func) \ - \ - int32_t func(volatile void *ptr, int memorder) \ - { \ - return tricore_atomic_swap(ptr, 1); \ - } - -#define ARCH_ATOMIC_FETCH_ADD_4(func) \ - \ - int32_t func(volatile void *ptr, int32_t value, int memorder) \ - { \ - int32_t old_val; \ - \ - do \ - { \ - old_val = atomic_load_4(ptr, memorder); \ - } \ - while (tricore_atomic_cmpswap(ptr, old_val + value, old_val) \ - != old_val); \ - \ - return old_val; \ - } - -#define ARCH_ATOMIC_FETCH_SUB_4(func) \ - \ - int32_t func(volatile void *ptr, int32_t value, int memorder) \ - { \ - int32_t old_val; \ - \ - do \ - { \ - old_val = atomic_load_4(ptr, memorder); \ - } \ - while (tricore_atomic_cmpswap(ptr, old_val - value, old_val) \ - != old_val); \ - \ - return old_val; \ - } - -#define ARCH_ATOMIC_FETCH_AND_4(func) \ - \ - int32_t func(volatile void *ptr, int32_t value, int memorder) \ - { \ - int32_t old_val; \ - \ - do \ - { \ - old_val = atomic_load_4(ptr, memorder); \ - } \ - while (tricore_atomic_cmpswap(ptr, old_val & value, old_val) \ - != old_val); \ - \ - return old_val; \ - } - -#define ARCH_ATOMIC_FETCH_OR_4(func) \ - \ - int32_t func(volatile void *ptr, int32_t value, int memorder) \ - { \ - int32_t old_val; \ - \ - do \ - { \ - old_val = atomic_load_4(ptr, memorder); \ - } \ - while (tricore_atomic_cmpswap(ptr, old_val | value, old_val) \ - != old_val); \ - \ - return old_val; \ - } - -#define ARCH_ATOMIC_FETCH_XOR_4(func) \ - \ - int32_t func(volatile void *ptr, int32_t value, int memorder) \ - { \ - int32_t old_val; \ - \ - do \ - { \ - old_val = atomic_load_4(ptr, memorder); \ - } \ - while (tricore_atomic_cmpswap(ptr, old_val ^ value, old_val) \ - != old_val); \ - \ - return old_val; \ - } - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -always_inline_function -static uint32_t tricore_atomic_swap(volatile void *addr, uint32_t value) -{ - uint32_t res; - - __asm__ volatile ("swap.w [%1]0, %2" - : "=d"(res) : "a"(addr), "0"(value)); - return res; -} +#define ARCH_ATOMIC_SPECIFIER -always_inline_function -static uint32_t tricore_atomic_cmpswap(volatile void *addr, uint32_t value, - uint32_t condition) -{ - uint64_t reg64 = value | ((uint64_t)condition << 32); - - __asm__ __volatile__ ("cmpswap.w [%1]0, %A0" - : "+d" (reg64) - : "a" (addr) - : "memory"); - return (uint32_t)reg64; -} +#include /**************************************************************************** * Public Functions ****************************************************************************/ -/**************************************************************************** - * Name: atomic_store_4 - ****************************************************************************/ - -ARCH_ATOMIC_STORE_4(__atomic_store_4) -ARCH_ATOMIC_STORE_4(atomic_store_4) - -/**************************************************************************** - * Name: atomic_load_4 - ****************************************************************************/ - -ARCH_ATOMIC_LOAD_4(__atomic_load_4) -ARCH_ATOMIC_LOAD_4(atomic_load_4) - -/**************************************************************************** - * Name: atomic_exchange_4 - ****************************************************************************/ - -ARCH_ATOMIC_EXCHANGE_4(__atomic_exchange_4) -ARCH_ATOMIC_EXCHANGE_4(atomic_exchange_4) - -/**************************************************************************** - * Name: atomic_compare_exchange_4 - ****************************************************************************/ - -ARCH_ATOMIC_COMPARE_EXCHANGE_4(__atomic_compare_exchange_4) -ARCH_ATOMIC_COMPARE_EXCHANGE_4(atomic_compare_exchange_4) - -/**************************************************************************** - * Name: atomic_flag_test_and_set_4 - ****************************************************************************/ - -ARCH_ATOMIC_FLAGS_TEST_AND_SET_4(__atomic_flags_test_and_set_4) -ARCH_ATOMIC_FLAGS_TEST_AND_SET_4(atomic_flags_test_and_set_4) - -/**************************************************************************** - * Name: atomic_fetch_add_4 - ****************************************************************************/ - -ARCH_ATOMIC_FETCH_ADD_4(__atomic_fetch_add_4) -ARCH_ATOMIC_FETCH_ADD_4(atomic_fetch_add_4) - -/**************************************************************************** - * Name: atomic_fetch_sub_4 - ****************************************************************************/ - -ARCH_ATOMIC_FETCH_SUB_4(__atomic_fetch_sub_4) -ARCH_ATOMIC_FETCH_SUB_4(atomic_fetch_sub_4) - -/**************************************************************************** - * Name: atomic_fetch_and_4 - ****************************************************************************/ - -ARCH_ATOMIC_FETCH_AND_4(__atomic_fetch_and_4) -ARCH_ATOMIC_FETCH_AND_4(atomic_fetch_and_4) - -/**************************************************************************** - * Name: atomic_fetch_or_4 - ****************************************************************************/ - -ARCH_ATOMIC_FETCH_OR_4(__atomic_fetch_or_4) -ARCH_ATOMIC_FETCH_OR_4(atomic_fetch_or_4) - -/**************************************************************************** - * Name: atomic_fetch_xor_4 - ****************************************************************************/ - -ARCH_ATOMIC_FETCH_XOR_4(__atomic_fetch_xor_4) -ARCH_ATOMIC_FETCH_XOR_4(atomic_fetch_xor_4) +ARCH_ATOMIC_DEFINE(__atomic, int32_t, 4) From ec557ba629c549615c3e40a0230141813f234561 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Thu, 2 Apr 2026 22:32:17 +0800 Subject: [PATCH 3/6] libc/atomic: support inline arch atomic for generic IRQ path 1. Add include/nuttx/lib/arch_atomic.h with inline atomic_*_4/8 and __sync_*_{1,2,4,8} operations using IRQ disable/enable or hwspinlock under CONFIG_LIBC_ATOMIC_IRQ / CONFIG_LIBC_ATOMIC_HWSPINLOCK. 2. Include the new header from include/nuttx/atomic.h so the NuttX atomic API becomes inline (no function call overhead). 3. Reduce libs/libc/machine/arch_atomic.c to only export __atomic_* and __sync_* symbols for GCC libatomic ABI; delete the local arch_atomic.h and arch_atomic64.c (superseded); update Make.defs and CMakeLists.txt accordingly. 4. Fix a pre-existing race in SYNC_*_FETCH macros where the return value was read from shared memory after releasing the lock; now captured in a local variable before unlocking. Signed-off-by: Bowen Wang --- include/nuttx/atomic.h | 60 +---- include/nuttx/lib/arch_atomic.h | 269 +++++++++++++++++++++ libs/libc/machine/CMakeLists.txt | 2 - libs/libc/machine/Make.defs | 2 - libs/libc/machine/arch_atomic.c | 384 ++---------------------------- libs/libc/machine/arch_atomic.h | 320 ------------------------- libs/libc/machine/arch_atomic64.c | 201 ---------------- 7 files changed, 289 insertions(+), 949 deletions(-) create mode 100644 include/nuttx/lib/arch_atomic.h delete mode 100644 libs/libc/machine/arch_atomic.h delete mode 100644 libs/libc/machine/arch_atomic64.c diff --git a/include/nuttx/atomic.h b/include/nuttx/atomic.h index 12ce9c42f7aaf..8bd231942d67b 100644 --- a/include/nuttx/atomic.h +++ b/include/nuttx/atomic.h @@ -35,6 +35,9 @@ #ifdef CONFIG_LIBC_ATOMIC_ARCH # include +#elif defined(CONFIG_LIBC_ATOMIC_IRQ) || \ + defined(CONFIG_LIBC_ATOMIC_HWSPINLOCK) +# include #endif /**************************************************************************** @@ -272,61 +275,4 @@ typedef atomic64_t atomic_ptr_t; typedef atomic_t atomic_ptr_t; #endif -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ - -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" -{ -#else -#define EXTERN extern -#endif - -#if !defined(CONFIG_LIBC_ATOMIC_TOOLCHAIN) && !defined(CONFIG_LIBC_ATOMIC_ARCH) -void atomic_store_4(FAR volatile void *ptr, int32_t value, int memorder); -void atomic_store_8(FAR volatile void *ptr, int64_t value, int memorder); -int32_t atomic_load_4(FAR const volatile void *ptr, int memorder); -int64_t atomic_load_8(FAR const volatile void *ptr, int memorder); -int32_t atomic_exchange_4(FAR volatile void *ptr, int32_t value, - int memorder); -int64_t atomic_exchange_8(FAR volatile void *ptr, int64_t value, - int memorder); -bool atomic_compare_exchange_4(FAR volatile void *ptr, - FAR volatile void *expect, - int32_t desired, bool weak, - int success, int failure); -bool atomic_compare_exchange_8(FAR volatile void *ptr, - FAR volatile void *expect, - int64_t desired, bool weak, - int success, int failure); -int32_t atomic_fetch_add_4(FAR volatile void *ptr, int32_t value, - int memorder); -int64_t atomic_fetch_add_8(FAR volatile void *ptr, int64_t value, - int memorder); -int32_t atomic_fetch_sub_4(FAR volatile void *ptr, int32_t value, - int memorder); -int64_t atomic_fetch_sub_8(FAR volatile void *ptr, int64_t value, - int memorder); -int32_t atomic_fetch_and_4(FAR volatile void *ptr, int32_t value, - int memorder); -int64_t atomic_fetch_and_8(FAR volatile void *ptr, int64_t value, - int memorder); -int32_t atomic_fetch_or_4(FAR volatile void *ptr, int32_t value, - int memorder); -int64_t atomic_fetch_or_8(FAR volatile void *ptr, int64_t value, - int memorder); -int32_t atomic_fetch_xor_4(FAR volatile void *ptr, int32_t value, - int memorder); -int64_t atomic_fetch_xor_8(FAR volatile void *ptr, int64_t value, - int memorder); -#endif - -#undef EXTERN -#if defined(__cplusplus) -} -#endif - #endif /* __INCLUDE_NUTTX_ATOMIC_H */ diff --git a/include/nuttx/lib/arch_atomic.h b/include/nuttx/lib/arch_atomic.h new file mode 100644 index 0000000000000..6a2d7bae5f793 --- /dev/null +++ b/include/nuttx/lib/arch_atomic.h @@ -0,0 +1,269 @@ +/**************************************************************************** + * include/nuttx/lib/arch_atomic.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_LIB_ARCH_ATOMIC_H +#define __INCLUDE_NUTTX_LIB_ARCH_ATOMIC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include + +#if defined(CONFIG_LIBC_ATOMIC_HWSPINLOCK) +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef ARCH_ATOMIC_SPECIFIER +# define ARCH_ATOMIC_SPECIFIER static always_inline_function +#endif + +#if defined(CONFIG_LIBC_ATOMIC_HWSPINLOCK) +extern struct hwspinlock_dev_s g_atomic_hwspinlock; +static inline irqstate_t atomic_lock(void) +{ + return hwspin_lock_irqsave(&g_atomic_hwspinlock); +} + +static inline void atomic_unlock(irqstate_t flags) +{ + hwspin_unlock_restore(&g_atomic_hwspinlock, flags); +} +#else +static inline irqstate_t atomic_lock(void) +{ + return up_irq_save(); +} + +static inline void atomic_unlock(irqstate_t flags) +{ + up_irq_restore(flags); +} +#endif + +#define ARCH_ATOMIC_STORE(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + void func(FAR volatile void *ptr, t value, int memorder) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + \ + *(FAR t *)ptr = value; \ + \ + atomic_unlock(irqstate); \ + } + +#define ARCH_ATOMIC_LOAD(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(FAR const volatile void *ptr, int memorder) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + \ + t ret = *(FAR t *)ptr; \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_ATOMIC_EXCHANGE(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(FAR volatile void *ptr, t value, int memorder) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + \ + t ret = *tmp; \ + *tmp = value; \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_ATOMIC_COMPARE_EXCHANGE(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + bool func(FAR volatile void *mem, FAR volatile void *expect, \ + t desired, bool weak, int success, int failure) \ + { \ + bool ret = false; \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmpmem = (FAR t *)mem; \ + FAR t *tmpexp = (FAR t *)expect; \ + \ + if (*tmpmem == *tmpexp) \ + { \ + ret = true; \ + *tmpmem = desired; \ + } \ + else \ + { \ + *tmpexp = *tmpmem; \ + } \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_ATOMIC_FLAGS_TEST_AND_SET(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(FAR volatile void *ptr, int memorder) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret = *tmp; \ + \ + *(FAR t *)ptr = 1; \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_ATOMIC_FETCH_OP(func, t, op) \ + ARCH_ATOMIC_SPECIFIER \ + t func(FAR volatile void *ptr, t value, int memorder) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret = *tmp; \ + \ + *tmp = *tmp op value; \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_ATOMIC_DEFINE(prefix, t, n) \ + ARCH_ATOMIC_STORE(prefix ## _store_ ## n, t) \ + ARCH_ATOMIC_LOAD(prefix ## _load_ ## n, t) \ + ARCH_ATOMIC_EXCHANGE(prefix ## _exchange_ ## n, t) \ + ARCH_ATOMIC_COMPARE_EXCHANGE(prefix ## _compare_exchange_ ## n, t) \ + ARCH_ATOMIC_FLAGS_TEST_AND_SET(prefix ## _flags_test_and_set_ ## n, t) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_add_ ## n, t, +) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_sub_ ## n, t, -) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_and_ ## n, t, &) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_or_ ## n, t, |) \ + ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_xor_ ## n, t, ^) + +#define ARCH_SYNC_OP_FETCH(func, t, op) \ + ARCH_ATOMIC_SPECIFIER \ + t func(FAR volatile void *ptr, t value) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret; \ + \ + *tmp = *tmp op value; \ + ret = *tmp; \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_SYNC_NAND_FETCH(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(FAR volatile void *ptr, t value) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret; \ + \ + *tmp = ~(*tmp & value); \ + ret = *tmp; \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_SYNC_BOOL_CMP_SWAP(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + bool func(FAR volatile void *ptr, t oldvalue, t newvalue) \ + { \ + bool ret = false; \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + \ + if (*tmp == oldvalue) \ + { \ + ret = true; \ + *tmp = newvalue; \ + } \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_SYNC_VAL_CMP_SWAP(func, t) \ + ARCH_ATOMIC_SPECIFIER \ + t func(FAR volatile void *ptr, t oldvalue, t newvalue) \ + { \ + irqstate_t irqstate = atomic_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret = *tmp; \ + \ + if (*tmp == oldvalue) \ + { \ + *tmp = newvalue; \ + } \ + \ + atomic_unlock(irqstate); \ + return ret; \ + } + +#define ARCH_SYNC_SYNCHRONIZE(prefix) \ + ARCH_ATOMIC_SPECIFIER \ + void prefix ## _synchronize(void) \ + { \ + UP_DMB(); \ + } + +#define ARCH_SYNC_DEFINE(prefix, t, n) \ + ARCH_SYNC_OP_FETCH(prefix ## _add_and_fetch_ ## n, t, +) \ + ARCH_SYNC_OP_FETCH(prefix ## _sub_and_fetch_ ## n, t, -) \ + ARCH_SYNC_OP_FETCH(prefix ## _or_and_fetch_ ## n, t, |) \ + ARCH_SYNC_OP_FETCH(prefix ## _and_and_fetch_ ## n, t, &) \ + ARCH_SYNC_OP_FETCH(prefix ## _xor_and_fetch_ ## n, t, ^) \ + ARCH_SYNC_NAND_FETCH(prefix ## _nand_and_fetch_ ## n, t) \ + ARCH_SYNC_BOOL_CMP_SWAP(prefix ## _bool_compare_and_swap_ ## n, t) \ + ARCH_SYNC_VAL_CMP_SWAP(prefix ## _val_compare_and_swap_ ## n, t) + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +ARCH_ATOMIC_DEFINE(atomic, uint8_t, 1) +ARCH_ATOMIC_DEFINE(atomic, uint16_t, 2) +ARCH_ATOMIC_DEFINE(atomic, int32_t, 4) +ARCH_ATOMIC_DEFINE(atomic, int64_t, 8) + +ARCH_SYNC_DEFINE(sync, uint8_t, 1) +ARCH_SYNC_DEFINE(sync, uint16_t, 2) +ARCH_SYNC_DEFINE(sync, uint32_t, 4) +ARCH_SYNC_DEFINE(sync, uint64_t, 8) + +#endif /* __INCLUDE_NUTTX_LIB_ARCH_ATOMIC_H */ diff --git a/libs/libc/machine/CMakeLists.txt b/libs/libc/machine/CMakeLists.txt index 35bbf1cbaffa9..e2dfd54085714 100644 --- a/libs/libc/machine/CMakeLists.txt +++ b/libs/libc/machine/CMakeLists.txt @@ -26,8 +26,6 @@ if(CONFIG_LIBC_ATOMIC_IRQ OR CONFIG_LIBC_ATOMIC_HWSPINLOCK) target_sources(c PRIVATE arch_atomic.c) endif() -target_sources(c PRIVATE arch_atomic64.c) - if(CONFIG_MM_KASAN) target_sources(c PRIVATE arch_libc.c) endif() diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs index e8e03b6543f10..ef340bd54cadc 100644 --- a/libs/libc/machine/Make.defs +++ b/libs/libc/machine/Make.defs @@ -24,8 +24,6 @@ ifneq ($(filter y,$(CONFIG_LIBC_ATOMIC_IRQ)$(CONFIG_LIBC_ATOMIC_HWSPINLOCK)),) CSRCS += arch_atomic.c endif -CSRCS += arch_atomic64.c - ifeq ($(CONFIG_MM_KASAN),y) CSRCS += arch_libc.c endif diff --git a/libs/libc/machine/arch_atomic.c b/libs/libc/machine/arch_atomic.c index 802514c3bd403..ab8a226f47172 100644 --- a/libs/libc/machine/arch_atomic.c +++ b/libs/libc/machine/arch_atomic.c @@ -26,237 +26,23 @@ #include -#include -#include -#include -#include -#if defined(CONFIG_LIBC_ATOMIC_HWSPINLOCK) -# include -#endif - -#include "arch_atomic.h" - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -#if defined(CONFIG_LIBC_ATOMIC_HWSPINLOCK) -extern struct hwspinlock_dev_s g_atomic_hwspinlock; - -static inline irqstate_t atomic_lock(void) -{ - return hwspin_lock_irqsave(&g_atomic_hwspinlock); -} +#define ARCH_ATOMIC_SPECIFIER -static inline void atomic_unlock(irqstate_t flags) -{ - hwspin_unlock_restore(&g_atomic_hwspinlock, flags); -} -#elif defined(CONFIG_LIBC_ATOMIC_IRQ) -static inline irqstate_t atomic_lock(void) -{ - return up_irq_save(); -} - -static inline void atomic_unlock(irqstate_t flags) -{ - up_irq_restore(flags); -} -#endif +#include +#include /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: __atomic_store_1 - ****************************************************************************/ - -STORE(__atomic_store_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_store_2 - ****************************************************************************/ - -STORE(__atomic_store_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_store_4 - ****************************************************************************/ - -STORE(__atomic_store_, 4, uint32_t) -STORE(atomic_store_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_load_1 - ****************************************************************************/ - -LOAD(__atomic_load_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_load_2 - ****************************************************************************/ - -LOAD(__atomic_load_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_load_4 - ****************************************************************************/ - -LOAD(__atomic_load_, 4, uint32_t) -LOAD(atomic_load_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_exchange_1 - ****************************************************************************/ - -EXCHANGE(__atomic_exchange_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_exchange_2 - ****************************************************************************/ - -EXCHANGE(__atomic_exchange_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_exchange_4 - ****************************************************************************/ - -EXCHANGE(__atomic_exchange_, 4, uint32_t) -EXCHANGE(atomic_exchange_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_compare_exchange_1 - ****************************************************************************/ - -CMP_EXCHANGE(__atomic_compare_exchange_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_compare_exchange_2 - ****************************************************************************/ - -CMP_EXCHANGE(__atomic_compare_exchange_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_compare_exchange_4 - ****************************************************************************/ - -CMP_EXCHANGE(__atomic_compare_exchange_, 4, uint32_t) -CMP_EXCHANGE(atomic_compare_exchange_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_flag_test_and_set_1 - ****************************************************************************/ - -FLAG_TEST_AND_SET(__atomic_flags_test_and_set_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_flag_test_and_set_2 - ****************************************************************************/ - -FLAG_TEST_AND_SET(__atomic_flags_test_and_set_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_flag_test_and_set_4 - ****************************************************************************/ - -FLAG_TEST_AND_SET(__atomic_flags_test_and_set_, 4, uint32_t) -FLAG_TEST_AND_SET(atomic_flags_test_and_set_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_fetch_add_1 - ****************************************************************************/ - -FETCH_ADD(__atomic_fetch_add_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_fetch_add_2 - ****************************************************************************/ - -FETCH_ADD(__atomic_fetch_add_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_fetch_add_4 - ****************************************************************************/ - -FETCH_ADD(__atomic_fetch_add_, 4, uint32_t) -FETCH_ADD(atomic_fetch_add_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_fetch_sub_1 - ****************************************************************************/ - -FETCH_SUB(__atomic_fetch_sub_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_fetch_sub_2 - ****************************************************************************/ - -FETCH_SUB(__atomic_fetch_sub_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_fetch_sub_4 - ****************************************************************************/ - -FETCH_SUB(__atomic_fetch_sub_, 4, uint32_t) -FETCH_SUB(atomic_fetch_sub_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_fetch_and_1 - ****************************************************************************/ - -FETCH_AND(__atomic_fetch_and_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_fetch_and_2 - ****************************************************************************/ - -FETCH_AND(__atomic_fetch_and_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_fetch_and_4 - ****************************************************************************/ - -FETCH_AND(__atomic_fetch_and_, 4, uint32_t) -FETCH_AND(atomic_fetch_and_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_fetch_or_1 - ****************************************************************************/ - -FETCH_OR(__atomic_fetch_or_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_fetch_or_2 - ****************************************************************************/ - -FETCH_OR(__atomic_fetch_or_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_fetch_or_4 - ****************************************************************************/ - -FETCH_OR(__atomic_fetch_or_, 4, uint32_t) -FETCH_OR(atomic_fetch_or_, 4, int32_t) - -/**************************************************************************** - * Name: __atomic_fetch_xor_1 - ****************************************************************************/ - -FETCH_XOR(__atomic_fetch_xor_, 1, uint8_t) - -/**************************************************************************** - * Name: __atomic_fetch_xor_2 - ****************************************************************************/ - -FETCH_XOR(__atomic_fetch_xor_, 2, uint16_t) - -/**************************************************************************** - * Name: __atomic_fetch_xor_4 + * Name: __atomic_*_{1,2,4,8} ****************************************************************************/ -FETCH_XOR(__atomic_fetch_xor_, 4, uint32_t) -FETCH_XOR(atomic_fetch_xor_, 4, int32_t) +ARCH_ATOMIC_DEFINE(__atomic, uint8_t, 1) +ARCH_ATOMIC_DEFINE(__atomic, uint16_t, 2) +ARCH_ATOMIC_DEFINE(__atomic, uint32_t, 4) +ARCH_ATOMIC_DEFINE(__atomic, uint64_t, 8) /* Clang define the __sync builtins, add #ifndef to avoid * redefined/redeclared problem. @@ -265,158 +51,22 @@ FETCH_XOR(atomic_fetch_xor_, 4, int32_t) #ifndef __clang__ /**************************************************************************** - * Name: __sync_add_and_fetch_1 - ****************************************************************************/ - -SYNC_ADD_FETCH(__sync_add_and_fetch_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_add_and_fetch_2 - ****************************************************************************/ - -SYNC_ADD_FETCH(__sync_add_and_fetch_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_add_and_fetch_4 - ****************************************************************************/ - -SYNC_ADD_FETCH(__sync_add_and_fetch_, 4, uint32_t) - -/**************************************************************************** - * Name: __sync_sub_and_fetch_1 + * Name: __sync_*_{1,2,4,8} ****************************************************************************/ -SYNC_SUB_FETCH(__sync_sub_and_fetch_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_sub_and_fetch_2 - ****************************************************************************/ - -SYNC_SUB_FETCH(__sync_sub_and_fetch_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_sub_and_fetch_4 - ****************************************************************************/ - -SYNC_SUB_FETCH(__sync_sub_and_fetch_, 4, uint32_t) - -/**************************************************************************** - * Name: __sync_or_and_fetch_1 - ****************************************************************************/ - -SYNC_OR_FETCH(__sync_or_and_fetch_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_or_and_fetch_2 - ****************************************************************************/ - -SYNC_OR_FETCH(__sync_or_and_fetch_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_or_and_fetch_4 - ****************************************************************************/ - -SYNC_OR_FETCH(__sync_or_and_fetch_, 4, uint32_t) - -/**************************************************************************** - * Name: __sync_and_and_fetch_1 - ****************************************************************************/ - -SYNC_AND_FETCH(__sync_and_and_fetch_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_and_and_fetch_2 - ****************************************************************************/ - -SYNC_AND_FETCH(__sync_and_and_fetch_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_and_and_fetch_4 - ****************************************************************************/ - -SYNC_AND_FETCH(__sync_and_and_fetch_, 4, uint32_t) - -/**************************************************************************** - * Name: __sync_xor_and_fetch_1 - ****************************************************************************/ - -SYNC_XOR_FETCH(__sync_xor_and_fetch_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_xor_and_fetch_2 - ****************************************************************************/ - -SYNC_XOR_FETCH(__sync_xor_and_fetch_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_xor_and_fetch_4 - ****************************************************************************/ - -SYNC_XOR_FETCH(__sync_xor_and_fetch_, 4, uint32_t) - -/**************************************************************************** - * Name: __sync_nand_and_fetch_1 - ****************************************************************************/ - -SYNC_NAND_FETCH(__sync_nand_and_fetch_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_nand_and_fetch_2 - ****************************************************************************/ - -SYNC_NAND_FETCH(__sync_nand_and_fetch_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_nand_and_fetch_4 - ****************************************************************************/ - -SYNC_NAND_FETCH(__sync_nand_and_fetch_, 4, uint32_t) - -/**************************************************************************** - * Name: __sync_bool_compare_and_swap_1 - ****************************************************************************/ - -SYNC_BOOL_CMP_SWAP(__sync_bool_compare_and_swap_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_bool_compare_and_swap_2 - ****************************************************************************/ - -SYNC_BOOL_CMP_SWAP(__sync_bool_compare_and_swap_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_bool_compare_and_swap_4 - ****************************************************************************/ - -SYNC_BOOL_CMP_SWAP(__sync_bool_compare_and_swap_, 4, uint32_t) - -/**************************************************************************** - * Name: __sync_val_compare_and_swap_1 - ****************************************************************************/ - -SYNC_VAL_CMP_SWAP(__sync_val_compare_and_swap_, 1, uint8_t) - -/**************************************************************************** - * Name: __sync_val_compare_and_swap_2 - ****************************************************************************/ - -SYNC_VAL_CMP_SWAP(__sync_val_compare_and_swap_, 2, uint16_t) - -/**************************************************************************** - * Name: __sync_val_compare_and_swap_4 - ****************************************************************************/ - -SYNC_VAL_CMP_SWAP(__sync_val_compare_and_swap_, 4, uint32_t) +#ifdef ARCH_SYNC_DEFINE +ARCH_SYNC_DEFINE(__sync, uint8_t, 1) +ARCH_SYNC_DEFINE(__sync, uint16_t, 2) +ARCH_SYNC_DEFINE(__sync, uint32_t, 4) +ARCH_SYNC_DEFINE(__sync, uint64_t, 8) +#endif /**************************************************************************** * Name: __sync_synchronize ****************************************************************************/ -void weak_function __sync_synchronize(void) -{ -#ifdef UP_DMB - UP_DMB(); +#ifdef ARCH_SYNC_SYNCHRONIZE +ARCH_SYNC_SYNCHRONIZE(__sync) #endif -} #endif /* __clang__ */ diff --git a/libs/libc/machine/arch_atomic.h b/libs/libc/machine/arch_atomic.h deleted file mode 100644 index 747271912cb5c..0000000000000 --- a/libs/libc/machine/arch_atomic.h +++ /dev/null @@ -1,320 +0,0 @@ -/**************************************************************************** - * libs/libc/machine/arch_atomic.h - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -#ifndef __LIBS_LIBC_MACHINE_ARCH_ATOMIC_H -#define __LIBS_LIBC_MACHINE_ARCH_ATOMIC_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define STORE(fn, n, type) \ - \ - void weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value, int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - \ - *(FAR type *)ptr = value; \ - \ - atomic_unlock(irqstate); \ - } - -#define LOAD(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR const volatile void *ptr, \ - int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - \ - type ret = *(FAR type *)ptr; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define EXCHANGE(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value, int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - type ret = *tmp; \ - *tmp = value; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define CMP_EXCHANGE(fn, n, type) \ - \ - bool weak_function CONCATENATE(fn, n)(FAR volatile void *mem, \ - FAR volatile void *expect, \ - type desired, bool weak, \ - int success, int failure) \ - { \ - bool ret = false; \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmpmem = (FAR type *)mem; \ - FAR type *tmpexp = (FAR type *)expect; \ - \ - if (*tmpmem == *tmpexp) \ - { \ - ret = true; \ - *tmpmem = desired; \ - } \ - else \ - { \ - *tmpexp = *tmpmem; \ - } \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define FLAG_TEST_AND_SET(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - type ret = *tmp; \ - \ - *(FAR type *)ptr = 1; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define FETCH_ADD(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value, int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - type ret = *tmp; \ - \ - *tmp = *tmp + value; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define FETCH_SUB(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value, int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - type ret = *tmp; \ - \ - *tmp = *tmp - value; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define FETCH_AND(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value, int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - type ret = *tmp; \ - \ - *tmp = *tmp & value; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define FETCH_OR(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value, int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - type ret = *tmp; \ - \ - *tmp = *tmp | value; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define FETCH_XOR(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value, int memorder) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - type ret = *tmp; \ - \ - *tmp = *tmp ^ value; \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define SYNC_ADD_FETCH(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - *tmp = *tmp + value; \ - \ - atomic_unlock(irqstate); \ - return *tmp; \ - } - -#define SYNC_SUB_FETCH(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - *tmp = *tmp - value; \ - \ - atomic_unlock(irqstate); \ - return *tmp; \ - } - -#define SYNC_OR_FETCH(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - *tmp = *tmp | value; \ - \ - atomic_unlock(irqstate); \ - return *tmp; \ - } - -#define SYNC_AND_FETCH(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - *tmp = *tmp & value; \ - \ - atomic_unlock(irqstate); \ - return *tmp; \ - } - -#define SYNC_XOR_FETCH(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - *tmp = *tmp ^ value; \ - \ - atomic_unlock(irqstate); \ - return *tmp; \ - } - -#define SYNC_NAND_FETCH(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type value) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - *tmp = ~(*tmp & value); \ - \ - atomic_unlock(irqstate); \ - return *tmp; \ - } - -#define SYNC_BOOL_CMP_SWAP(fn, n, type) \ - \ - bool weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type oldvalue, \ - type newvalue) \ - { \ - bool ret = false; \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - \ - if (*tmp == oldvalue) \ - { \ - ret = true; \ - *tmp = newvalue; \ - } \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#define SYNC_VAL_CMP_SWAP(fn, n, type) \ - \ - type weak_function CONCATENATE(fn, n)(FAR volatile void *ptr, \ - type oldvalue, \ - type newvalue) \ - { \ - irqstate_t irqstate = atomic_lock(); \ - FAR type *tmp = (FAR type *)ptr; \ - type ret = *tmp; \ - \ - if (*tmp == oldvalue) \ - { \ - *tmp = newvalue; \ - } \ - \ - atomic_unlock(irqstate); \ - return ret; \ - } - -#endif /* __LIBS_LIBC_MACHINE_ARCH_ATOMIC_H */ diff --git a/libs/libc/machine/arch_atomic64.c b/libs/libc/machine/arch_atomic64.c deleted file mode 100644 index 41cdeafeaf0a3..0000000000000 --- a/libs/libc/machine/arch_atomic64.c +++ /dev/null @@ -1,201 +0,0 @@ -/**************************************************************************** - * libs/libc/machine/arch_atomic64.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include - -#include "arch_atomic.h" - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static spinlock_t g_atomic_lock = SP_UNLOCKED; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static inline irqstate_t atomic_lock(void) -{ - return spin_lock_irqsave(&g_atomic_lock); -} - -static inline void atomic_unlock(irqstate_t flags) -{ - spin_unlock_irqrestore(&g_atomic_lock, flags); -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: __atomic_store_8 - ****************************************************************************/ - -STORE(__atomic_store_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -STORE(atomic_store_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_load_8 - ****************************************************************************/ - -LOAD(__atomic_load_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -LOAD(atomic_load_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_exchange_8 - ****************************************************************************/ - -EXCHANGE(__atomic_exchange_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -EXCHANGE(atomic_exchange_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_compare_exchange_8 - ****************************************************************************/ - -CMP_EXCHANGE(__atomic_compare_exchange_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -CMP_EXCHANGE(atomic_compare_exchange_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_flag_test_and_set_8 - ****************************************************************************/ - -FLAG_TEST_AND_SET(__atomic_flags_test_and_set_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FLAG_TEST_AND_SET(atomic_flags_test_and_set_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_fetch_add_8 - ****************************************************************************/ - -FETCH_ADD(__atomic_fetch_add_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FETCH_ADD(atomic_fetch_add_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_fetch_sub_8 - ****************************************************************************/ - -FETCH_SUB(__atomic_fetch_sub_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FETCH_SUB(atomic_fetch_sub_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_fetch_and_8 - ****************************************************************************/ - -FETCH_AND(__atomic_fetch_and_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FETCH_AND(atomic_fetch_and_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_fetch_or_8 - ****************************************************************************/ - -FETCH_OR(__atomic_fetch_or_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FETCH_OR(atomic_fetch_or_, 8, int64_t) -#endif - -/**************************************************************************** - * Name: __atomic_fetch_xor_8 - ****************************************************************************/ - -FETCH_XOR(__atomic_fetch_xor_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FETCH_XOR(atomic_fetch_xor_, 8, int64_t) -#endif - -/* Clang define the __sync builtins, add #ifndef to avoid - * redefined/redeclared problem. - */ - -#ifndef __clang__ - -/**************************************************************************** - * Name: __sync_add_and_fetch_8 - ****************************************************************************/ - -SYNC_ADD_FETCH(__sync_add_and_fetch_, 8, uint64_t) - -/**************************************************************************** - * Name: __sync_sub_and_fetch_8 - ****************************************************************************/ - -SYNC_SUB_FETCH(__sync_sub_and_fetch_, 8, uint64_t) - -/**************************************************************************** - * Name: __sync_or_and_fetch_8 - ****************************************************************************/ - -SYNC_OR_FETCH(__sync_or_and_fetch_, 8, uint64_t) - -/**************************************************************************** - * Name: __sync_and_and_fetch_8 - ****************************************************************************/ - -SYNC_AND_FETCH(__sync_and_and_fetch_, 8, uint64_t) - -/**************************************************************************** - * Name: __sync_xor_and_fetch_8 - ****************************************************************************/ - -SYNC_XOR_FETCH(__sync_xor_and_fetch_, 8, uint64_t) - -/**************************************************************************** - * Name: __sync_nand_and_fetch_8 - ****************************************************************************/ - -SYNC_NAND_FETCH(__sync_nand_and_fetch_, 8, uint64_t) - -/**************************************************************************** - * Name: __sync_bool_compare_and_swap_8 - ****************************************************************************/ - -SYNC_BOOL_CMP_SWAP(__sync_bool_compare_and_swap_, 8, uint64_t) - -/**************************************************************************** - * Name: __sync_val_compare_and_swap_8 - ****************************************************************************/ - -SYNC_VAL_CMP_SWAP(__sync_val_compare_and_swap_, 8, uint64_t) - -#endif /* __clang__ */ From f1f46f0e52757c3b7706c7096b3d550916bd44ea Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Tue, 1 Sep 2026 18:03:51 +0800 Subject: [PATCH 4/6] libc/atomic: merge tricore arch_atomic.c into machine/arch_atomic.c 1. Add ARCH_HAVE_ATOMIC_4 guard in arch/tricore/include/atomic.h so the tricore arch declares which sizes have hardware atomic support. 2. Extend include/nuttx/lib/arch_atomic.h to #undef arch overrides and provide IRQ-based inline fallback for sizes the arch does not support, so generic code covers all {1,2,4,8} sizes uniformly. 3. Update libs/libc/machine/arch_atomic.c to gate per-size symbol export on ARCH_HAVE_ATOMIC_X and 64-bit on UINTPTR_MAX > UINT32_MAX; delete libs/libc/machine/tricore/arch_atomic.c (now merged into the generic machine/arch_atomic.c). 4. Drop tricore-specific arch_atomic.c references from libs/libc/machine/tricore/{Make.defs,CMakeLists.txt}. Signed-off-by: Bowen Wang --- arch/tricore/include/atomic.h | 2 ++ include/nuttx/lib/arch_atomic.h | 5 ++++ libs/libc/machine/CMakeLists.txt | 2 +- libs/libc/machine/Make.defs | 2 +- libs/libc/machine/arch_atomic.c | 16 ++++++++++ libs/libc/machine/tricore/CMakeLists.txt | 4 --- libs/libc/machine/tricore/Make.defs | 4 --- libs/libc/machine/tricore/arch_atomic.c | 37 ------------------------ 8 files changed, 25 insertions(+), 47 deletions(-) delete mode 100644 libs/libc/machine/tricore/arch_atomic.c diff --git a/arch/tricore/include/atomic.h b/arch/tricore/include/atomic.h index 938ddfd15b65d..693e863a67512 100644 --- a/arch/tricore/include/atomic.h +++ b/arch/tricore/include/atomic.h @@ -112,6 +112,8 @@ ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_or_ ## n, t, n, |) \ ARCH_ATOMIC_FETCH_OP(prefix ## _fetch_xor_ ## n, t, n, ^) +#define ARCH_HAVE_ATOMIC_4 + /**************************************************************************** * Inline Functions ****************************************************************************/ diff --git a/include/nuttx/lib/arch_atomic.h b/include/nuttx/lib/arch_atomic.h index 6a2d7bae5f793..932536120a911 100644 --- a/include/nuttx/lib/arch_atomic.h +++ b/include/nuttx/lib/arch_atomic.h @@ -252,6 +252,11 @@ static inline void atomic_unlock(irqstate_t flags) ARCH_SYNC_BOOL_CMP_SWAP(prefix ## _bool_compare_and_swap_ ## n, t) \ ARCH_SYNC_VAL_CMP_SWAP(prefix ## _val_compare_and_swap_ ## n, t) +#define ARCH_HAVE_ATOMIC_1 +#define ARCH_HAVE_ATOMIC_2 +#define ARCH_HAVE_ATOMIC_4 +#define ARCH_HAVE_ATOMIC_8 + /**************************************************************************** * Inline Functions ****************************************************************************/ diff --git a/libs/libc/machine/CMakeLists.txt b/libs/libc/machine/CMakeLists.txt index e2dfd54085714..1c9542380a03b 100644 --- a/libs/libc/machine/CMakeLists.txt +++ b/libs/libc/machine/CMakeLists.txt @@ -22,7 +22,7 @@ add_subdirectory(${CONFIG_ARCH}) -if(CONFIG_LIBC_ATOMIC_IRQ OR CONFIG_LIBC_ATOMIC_HWSPINLOCK) +if(NOT CONFIG_LIBC_ATOMIC_TOOLCHAIN) target_sources(c PRIVATE arch_atomic.c) endif() diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs index ef340bd54cadc..af1a0636b565c 100644 --- a/libs/libc/machine/Make.defs +++ b/libs/libc/machine/Make.defs @@ -20,7 +20,7 @@ # ############################################################################ -ifneq ($(filter y,$(CONFIG_LIBC_ATOMIC_IRQ)$(CONFIG_LIBC_ATOMIC_HWSPINLOCK)),) +ifneq ($(CONFIG_LIBC_ATOMIC_TOOLCHAIN),y) CSRCS += arch_atomic.c endif diff --git a/libs/libc/machine/arch_atomic.c b/libs/libc/machine/arch_atomic.c index ab8a226f47172..e0f9c85b723e3 100644 --- a/libs/libc/machine/arch_atomic.c +++ b/libs/libc/machine/arch_atomic.c @@ -39,10 +39,18 @@ * Name: __atomic_*_{1,2,4,8} ****************************************************************************/ +#ifdef ARCH_HAVE_ATOMIC_1 ARCH_ATOMIC_DEFINE(__atomic, uint8_t, 1) +#endif +#ifdef ARCH_HAVE_ATOMIC_2 ARCH_ATOMIC_DEFINE(__atomic, uint16_t, 2) +#endif +#ifdef ARCH_HAVE_ATOMIC_4 ARCH_ATOMIC_DEFINE(__atomic, uint32_t, 4) +#endif +#ifdef ARCH_HAVE_ATOMIC_8 ARCH_ATOMIC_DEFINE(__atomic, uint64_t, 8) +#endif /* Clang define the __sync builtins, add #ifndef to avoid * redefined/redeclared problem. @@ -55,10 +63,18 @@ ARCH_ATOMIC_DEFINE(__atomic, uint64_t, 8) ****************************************************************************/ #ifdef ARCH_SYNC_DEFINE +# ifdef ARCH_HAVE_ATOMIC_1 ARCH_SYNC_DEFINE(__sync, uint8_t, 1) +# endif +# ifdef ARCH_HAVE_ATOMIC_2 ARCH_SYNC_DEFINE(__sync, uint16_t, 2) +# endif +# ifdef ARCH_HAVE_ATOMIC_4 ARCH_SYNC_DEFINE(__sync, uint32_t, 4) +# endif +# ifdef ARCH_HAVE_ATOMIC_8 ARCH_SYNC_DEFINE(__sync, uint64_t, 8) +# endif #endif /**************************************************************************** diff --git a/libs/libc/machine/tricore/CMakeLists.txt b/libs/libc/machine/tricore/CMakeLists.txt index 689da31505c6b..e2708f1e04bea 100644 --- a/libs/libc/machine/tricore/CMakeLists.txt +++ b/libs/libc/machine/tricore/CMakeLists.txt @@ -22,10 +22,6 @@ set(SRCS) -if(CONFIG_LIBC_ATOMIC_ARCH) - list(APPEND SRCS arch_atomic.c) -endif() - if(CONFIG_ARCH_SETJMP_H) list(APPEND SRCS arch_setjmp.c) endif() diff --git a/libs/libc/machine/tricore/Make.defs b/libs/libc/machine/tricore/Make.defs index b39fa5ac414bb..118afa1ccbe61 100644 --- a/libs/libc/machine/tricore/Make.defs +++ b/libs/libc/machine/tricore/Make.defs @@ -20,10 +20,6 @@ # ############################################################################ -ifeq ($(CONFIG_LIBC_ATOMIC_ARCH),y) -CSRCS += arch_atomic.c -endif - ifeq ($(CONFIG_ARCH_SETJMP_H),y) CSRCS += arch_setjmp.c endif diff --git a/libs/libc/machine/tricore/arch_atomic.c b/libs/libc/machine/tricore/arch_atomic.c deleted file mode 100644 index a834d5ad975aa..0000000000000 --- a/libs/libc/machine/tricore/arch_atomic.c +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** - * libs/libc/machine/tricore/arch_atomic.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#define ARCH_ATOMIC_SPECIFIER - -#include - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -ARCH_ATOMIC_DEFINE(__atomic, int32_t, 4) From 5c36cc35ef1bf33940badd7e2a71a65d887e395a Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Tue, 1 Sep 2026 18:09:45 +0800 Subject: [PATCH 5/6] include/atomic: add cmpxchg_release_acquire memory order variant 1. Add atomic_cmpxchg_release_acquire and atomic_try_cmpxchg_release_acquire for 32-bit (atomic_compare_exchange_4) using RELEASE on CAS success. 2. Add 64-bit counterparts atomic64_cmpxchg_release_acquire and atomic64_try_cmpxchg_release_acquire (atomic_compare_exchange_8). 3. Add pointer-width aliases atomic_ptr_cmpxchg_release_acquire and atomic_ptr_try_cmpxchg_release_acquire for both 64-bit and 32-bit pointer configurations, expanding the existing ptr_*_cmpxchg family. 4. Use ACQUIRE on CAS failure so the retry path re-acquires visibility of updates from other threads, matching the ordering used by DPDK RTS ring tail-commit CAS. Signed-off-by: Bowen Wang --- include/nuttx/atomic.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/nuttx/atomic.h b/include/nuttx/atomic.h index 8bd231942d67b..acab3cf7815cc 100644 --- a/include/nuttx/atomic.h +++ b/include/nuttx/atomic.h @@ -138,6 +138,8 @@ atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED) #define atomic_cmpxchg_release(obj, expected, desired) \ atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED) +#define atomic_cmpxchg_release_acquire(obj, expected, desired) \ + atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, false, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE) #define atomic_cmpxchg_relaxed(obj, expected, desired) \ atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED) #define atomic64_cmpxchg(obj, expected, desired) \ @@ -146,6 +148,8 @@ atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED) #define atomic64_cmpxchg_release(obj, expected, desired) \ atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, false, __ATOMIC_RELEASE, __ATOMIC_RELAXED) +#define atomic64_cmpxchg_release_acquire(obj, expected, desired) \ + atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, false, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE) #define atomic64_cmpxchg_relaxed(obj, expected, desired) \ atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED) @@ -155,6 +159,8 @@ atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED) #define atomic_try_cmpxchg_release(obj, expected, desired) \ atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, true, __ATOMIC_RELEASE, __ATOMIC_RELAXED) +#define atomic_try_cmpxchg_release_acquire(obj, expected, desired) \ + atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, true, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE) #define atomic_try_cmpxchg_relaxed(obj, expected, desired) \ atomic_compare_exchange_4(obj, (FAR int32_t *)expected, desired, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED) #define atomic64_try_cmpxchg(obj, expected, desired) \ @@ -163,6 +169,8 @@ atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED) #define atomic64_try_cmpxchg_release(obj, expected, desired) \ atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, true, __ATOMIC_RELEASE, __ATOMIC_RELAXED) +#define atomic64_try_cmpxchg_release_acquire(obj, expected, desired) \ + atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, true, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE) #define atomic64_try_cmpxchg_relaxed(obj, expected, desired) \ atomic_compare_exchange_8(obj, (FAR int64_t *)expected, desired, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED) @@ -202,6 +210,8 @@ atomic64_cmpxchg_acquire(obj, expected, desired) #define atomic_ptr_cmpxchg_release(obj, expected, desired) \ atomic64_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_cmpxchg_release_acquire(obj, expected, desired) \ + atomic64_cmpxchg_release_acquire(obj, expected, desired) #define atomic_ptr_cmpxchg_relaxed(obj, expected, desired) \ atomic64_cmpxchg_relaxed(obj, expected, desired) #define atomic_ptr_try_cmpxchg(obj, expected, desired) \ @@ -210,6 +220,8 @@ atomic64_try_cmpxchg_acquire(obj, expected, desired) #define atomic_ptr_try_cmpxchg_release(obj, expected, desired) \ atomic64_try_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_release_acquire(obj, expected, desired) \ + atomic64_try_cmpxchg_release_acquire(obj, expected, desired) #define atomic_ptr_try_cmpxchg_relaxed(obj, expected, desired) \ atomic64_try_cmpxchg_relaxed(obj, expected, desired) @@ -249,6 +261,8 @@ atomic_cmpxchg_acquire(obj, expected, desired) #define atomic_ptr_cmpxchg_release(obj, expected, desired) \ atomic_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_cmpxchg_release_acquire(obj, expected, desired) \ + atomic_cmpxchg_release_acquire(obj, expected, desired) #define atomic_ptr_cmpxchg_relaxed(obj, expected, desired) \ atomic_cmpxchg_relaxed(obj, expected, desired) #define atomic_ptr_try_cmpxchg(obj, expected, desired) \ @@ -257,6 +271,8 @@ atomic_try_cmpxchg_acquire(obj, expected, desired) #define atomic_ptr_try_cmpxchg_release(obj, expected, desired) \ atomic_try_cmpxchg_release(obj, expected, desired) +#define atomic_ptr_try_cmpxchg_release_acquire(obj, expected, desired) \ + atomic_try_cmpxchg_release_acquire(obj, expected, desired) #define atomic_ptr_try_cmpxchg_relaxed(obj, expected, desired) \ atomic_try_cmpxchg_relaxed(obj, expected, desired) From 2802f3b4262bed76299a8c022ba8b4a73ba55cd7 Mon Sep 17 00:00:00 2001 From: zhangyu117 Date: Wed, 2 Sep 2026 15:05:23 +0800 Subject: [PATCH 6/6] libc: realize atomic64 via a spinlock helper libc/machine/arch_atomic64.c implementing atomic_*_8 on a single spinlock. All helpers are weak_function so an arch with native 64-bit support overrides at link time Signed-off-by: zhangyu117 --- include/nuttx/lib/arch_atomic.h | 5 +- libs/libc/machine/CMakeLists.txt | 2 + libs/libc/machine/Make.defs | 2 + libs/libc/machine/arch_atomic.c | 12 +- libs/libc/machine/arch_atomic64.c | 287 ++++++++++++++++++++++++++++++ 5 files changed, 296 insertions(+), 12 deletions(-) create mode 100644 libs/libc/machine/arch_atomic64.c diff --git a/include/nuttx/lib/arch_atomic.h b/include/nuttx/lib/arch_atomic.h index 932536120a911..165428e8aa5e9 100644 --- a/include/nuttx/lib/arch_atomic.h +++ b/include/nuttx/lib/arch_atomic.h @@ -255,20 +255,19 @@ static inline void atomic_unlock(irqstate_t flags) #define ARCH_HAVE_ATOMIC_1 #define ARCH_HAVE_ATOMIC_2 #define ARCH_HAVE_ATOMIC_4 -#define ARCH_HAVE_ATOMIC_8 /**************************************************************************** * Inline Functions ****************************************************************************/ +#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN ARCH_ATOMIC_DEFINE(atomic, uint8_t, 1) ARCH_ATOMIC_DEFINE(atomic, uint16_t, 2) ARCH_ATOMIC_DEFINE(atomic, int32_t, 4) -ARCH_ATOMIC_DEFINE(atomic, int64_t, 8) ARCH_SYNC_DEFINE(sync, uint8_t, 1) ARCH_SYNC_DEFINE(sync, uint16_t, 2) ARCH_SYNC_DEFINE(sync, uint32_t, 4) -ARCH_SYNC_DEFINE(sync, uint64_t, 8) +#endif #endif /* __INCLUDE_NUTTX_LIB_ARCH_ATOMIC_H */ diff --git a/libs/libc/machine/CMakeLists.txt b/libs/libc/machine/CMakeLists.txt index 1c9542380a03b..6f340fa278d95 100644 --- a/libs/libc/machine/CMakeLists.txt +++ b/libs/libc/machine/CMakeLists.txt @@ -26,6 +26,8 @@ if(NOT CONFIG_LIBC_ATOMIC_TOOLCHAIN) target_sources(c PRIVATE arch_atomic.c) endif() +target_sources(c PRIVATE arch_atomic64.c) + if(CONFIG_MM_KASAN) target_sources(c PRIVATE arch_libc.c) endif() diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs index af1a0636b565c..74837fac4d7d1 100644 --- a/libs/libc/machine/Make.defs +++ b/libs/libc/machine/Make.defs @@ -24,6 +24,8 @@ ifneq ($(CONFIG_LIBC_ATOMIC_TOOLCHAIN),y) CSRCS += arch_atomic.c endif +CSRCS += arch_atomic64.c + ifeq ($(CONFIG_MM_KASAN),y) CSRCS += arch_libc.c endif diff --git a/libs/libc/machine/arch_atomic.c b/libs/libc/machine/arch_atomic.c index e0f9c85b723e3..5cda66c8b6dbf 100644 --- a/libs/libc/machine/arch_atomic.c +++ b/libs/libc/machine/arch_atomic.c @@ -26,7 +26,7 @@ #include -#define ARCH_ATOMIC_SPECIFIER +#define ARCH_ATOMIC_SPECIFIER weak_function #include #include @@ -36,7 +36,7 @@ ****************************************************************************/ /**************************************************************************** - * Name: __atomic_*_{1,2,4,8} + * Name: __atomic_*_{1,2,4} ****************************************************************************/ #ifdef ARCH_HAVE_ATOMIC_1 @@ -48,9 +48,6 @@ ARCH_ATOMIC_DEFINE(__atomic, uint16_t, 2) #ifdef ARCH_HAVE_ATOMIC_4 ARCH_ATOMIC_DEFINE(__atomic, uint32_t, 4) #endif -#ifdef ARCH_HAVE_ATOMIC_8 -ARCH_ATOMIC_DEFINE(__atomic, uint64_t, 8) -#endif /* Clang define the __sync builtins, add #ifndef to avoid * redefined/redeclared problem. @@ -59,7 +56,7 @@ ARCH_ATOMIC_DEFINE(__atomic, uint64_t, 8) #ifndef __clang__ /**************************************************************************** - * Name: __sync_*_{1,2,4,8} + * Name: __sync_*_{1,2,4} ****************************************************************************/ #ifdef ARCH_SYNC_DEFINE @@ -72,9 +69,6 @@ ARCH_SYNC_DEFINE(__sync, uint16_t, 2) # ifdef ARCH_HAVE_ATOMIC_4 ARCH_SYNC_DEFINE(__sync, uint32_t, 4) # endif -# ifdef ARCH_HAVE_ATOMIC_8 -ARCH_SYNC_DEFINE(__sync, uint64_t, 8) -# endif #endif /**************************************************************************** diff --git a/libs/libc/machine/arch_atomic64.c b/libs/libc/machine/arch_atomic64.c new file mode 100644 index 0000000000000..7d08b7bfe62a2 --- /dev/null +++ b/libs/libc/machine/arch_atomic64.c @@ -0,0 +1,287 @@ +/**************************************************************************** + * libs/libc/machine/arch_atomic64.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* 8 byte atomics are not lock free on every target. An arch may only have a + * 32 bit atomic instruction (TriCore swap.w/cmpswap.w for instance) and a + * toolchain without 64 bit support emits calls to the __atomic_*_8 helpers + * that would otherwise come from libatomic, which NuttX does not link. + * + * The helpers are implemented here on top of a single spinlock. A spinlock + * rather than a plain up_irq_save() is needed because disabling interrupts + * only excludes the local CPU: on SMP another CPU could still enter the same + * critical section and corrupt the 64 bit value. The interrupt state is + * still saved (spin_lock_irqsave) so that an ISR on this CPU cannot deadlock + * against a holder it interrupted. + * + * is deliberately not reused: its macros are built around + * the native word size and a 64 bit access would be silently truncated. All + * symbols are weak, so a toolchain or arch with a native 64 bit + * implementation still wins at link time. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Every 64 bit atomic serializes on this lock. The granularity is coarse, + * but 64 bit atomics are rare enough that a single lock is not a bottleneck. + */ + +static spinlock_t g_atomic64_lock = SP_UNLOCKED; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline irqstate_t atomic64_lock(void) +{ + return spin_lock_irqsave(&g_atomic64_lock); +} + +static inline void atomic64_unlock(irqstate_t flags) +{ + spin_unlock_irqrestore(&g_atomic64_lock, flags); +} + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ATOMIC64_STORE(func, t) \ + weak_function \ + void func(FAR volatile void *ptr, t value, int memorder) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + \ + *(FAR t *)ptr = value; \ + \ + atomic64_unlock(irqstate); \ + } + +#define ATOMIC64_LOAD(func, t) \ + weak_function \ + t func(FAR const volatile void *ptr, int memorder) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + \ + t ret = *(FAR t *)ptr; \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_EXCHANGE(func, t) \ + weak_function \ + t func(FAR volatile void *ptr, t value, int memorder) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + \ + t ret = *tmp; \ + *tmp = value; \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_COMPARE_EXCHANGE(func, t) \ + weak_function \ + bool func(FAR volatile void *mem, FAR volatile void *expect, \ + t desired, bool weak, int success, int failure) \ + { \ + bool ret = false; \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmpmem = (FAR t *)mem; \ + FAR t *tmpexp = (FAR t *)expect; \ + \ + if (*tmpmem == *tmpexp) \ + { \ + ret = true; \ + *tmpmem = desired; \ + } \ + else \ + { \ + *tmpexp = *tmpmem; \ + } \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_FLAGS_TEST_AND_SET(func, t) \ + weak_function \ + t func(FAR volatile void *ptr, int memorder) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret = *tmp; \ + \ + *tmp = 1; \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_FETCH_OP(func, t, op) \ + weak_function \ + t func(FAR volatile void *ptr, t value, int memorder) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret = *tmp; \ + \ + *tmp = *tmp op value; \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_OP_FETCH(func, t, op) \ + weak_function \ + t func(FAR volatile void *ptr, t value) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret; \ + \ + *tmp = *tmp op value; \ + ret = *tmp; \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_NAND_FETCH(func, t) \ + weak_function \ + t func(FAR volatile void *ptr, t value) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret; \ + \ + *tmp = ~(*tmp & value); \ + ret = *tmp; \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_BOOL_CMP_SWAP(func, t) \ + weak_function \ + bool func(FAR volatile void *ptr, t oldvalue, t newvalue) \ + { \ + bool ret = false; \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + \ + if (*tmp == oldvalue) \ + { \ + ret = true; \ + *tmp = newvalue; \ + } \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_VAL_CMP_SWAP(func, t) \ + weak_function \ + t func(FAR volatile void *ptr, t oldvalue, t newvalue) \ + { \ + irqstate_t irqstate = atomic64_lock(); \ + FAR t *tmp = (FAR t *)ptr; \ + t ret = *tmp; \ + \ + if (*tmp == oldvalue) \ + { \ + *tmp = newvalue; \ + } \ + \ + atomic64_unlock(irqstate); \ + return ret; \ + } + +#define ATOMIC64_DEFINE(prefix, t, n) \ + ATOMIC64_STORE(prefix ## _store_ ## n, t) \ + ATOMIC64_LOAD(prefix ## _load_ ## n, t) \ + ATOMIC64_EXCHANGE(prefix ## _exchange_ ## n, t) \ + ATOMIC64_COMPARE_EXCHANGE(prefix ## _compare_exchange_ ## n, t) \ + ATOMIC64_FLAGS_TEST_AND_SET(prefix ## _flags_test_and_set_ ## n, t) \ + ATOMIC64_FETCH_OP(prefix ## _fetch_add_ ## n, t, +) \ + ATOMIC64_FETCH_OP(prefix ## _fetch_sub_ ## n, t, -) \ + ATOMIC64_FETCH_OP(prefix ## _fetch_and_ ## n, t, &) \ + ATOMIC64_FETCH_OP(prefix ## _fetch_or_ ## n, t, |) \ + ATOMIC64_FETCH_OP(prefix ## _fetch_xor_ ## n, t, ^) + +#define SYNC64_DEFINE(prefix, t, n) \ + ATOMIC64_OP_FETCH(prefix ## _add_and_fetch_ ## n, t, +) \ + ATOMIC64_OP_FETCH(prefix ## _sub_and_fetch_ ## n, t, -) \ + ATOMIC64_OP_FETCH(prefix ## _or_and_fetch_ ## n, t, |) \ + ATOMIC64_OP_FETCH(prefix ## _and_and_fetch_ ## n, t, &) \ + ATOMIC64_OP_FETCH(prefix ## _xor_and_fetch_ ## n, t, ^) \ + ATOMIC64_NAND_FETCH(prefix ## _nand_and_fetch_ ## n, t) \ + ATOMIC64_BOOL_CMP_SWAP(prefix ## _bool_compare_and_swap_ ## n, t) \ + ATOMIC64_VAL_CMP_SWAP(prefix ## _val_compare_and_swap_ ## n, t) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: atomic_*_8 and __atomic_*_8 + ****************************************************************************/ + +#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN +ATOMIC64_DEFINE(atomic, int64_t, 8) +#endif + +ATOMIC64_DEFINE(__atomic, uint64_t, 8) + +/* Clang define the __sync builtins, add #ifndef to avoid + * redefined/redeclared problem. + */ + +#ifndef __clang__ + +/**************************************************************************** + * Name: sync_*_8 and __sync_*_8 + ****************************************************************************/ + +#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN +SYNC64_DEFINE(sync, uint64_t, 8) +#endif + +SYNC64_DEFINE(__sync, uint64_t, 8) + +#endif /* __clang__ */