diff --git a/arch/tricore/include/atomic.h b/arch/tricore/include/atomic.h new file mode 100644 index 0000000000000..693e863a67512 --- /dev/null +++ b/arch/tricore/include/atomic.h @@ -0,0 +1,154 @@ +/**************************************************************************** + * 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, ^) + +#define ARCH_HAVE_ATOMIC_4 + +/**************************************************************************** + * 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 aa381a4402ee0..acab3cf7815cc 100644 --- a/include/nuttx/atomic.h +++ b/include/nuttx/atomic.h @@ -27,7 +27,18 @@ * Included Files ****************************************************************************/ +#include + #include +#include +#include + +#ifdef CONFIG_LIBC_ATOMIC_ARCH +# include +#elif defined(CONFIG_LIBC_ATOMIC_IRQ) || \ + defined(CONFIG_LIBC_ATOMIC_HWSPINLOCK) +# include +#endif /**************************************************************************** * Pre-processor Definitions @@ -127,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) \ @@ -135,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) @@ -144,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) \ @@ -152,9 +169,115 @@ 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) +#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_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) \ + 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_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) + +#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_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) \ + 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_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) + +#endif /* UINTPTR_MAX > UINT32_MAX */ + /**************************************************************************** * Public Types ****************************************************************************/ @@ -162,61 +285,10 @@ typedef __Atomic(int32_t) atomic_t; typedef __Atomic(int64_t) atomic64_t; -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ - -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" -{ +#if UINTPTR_MAX > UINT32_MAX +typedef atomic64_t atomic_ptr_t; #else -#define EXTERN extern -#endif - -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -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) -} +typedef atomic_t atomic_ptr_t; #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..165428e8aa5e9 --- /dev/null +++ b/include/nuttx/lib/arch_atomic.h @@ -0,0 +1,273 @@ +/**************************************************************************** + * 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) + +#define ARCH_HAVE_ATOMIC_1 +#define ARCH_HAVE_ATOMIC_2 +#define ARCH_HAVE_ATOMIC_4 + +/**************************************************************************** + * 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_SYNC_DEFINE(sync, uint8_t, 1) +ARCH_SYNC_DEFINE(sync, uint16_t, 2) +ARCH_SYNC_DEFINE(sync, uint32_t, 4) +#endif + +#endif /* __INCLUDE_NUTTX_LIB_ARCH_ATOMIC_H */ diff --git a/libs/libc/machine/CMakeLists.txt b/libs/libc/machine/CMakeLists.txt index 35bbf1cbaffa9..6f340fa278d95 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 e8e03b6543f10..74837fac4d7d1 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 802514c3bd403..5cda66c8b6dbf 100644 --- a/libs/libc/machine/arch_atomic.c +++ b/libs/libc/machine/arch_atomic.c @@ -26,237 +26,28 @@ #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 weak_function -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 + * Name: __atomic_*_{1,2,4} ****************************************************************************/ -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 - ****************************************************************************/ - -FETCH_XOR(__atomic_fetch_xor_, 4, uint32_t) -FETCH_XOR(atomic_fetch_xor_, 4, int32_t) +#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 /* Clang define the __sync builtins, add #ifndef to avoid * redefined/redeclared problem. @@ -265,158 +56,27 @@ 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 - ****************************************************************************/ - -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 + * Name: __sync_*_{1,2,4} ****************************************************************************/ -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 +# 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 +#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 index 41cdeafeaf0a3..7d08b7bfe62a2 100644 --- a/libs/libc/machine/arch_atomic64.c +++ b/libs/libc/machine/arch_atomic64.c @@ -20,129 +20,253 @@ * ****************************************************************************/ +/* 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 "arch_atomic.h" +#include +#include /**************************************************************************** * Private Data ****************************************************************************/ -static spinlock_t g_atomic_lock = SP_UNLOCKED; +/* 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 atomic_lock(void) +static inline irqstate_t atomic64_lock(void) { - return spin_lock_irqsave(&g_atomic_lock); + return spin_lock_irqsave(&g_atomic64_lock); } -static inline void atomic_unlock(irqstate_t flags) +static inline void atomic64_unlock(irqstate_t flags) { - spin_unlock_irqrestore(&g_atomic_lock, flags); + spin_unlock_irqrestore(&g_atomic64_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 + * Pre-processor Definitions ****************************************************************************/ -FETCH_SUB(__atomic_fetch_sub_, 8, uint64_t) -#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FETCH_SUB(atomic_fetch_sub_, 8, int64_t) -#endif +#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) /**************************************************************************** - * Name: __atomic_fetch_and_8 + * Public Functions ****************************************************************************/ -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 + * Name: atomic_*_8 and __atomic_*_8 ****************************************************************************/ -FETCH_OR(__atomic_fetch_or_, 8, uint64_t) #ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN -FETCH_OR(atomic_fetch_or_, 8, int64_t) +ATOMIC64_DEFINE(atomic, int64_t, 8) #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 +ATOMIC64_DEFINE(__atomic, uint64_t, 8) /* Clang define the __sync builtins, add #ifndef to avoid * redefined/redeclared problem. @@ -151,51 +275,13 @@ FETCH_XOR(atomic_fetch_xor_, 8, int64_t) #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 + * Name: sync_*_8 and __sync_*_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 - ****************************************************************************/ +#ifndef CONFIG_LIBC_ATOMIC_TOOLCHAIN +SYNC64_DEFINE(sync, uint64_t, 8) +#endif -SYNC_VAL_CMP_SWAP(__sync_val_compare_and_swap_, 8, uint64_t) +SYNC64_DEFINE(__sync, uint64_t, 8) #endif /* __clang__ */ 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 dd4e83e697eb1..0000000000000 --- a/libs/libc/machine/tricore/arch_atomic.c +++ /dev/null @@ -1,261 +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 - -#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; -} - -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; -} - -/**************************************************************************** - * 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)