blob: 88360ee5d02f2227e0c880d2d1c74ea9f7c7f83d [file] [log] [blame]
yayun.shi4a7148a2021-07-16 06:13:50 -04001//GCC Atomic builtins helpers
2#ifndef _ATOMIC_H
3#define _ATOMIC_H
4
5/* Check GCC version, just to be safe */
6#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
7# error atomic.h works only with GCC newer than version 4.1
8#endif /* GNUC >= 4.1 */
9
10/**
11 * Atomic type.
12 */
13typedef struct {
14 volatile int counter;
15} atomic_t;
16
17#define ATOMIC_INIT(i) { (i) }
18
19/**
20 * Read atomic variable
21 * @param v pointer of type atomic_t
22 *
23 * Atomically reads the value of @v.
24 */
25#define atomic_read(v) ((v)->counter)
26
27/**
28 * Set atomic variable
29 * @param v pointer of type atomic_t
30 * @param i required value
31 */
32#define atomic_set(v,i) (((v)->counter) = (i))
33
34/**
35 * Add to the atomic variable
36 * @param i integer value to add
37 * @param v pointer of type atomic_t
38 */
39static inline void atomic_add( int i, atomic_t *v )
40{
41 (void)__sync_add_and_fetch(&v->counter, i);
42}
43
44/**
45 * Subtract the atomic variable
46 * @param i integer value to subtract
47 * @param v pointer of type atomic_t
48 *
49 * Atomically subtracts @i from @v.
50 */
51static inline void atomic_sub( int i, atomic_t *v )
52{
53 (void)__sync_sub_and_fetch(&v->counter, i);
54}
55
56/**
57 * Subtract value from variable and test result
58 * @param i integer value to subtract
59 * @param v pointer of type atomic_t
60 *
61 * Atomically subtracts @i from @v and returns
62 * true if the result is zero, or false for all
63 * other cases.
64 */
65static inline int atomic_sub_and_test( int i, atomic_t *v )
66{
67 return !(__sync_sub_and_fetch(&v->counter, i));
68}
69
70/**
71 * Increment atomic variable
72 * @param v pointer of type atomic_t
73 *
74 * Atomically increments @v by 1.
75 */
76static inline int atomic_inc( atomic_t *v )
77{
78 return __sync_fetch_and_add(&v->counter, 1);
79}
80
81/**
82 * @brief decrement atomic variable
83 * @param v: pointer of type atomic_t
84 *
85 * Atomically decrements @v by 1. Note that the guaranteed
86 * useful range of an atomic_t is only 24 bits.
87 */
88static inline int atomic_dec( atomic_t *v )
89{
90 return __sync_fetch_and_sub(&v->counter, 1);
91}
92
93/**
94 * @brief Decrement and test
95 * @param v pointer of type atomic_t
96 *
97 * Atomically decrements @v by 1 and
98 * returns true if the result is 0, or false for all other
99 * cases.
100 */
101static inline int atomic_dec_and_test( atomic_t *v )
102{
103 return !(__sync_sub_and_fetch(&v->counter, 1));
104}
105
106/**
107 * @brief Increment and test
108 * @param v pointer of type atomic_t
109 *
110 * Atomically increments @v by 1
111 * and returns true if the result is zero, or false for all
112 * other cases.
113 */
114static inline int atomic_inc_and_test( atomic_t *v )
115{
116 return !(__sync_add_and_fetch(&v->counter, 1));
117}
118
119/**
120 * @brief add and test if negative
121 * @param v pointer of type atomic_t
122 * @param i integer value to add
123 *
124 * Atomically adds @i to @v and returns true
125 * if the result is negative, or false when
126 * result is greater than or equal to zero.
127 */
128static inline int atomic_add_negative( int i, atomic_t *v )
129{
130 return (__sync_add_and_fetch(&v->counter, i) < 0);
131}
132
133#endif