Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions arch/tricore/include/atomic.h
Original file line number Diff line number Diff line change
@@ -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 <nuttx/config.h>
#include <nuttx/compiler.h>

/****************************************************************************
* 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why add here


/****************************************************************************
* 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 */
180 changes: 126 additions & 54 deletions include/nuttx/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,18 @@
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>

#ifdef CONFIG_LIBC_ATOMIC_ARCH
# include <arch/atomic.h>
#elif defined(CONFIG_LIBC_ATOMIC_IRQ) || \
defined(CONFIG_LIBC_ATOMIC_HWSPINLOCK)
# include <nuttx/lib/arch_atomic.h>
#endif

/****************************************************************************
* Pre-processor Definitions
Expand Down Expand Up @@ -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) \
Expand All @@ -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)

Expand All @@ -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) \
Expand All @@ -152,71 +169,126 @@
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
****************************************************************************/

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 */
Loading
Loading