EM-ODP  3.7.0
Event Machine on ODP
env_atomic.h
1 /*
2  * Copyright (c) 2013, Nokia Solutions and Networks
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * * Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /*
32  * env helper include file - don't include this file directly,
33  * instead #include "environment.h"
34  */
35 
36 #ifndef _ENV_ATOMIC_H_
37 #define _ENV_ATOMIC_H_
38 
39 #pragma GCC visibility push(default)
40 
41 /*
42  * Atomic operations - types & functions
43  */
44 struct _env_atomic32 {
45  uint32_t a32; /**< Storage for the atomic variable */
46 } ENV_ALIGNED(sizeof(uint32_t)); /* Enforce alignment! */
47 
48 struct _env_atomic64 {
49  uint64_t a64; /**< Storage for the atomic variable */
50 } ENV_ALIGNED(sizeof(uint64_t)); /* Enforce alignment! */
51 
52 typedef struct _env_atomic32 env_atomic32_t;
53 typedef struct _env_atomic64 env_atomic64_t;
54 
55 /*
56  * 32 bit functions
57  */
58 static inline void
59 env_atomic32_init(env_atomic32_t *atom)
60 {
61  __atomic_store_n(&atom->a32, 0, __ATOMIC_SEQ_CST);
62 }
63 
64 static inline void
65 env_atomic32_set(env_atomic32_t *atom, uint32_t new_val)
66 {
67  __atomic_store_n(&atom->a32, new_val, __ATOMIC_SEQ_CST);
68 }
69 
70 static inline uint32_t
71 env_atomic32_get(const env_atomic32_t *atom)
72 {
73  return __atomic_load_n(&atom->a32, __ATOMIC_SEQ_CST);
74 }
75 
76 static inline void
77 env_atomic32_dec(env_atomic32_t *atom)
78 {
79  (void)__atomic_fetch_sub(&atom->a32, 1, __ATOMIC_SEQ_CST);
80 }
81 
82 static inline void
83 env_atomic32_inc(env_atomic32_t *atom)
84 {
85  (void)__atomic_fetch_add(&atom->a32, 1, __ATOMIC_SEQ_CST);
86 }
87 
88 static inline void
89 env_atomic32_add(env_atomic32_t *atom, uint32_t add_val)
90 {
91  (void)__atomic_fetch_add(&atom->a32, add_val, __ATOMIC_SEQ_CST);
92 }
93 
94 static inline void
95 env_atomic32_sub(env_atomic32_t *atom, uint32_t sub_val)
96 {
97  (void)__atomic_fetch_sub(&atom->a32, sub_val, __ATOMIC_SEQ_CST);
98 }
99 
100 static inline uint32_t
101 env_atomic32_add_return(env_atomic32_t *atom, uint32_t add_val)
102 {
103  return __atomic_add_fetch(&atom->a32, add_val, __ATOMIC_SEQ_CST);
104 }
105 
106 static inline uint32_t
107 env_atomic32_return_add(env_atomic32_t *atom, uint32_t add_val)
108 {
109  return __atomic_fetch_add(&atom->a32, add_val, __ATOMIC_SEQ_CST);
110 }
111 
112 static inline uint32_t
113 env_atomic32_sub_return(env_atomic32_t *atom, uint32_t sub_val)
114 {
115  return __atomic_sub_fetch(&atom->a32, sub_val, __ATOMIC_SEQ_CST);
116 }
117 
118 static inline uint32_t
119 env_atomic32_return_sub(env_atomic32_t *atom, uint32_t sub_val)
120 {
121  return __atomic_fetch_sub(&atom->a32, sub_val, __ATOMIC_SEQ_CST);
122 }
123 
124 static inline int
125 env_atomic32_cmpset(env_atomic32_t *atom, uint32_t expected, uint32_t desired)
126 {
127  return __atomic_compare_exchange_n(&atom->a32, &expected, desired,
128  0 /*strong*/, __ATOMIC_SEQ_CST,
129  __ATOMIC_SEQ_CST);
130 }
131 
132 static inline uint32_t
133 env_atomic32_exchange(env_atomic32_t *atom, uint32_t new_val)
134 {
135  return __atomic_exchange_n(&atom->a32, new_val, __ATOMIC_SEQ_CST);
136 }
137 
138 static inline void
139 env_atomic32_set_bits(env_atomic32_t *atom, uint32_t bit_mask)
140 {
141  uint32_t old_val;
142  uint32_t new_val;
143  int ret;
144 
145  do {
146  old_val = env_atomic32_get(atom);
147  new_val = old_val | bit_mask;
148  ret = env_atomic32_cmpset(atom, old_val, new_val);
149  } while (ret == 0);
150 }
151 
152 static inline void
153 env_atomic32_clr_bits(env_atomic32_t *atom, uint32_t bit_mask)
154 {
155  uint32_t old_val;
156  uint32_t new_val;
157  int ret;
158 
159  do {
160  old_val = env_atomic32_get(atom);
161  new_val = old_val & (~bit_mask);
162  ret = env_atomic32_cmpset(atom, old_val, new_val);
163  } while (ret == 0);
164 }
165 
166 static inline int
167 env_atomic32_cnt_bits(const env_atomic32_t *atom)
168 {
169  return __builtin_popcount(env_atomic32_get(atom));
170 }
171 
172 /*
173  * 64 bit functions
174  */
175 static inline void
176 env_atomic64_init(env_atomic64_t *atom)
177 {
178  __atomic_store_n(&atom->a64, 0, __ATOMIC_SEQ_CST);
179 }
180 
181 static inline void
182 env_atomic64_set(env_atomic64_t *atom, uint64_t new_val)
183 {
184  __atomic_store_n(&atom->a64, new_val, __ATOMIC_SEQ_CST);
185 }
186 
187 static inline uint64_t
188 env_atomic64_get(const env_atomic64_t *atom)
189 {
190  return __atomic_load_n(&atom->a64, __ATOMIC_SEQ_CST);
191 }
192 
193 static inline void
194 env_atomic64_dec(env_atomic64_t *atom)
195 {
196  (void)__atomic_fetch_sub(&atom->a64, 1, __ATOMIC_SEQ_CST);
197 }
198 
199 static inline void
200 env_atomic64_inc(env_atomic64_t *atom)
201 {
202  (void)__atomic_fetch_add(&atom->a64, 1, __ATOMIC_SEQ_CST);
203 }
204 
205 static inline void
206 env_atomic64_add(env_atomic64_t *atom, uint64_t add_val)
207 {
208  (void)__atomic_fetch_add(&atom->a64, add_val, __ATOMIC_SEQ_CST);
209 }
210 
211 static inline void
212 env_atomic64_sub(env_atomic64_t *atom, uint64_t sub_val)
213 {
214  (void)__atomic_fetch_sub(&atom->a64, sub_val, __ATOMIC_SEQ_CST);
215 }
216 
217 static inline uint64_t
218 env_atomic64_add_return(env_atomic64_t *atom, uint64_t add_val)
219 {
220  return __atomic_add_fetch(&atom->a64, add_val, __ATOMIC_SEQ_CST);
221 }
222 
223 static inline uint64_t
224 env_atomic64_return_add(env_atomic64_t *atom, uint64_t add_val)
225 {
226  return __atomic_fetch_add(&atom->a64, add_val, __ATOMIC_SEQ_CST);
227 }
228 
229 static inline uint64_t
230 env_atomic64_sub_return(env_atomic64_t *atom, uint64_t sub_val)
231 {
232  return __atomic_sub_fetch(&atom->a64, sub_val, __ATOMIC_SEQ_CST);
233 }
234 
235 static inline uint64_t
236 env_atomic64_return_sub(env_atomic64_t *atom, uint64_t sub_val)
237 {
238  return __atomic_fetch_sub(&atom->a64, sub_val, __ATOMIC_SEQ_CST);
239 }
240 
241 static inline int
242 env_atomic64_cmpset(env_atomic64_t *atom, uint64_t expected, uint64_t desired)
243 {
244  return __atomic_compare_exchange_n(&atom->a64, &expected, desired,
245  0 /*strong*/, __ATOMIC_SEQ_CST,
246  __ATOMIC_SEQ_CST);
247 }
248 
249 static inline uint64_t
250 env_atomic64_exchange(env_atomic64_t *atom, uint64_t new_val)
251 {
252  return __atomic_exchange_n(&atom->a64, new_val, __ATOMIC_SEQ_CST);
253 }
254 
255 static inline void
256 env_atomic64_set_bits(env_atomic64_t *atom, uint64_t bit_mask)
257 {
258  uint64_t old_val;
259  uint64_t new_val;
260  int ret;
261 
262  do {
263  old_val = env_atomic64_get(atom);
264  new_val = old_val | bit_mask;
265  ret = env_atomic64_cmpset(atom, old_val, new_val);
266  } while (ret == 0);
267 }
268 
269 static inline void
270 env_atomic64_clr_bits(env_atomic64_t *atom, uint64_t bit_mask)
271 {
272  uint64_t old_val;
273  uint64_t new_val;
274  int ret;
275 
276  do {
277  old_val = env_atomic64_get(atom);
278  new_val = old_val & (~bit_mask);
279  ret = env_atomic64_cmpset(atom, old_val, new_val);
280  } while (ret == 0);
281 }
282 
283 static inline int
284 env_atomic64_cnt_bits(const env_atomic64_t *atom)
285 {
286  return __builtin_popcountll(env_atomic64_get(atom));
287 }
288 
289 #pragma GCC visibility pop
290 #endif /* _ENV_ATOMIC_H_ */
_env_atomic64
Definition: env_atomic.h:48
_env_atomic32::a32
uint32_t a32
Definition: env_atomic.h:45
_env_atomic64::a64
uint64_t a64
Definition: env_atomic.h:49
_env_atomic32
Definition: env_atomic.h:44