-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatomic.h
163 lines (134 loc) · 3.13 KB
/
atomic.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#ifndef ATOMIC_H
#define ATOMIC_H
// Adapted from http://golubenco.org/2007/06/14/atomic-operations
/**
* @brief Atomic type
*/
typedef int atomic_t;
#define ATOMIC_INIT(i) (i)
/**
* @brief Atomic read
*
* @param v pointer of type atomic_t
*/
static inline int atomic_read(atomic_t *v)
{
return *(volatile int *)v;
}
/**
* @brief Atomic write
*
* @param v pointer of type atomic_t
* @param i new integer value
*/
static inline void atomic_set(atomic_t *v, int i)
{
*v = i;
}
/**
* @brief Atomic add
*
* @param i integer value to add
* @param v pointer of type atomic_t
* @return new value of @v
*/
static inline int atomic_add(int i, atomic_t *v)
{
return __sync_add_and_fetch(v, i);
}
/**
* @brief Atomic subtract
*
* @param i integer value to subtract
* @param v pointer of type atomic_t
* @return new value of @v
*/
static inline int atomic_sub(int i, atomic_t *v)
{
return __sync_sub_and_fetch(v, i);
}
/**
* @brief Atomic subtract and test if zero
*
* @param i integer value to subtract
* @param v pointer of type atomic_t
*
* Atomically subtracts @i from @v and returns true if the result is 0
* and false otherwise.
*/
static inline int atomic_sub_and_test(int i, atomic_t *v)
{
return !(__sync_sub_and_fetch(v, i));
}
/**
* @brief Atomic add and test if zero
*
* @param i integer value to add
* @param v pointer of type atomic_t
*
* Atomically adds @i to @v and returns true if the result is 0
* and false otherwise.
*/
static inline int atomic_add_and_test(int i, atomic_t *v)
{
return !(__sync_add_and_fetch(v, i));
}
/**
* @brief Atomic increment
*
* @param v pointer of type atomic_t
* @return incremented value of @v
*/
#define atomic_inc(v) atomic_add(1, v)
/**
* @brief Atomic decrement
*
* @param v: pointer of type atomic_t
* @return decremented value of @v
*/
#define atomic_dec(v) atomic_sub(1, v)
/**
* @brief Atomic decrement and test if zero
*
* @param v pointer of type atomic_t
*
* Atomically decrements @v by 1 and returns true if the result is 0
* and false otherwise.
*/
#define atomic_dec_and_test(v) atomic_sub_and_test(1, v)
/**
* @brief Atomic increment and test if zero
*
* @param v pointer of type atomic_t
*
* Atomically increments @v by 1 and returns true if the result is 0
* and false otherwise.
*/
#define atomic_inc_and_test(v) atomic_add_and_test(1, v)
/**
* @brief Compare and swap (CAS)
*
* @param v pointer of type atomic_t
* @param oldval old integer value
* @param newval new integer value
* @return true if comparison was successful and @newval was written,
* false otherwise
*
* Atomically tests if @v == @oldval, and if true sets @v to @newval.
*/
static inline int atomic_CAS(atomic_t *v, int oldval, int newval)
{
return __sync_bool_compare_and_swap(v, oldval, newval);
}
// Prevents the compiler from reordering memory operations
#define __compiler_barrier() \
__asm__ __volatile__ ("" : : : "memory")
// Full memory barrier (includes compiler barriers for safety)
// See http://gcc.gnu.org/ml/gcc/2011-09/msg00088.html
#define __memory_barrier() \
{ \
__compiler_barrier(); \
__sync_synchronize(); \
__compiler_barrier(); \
}
#endif // ATOMIC_H