Zephyr API Documentation  3.7.0
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
atomic_xtensa.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Intel Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6#ifndef ZEPHYR_INCLUDE_ATOMIC_XTENSA_H_
7#define ZEPHYR_INCLUDE_ATOMIC_XTENSA_H_
8
9/* Included from <zephyr/sys/atomic.h> */
10
11/* Recent GCC versions actually do have working atomics support on
12 * Xtensa (and so should work with CONFIG_ATOMIC_OPERATIONS_BUILTIN),
13 * but existing versions of Xtensa's XCC do not. So we define an
14 * inline implementation here that is more or less identical
15 */
16
19{
20 atomic_val_t ret;
21
22 /* Actual Xtensa hardware seems to have only in-order
23 * pipelines, but the architecture does define a barrier load,
24 * so use it. There is a matching s32ri instruction, but
25 * nothing in the Zephyr API requires a barrier store (all the
26 * atomic write ops have exchange semantics.
27 */
28 __asm__ volatile("l32ai %0, %1, 0"
29 : "=r"(ret) : "r"(target) : "memory");
30 return ret;
31}
32
50static ALWAYS_INLINE
52 atomic_val_t newval)
53{
54 __asm__ volatile("wsr %1, SCOMPARE1; s32c1i %0, %2, 0"
55 : "+r"(newval), "+r"(oldval) : "r"(addr) : "memory");
56
57 return newval; /* got swapped with the old memory by s32c1i */
58}
59
61static ALWAYS_INLINE
62bool atomic_cas(atomic_t *target, atomic_val_t oldval, atomic_val_t newval)
63{
64 return oldval == xtensa_cas(target, oldval, newval);
65}
66
68static ALWAYS_INLINE
69bool atomic_ptr_cas(atomic_ptr_t *target, void *oldval, void *newval)
70{
71 return (atomic_val_t) oldval
72 == xtensa_cas((atomic_t *) target, (atomic_val_t) oldval,
73 (atomic_val_t) newval);
74}
75
76/* Generates an atomic exchange sequence that swaps the value at
77 * address "target", whose old value is read to be "cur", with the
78 * specified expression. Evaluates to the old value which was
79 * atomically replaced.
80 */
81#define Z__GEN_ATOMXCHG(expr) ({ \
82 atomic_val_t res, cur; \
83 do { \
84 cur = *target; \
85 res = xtensa_cas(target, cur, (expr)); \
86 } while (res != cur); \
87 res; })
88
90static ALWAYS_INLINE
92{
93 return Z__GEN_ATOMXCHG(value);
94}
95
97static ALWAYS_INLINE
99{
100 return Z__GEN_ATOMXCHG(cur + value);
101}
102
104static ALWAYS_INLINE
106{
107 return Z__GEN_ATOMXCHG(cur - value);
108}
109
111static ALWAYS_INLINE
113{
114 return Z__GEN_ATOMXCHG(cur + 1);
115}
116
118static ALWAYS_INLINE
120{
121 return Z__GEN_ATOMXCHG(cur - 1);
122}
123
126 atomic_val_t value)
127{
128 return Z__GEN_ATOMXCHG(cur | value);
129}
130
133 atomic_val_t value)
134{
135 return Z__GEN_ATOMXCHG(cur ^ value);
136}
137
140 atomic_val_t value)
141{
142 return Z__GEN_ATOMXCHG(cur & value);
143}
144
147 atomic_val_t value)
148{
149 return Z__GEN_ATOMXCHG(~(cur & value));
150}
151
153static ALWAYS_INLINE void *atomic_ptr_get(const atomic_ptr_t *target)
154{
155 return (void *) atomic_get((atomic_t *)target);
156}
157
159static ALWAYS_INLINE void *atomic_ptr_set(atomic_ptr_t *target, void *value)
160{
161 return (void *) atomic_set((atomic_t *) target, (atomic_val_t) value);
162}
163
166{
167 return atomic_set(target, 0);
168}
169
172{
173 return (void *) atomic_set((atomic_t *) target, 0);
174}
175
176#endif /* ZEPHYR_INCLUDE_ATOMIC_XTENSA_H_ */
long atomic_t
Definition: atomic_types.h:15
atomic_t atomic_val_t
Definition: atomic_types.h:16
void * atomic_ptr_t
Definition: atomic_types.h:17
static ALWAYS_INLINE void * atomic_ptr_set(atomic_ptr_t *target, void *value)
Implementation of atomic_ptr_set.
Definition: atomic_xtensa.h:159
static ALWAYS_INLINE atomic_val_t atomic_inc(atomic_t *target)
Implementation of atomic_inc.
Definition: atomic_xtensa.h:112
static ALWAYS_INLINE atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
Implementation of atomic_and.
Definition: atomic_xtensa.h:139
static ALWAYS_INLINE atomic_val_t xtensa_cas(atomic_t *addr, atomic_val_t oldval, atomic_val_t newval)
Xtensa specific atomic compare-and-set (CAS).
Definition: atomic_xtensa.h:51
static ALWAYS_INLINE atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
Implementation of atomic_sub.
Definition: atomic_xtensa.h:105
static ALWAYS_INLINE atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
Implementation of atomic_set.
Definition: atomic_xtensa.h:91
static ALWAYS_INLINE void * atomic_ptr_get(const atomic_ptr_t *target)
Implementation of atomic_ptr_get.
Definition: atomic_xtensa.h:153
static ALWAYS_INLINE bool atomic_cas(atomic_t *target, atomic_val_t oldval, atomic_val_t newval)
Implementation of atomic_cas.
Definition: atomic_xtensa.h:62
static ALWAYS_INLINE atomic_val_t atomic_get(const atomic_t *target)
Implementation of atomic_get.
Definition: atomic_xtensa.h:18
static ALWAYS_INLINE atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
Implementation of atomic_add.
Definition: atomic_xtensa.h:98
static ALWAYS_INLINE atomic_val_t atomic_clear(atomic_t *target)
Implementation of atomic_clear.
Definition: atomic_xtensa.h:165
static ALWAYS_INLINE atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
Implementation of atomic_xor.
Definition: atomic_xtensa.h:132
static ALWAYS_INLINE atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
Implementation of atomic_nand.
Definition: atomic_xtensa.h:146
static ALWAYS_INLINE bool atomic_ptr_cas(atomic_ptr_t *target, void *oldval, void *newval)
Implementation of atomic_ptr_cas.
Definition: atomic_xtensa.h:69
static ALWAYS_INLINE atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
Implementation of atomic_or.
Definition: atomic_xtensa.h:125
static ALWAYS_INLINE atomic_val_t atomic_dec(atomic_t *target)
Implementation of atomic_dec.
Definition: atomic_xtensa.h:119
static ALWAYS_INLINE void * atomic_ptr_clear(atomic_ptr_t *target)
Implementation of atomic_ptr_clear.
Definition: atomic_xtensa.h:171
#define ALWAYS_INLINE
Definition: common.h:129