NimBLE-Arduino 2.1.2
Loading...
Searching...
No Matches
atomic.h
1/* atomic operations */
2
3/*
4 * Copyright (c) 1997-2015, Wind River Systems, Inc.
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9#ifndef __ATOMIC_H__
10#define __ATOMIC_H__
11
12#ifdef __cplusplus
13extern "C"
14{
15#endif
16
17typedef int atomic_t;
18typedef atomic_t atomic_val_t;
19
39static inline int atomic_cas(atomic_t *target, atomic_val_t old_value,
40 atomic_val_t new_value)
41{
42 return __atomic_compare_exchange_n(target, &old_value, new_value,
43 0, __ATOMIC_SEQ_CST,
44 __ATOMIC_SEQ_CST);
45}
46
58static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
59{
60 return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
61}
62
75static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
76{
77 return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
78}
79
91static inline atomic_val_t atomic_inc(atomic_t *target)
92{
93 return atomic_add(target, 1);
94}
95
107static inline atomic_val_t atomic_dec(atomic_t *target)
108{
109 return atomic_sub(target, 1);
110}
111
123static inline atomic_val_t atomic_get(const atomic_t *target)
124{
125 return __atomic_load_n(target, __ATOMIC_SEQ_CST);
126}
127
141static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
142{
143 /* This builtin, as described by Intel, is not a traditional
144 * test-and-set operation, but rather an atomic exchange operation. It
145 * writes value into *ptr, and returns the previous contents of *ptr.
146 */
147 return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
148}
149
162static inline atomic_val_t atomic_clear(atomic_t *target)
163{
164 return atomic_set(target, 0);
165}
166
180static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
181{
182 return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
183}
184
198static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
199{
200 return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
201}
202
216static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
217{
218 return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
219}
220
234static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
235{
236 return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
237}
238
247#define ATOMIC_INIT(i) (i)
248
253#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
254#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1)))
255#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
256
274#define ATOMIC_DEFINE(name, num_bits) \
275 atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
276
288 static inline int
289 atomic_test_bit(const atomic_t *target, int bit)
290 {
291 atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
292
293 return (1 & (val >> (bit & (ATOMIC_BITS - 1))));
294 }
295
307 static inline int
308 atomic_test_and_clear_bit(atomic_t *target, int bit)
309 {
310 atomic_val_t mask = ATOMIC_MASK(bit);
311 atomic_val_t old;
312
313 old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
314
315 return (old & mask) != 0;
316 }
317
329 static inline int
330 atomic_test_and_set_bit(atomic_t *target, int bit)
331 {
332 atomic_val_t mask = ATOMIC_MASK(bit);
333 atomic_val_t old;
334
335 old = atomic_or(ATOMIC_ELEM(target, bit), mask);
336
337 return (old & mask) != 0;
338 }
339
351 static inline void
352 atomic_clear_bit(atomic_t *target, int bit)
353 {
354 atomic_val_t mask = ATOMIC_MASK(bit);
355
356 atomic_and(ATOMIC_ELEM(target, bit), ~mask);
357 }
358
370 static inline void
371 atomic_set_bit(atomic_t *target, int bit)
372 {
373 atomic_val_t mask = ATOMIC_MASK(bit);
374
375 atomic_or(ATOMIC_ELEM(target, bit), mask);
376 }
377
390static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
391{
392 atomic_val_t mask = ATOMIC_MASK(bit);
393
394 if (val) {
395 (void)atomic_or(ATOMIC_ELEM(target, bit), mask);
396 } else {
397 (void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
398 }
399}
400
405#ifdef __cplusplus
406}
407#endif
408
409#endif /* __ATOMIC_H__ */