remove extra parentheses in return statement
[dpdk.git] / lib / librte_eal / common / include / arch / ppc_64 / rte_atomic.h
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright (C) IBM Corporation 2014.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of IBM Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34  * Inspired from FreeBSD src/sys/powerpc/include/atomic.h
35  * Copyright (c) 2008 Marcel Moolenaar
36  * Copyright (c) 2001 Benno Rice
37  * Copyright (c) 2001 David E. O'Brien
38  * Copyright (c) 1998 Doug Rabson
39  * All rights reserved.
40  */
41
42 #ifndef _RTE_ATOMIC_PPC_64_H_
43 #define _RTE_ATOMIC_PPC_64_H_
44
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48
49 #include "generic/rte_atomic.h"
50
51 /**
52  * General memory barrier.
53  *
54  * Guarantees that the LOAD and STORE operations generated before the
55  * barrier occur before the LOAD and STORE operations generated after.
56  */
57 #define rte_mb()  {asm volatile("sync" : : : "memory"); }
58
59 /**
60  * Write memory barrier.
61  *
62  * Guarantees that the STORE operations generated before the barrier
63  * occur before the STORE operations generated after.
64  */
65 #define rte_wmb() {asm volatile("sync" : : : "memory"); }
66
67 /**
68  * Read memory barrier.
69  *
70  * Guarantees that the LOAD operations generated before the barrier
71  * occur before the LOAD operations generated after.
72  */
73 #define rte_rmb() {asm volatile("sync" : : : "memory"); }
74
75 #define rte_smp_mb() rte_mb()
76
77 #define rte_smp_wmb() rte_compiler_barrier()
78
79 #define rte_smp_rmb() rte_compiler_barrier()
80
81 /*------------------------- 16 bit atomic operations -------------------------*/
82 /* To be compatible with Power7, use GCC built-in functions for 16 bit
83  * operations */
84
85 #ifndef RTE_FORCE_INTRINSICS
86 static inline int
87 rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src)
88 {
89         return __atomic_compare_exchange(dst, &exp, &src, 0, __ATOMIC_ACQUIRE,
90                 __ATOMIC_ACQUIRE) ? 1 : 0;
91 }
92
93 static inline int rte_atomic16_test_and_set(rte_atomic16_t *v)
94 {
95         return rte_atomic16_cmpset((volatile uint16_t *)&v->cnt, 0, 1);
96 }
97
98 static inline void
99 rte_atomic16_inc(rte_atomic16_t *v)
100 {
101         __atomic_add_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE);
102 }
103
104 static inline void
105 rte_atomic16_dec(rte_atomic16_t *v)
106 {
107         __atomic_sub_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE);
108 }
109
110 static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v)
111 {
112         return __atomic_add_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE) == 0;
113 }
114
115 static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v)
116 {
117         return __atomic_sub_fetch(&v->cnt, 1, __ATOMIC_ACQUIRE) == 0;
118 }
119
120 /*------------------------- 32 bit atomic operations -------------------------*/
121
122 static inline int
123 rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
124 {
125         unsigned int ret = 0;
126
127         asm volatile(
128                         "\tlwsync\n"
129                         "1:\tlwarx %[ret], 0, %[dst]\n"
130                         "cmplw %[exp], %[ret]\n"
131                         "bne 2f\n"
132                         "stwcx. %[src], 0, %[dst]\n"
133                         "bne- 1b\n"
134                         "li %[ret], 1\n"
135                         "b 3f\n"
136                         "2:\n"
137                         "stwcx. %[ret], 0, %[dst]\n"
138                         "li %[ret], 0\n"
139                         "3:\n"
140                         "isync\n"
141                         : [ret] "=&r" (ret), "=m" (*dst)
142                         : [dst] "r" (dst),
143                           [exp] "r" (exp),
144                           [src] "r" (src),
145                           "m" (*dst)
146                         : "cc", "memory");
147
148         return ret;
149 }
150
151 static inline int rte_atomic32_test_and_set(rte_atomic32_t *v)
152 {
153         return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1);
154 }
155
156 static inline void
157 rte_atomic32_inc(rte_atomic32_t *v)
158 {
159         int t;
160
161         asm volatile(
162                         "1: lwarx %[t],0,%[cnt]\n"
163                         "addic %[t],%[t],1\n"
164                         "stwcx. %[t],0,%[cnt]\n"
165                         "bne- 1b\n"
166                         : [t] "=&r" (t), "=m" (v->cnt)
167                         : [cnt] "r" (&v->cnt), "m" (v->cnt)
168                         : "cc", "xer", "memory");
169 }
170
171 static inline void
172 rte_atomic32_dec(rte_atomic32_t *v)
173 {
174         int t;
175
176         asm volatile(
177                         "1: lwarx %[t],0,%[cnt]\n"
178                         "addic %[t],%[t],-1\n"
179                         "stwcx. %[t],0,%[cnt]\n"
180                         "bne- 1b\n"
181                         : [t] "=&r" (t), "=m" (v->cnt)
182                         : [cnt] "r" (&v->cnt), "m" (v->cnt)
183                         : "cc", "xer", "memory");
184 }
185
186 static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v)
187 {
188         int ret;
189
190         asm volatile(
191                         "\n\tlwsync\n"
192                         "1: lwarx %[ret],0,%[cnt]\n"
193                         "addic  %[ret],%[ret],1\n"
194                         "stwcx. %[ret],0,%[cnt]\n"
195                         "bne- 1b\n"
196                         "isync\n"
197                         : [ret] "=&r" (ret)
198                         : [cnt] "r" (&v->cnt)
199                         : "cc", "xer", "memory");
200
201         return ret == 0;
202 }
203
204 static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)
205 {
206         int ret;
207
208         asm volatile(
209                         "\n\tlwsync\n"
210                         "1: lwarx %[ret],0,%[cnt]\n"
211                         "addic %[ret],%[ret],-1\n"
212                         "stwcx. %[ret],0,%[cnt]\n"
213                         "bne- 1b\n"
214                         "isync\n"
215                         : [ret] "=&r" (ret)
216                         : [cnt] "r" (&v->cnt)
217                         : "cc", "xer", "memory");
218
219         return ret == 0;
220 }
221 /*------------------------- 64 bit atomic operations -------------------------*/
222
223 static inline int
224 rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src)
225 {
226         unsigned int ret = 0;
227
228         asm volatile (
229                         "\tlwsync\n"
230                         "1: ldarx %[ret], 0, %[dst]\n"
231                         "cmpld %[exp], %[ret]\n"
232                         "bne 2f\n"
233                         "stdcx. %[src], 0, %[dst]\n"
234                         "bne- 1b\n"
235                         "li %[ret], 1\n"
236                         "b 3f\n"
237                         "2:\n"
238                         "stdcx. %[ret], 0, %[dst]\n"
239                         "li %[ret], 0\n"
240                         "3:\n"
241                         "isync\n"
242                         : [ret] "=&r" (ret), "=m" (*dst)
243                         : [dst] "r" (dst),
244                           [exp] "r" (exp),
245                           [src] "r" (src),
246                           "m" (*dst)
247                         : "cc", "memory");
248         return ret;
249 }
250
251 static inline void
252 rte_atomic64_init(rte_atomic64_t *v)
253 {
254         v->cnt = 0;
255 }
256
257 static inline int64_t
258 rte_atomic64_read(rte_atomic64_t *v)
259 {
260         long ret;
261
262         asm volatile("ld%U1%X1 %[ret],%[cnt]"
263                 : [ret] "=r"(ret)
264                 : [cnt] "m"(v->cnt));
265
266         return ret;
267 }
268
269 static inline void
270 rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
271 {
272         asm volatile("std%U0%X0 %[new_value],%[cnt]"
273                 : [cnt] "=m"(v->cnt)
274                 : [new_value] "r"(new_value));
275 }
276
277 static inline void
278 rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
279 {
280         long t;
281
282         asm volatile(
283                         "1: ldarx %[t],0,%[cnt]\n"
284                         "add %[t],%[inc],%[t]\n"
285                         "stdcx. %[t],0,%[cnt]\n"
286                         "bne- 1b\n"
287                         : [t] "=&r" (t), "=m" (v->cnt)
288                         : [cnt] "r" (&v->cnt), [inc] "r" (inc), "m" (v->cnt)
289                         : "cc", "memory");
290 }
291
292 static inline void
293 rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
294 {
295         long t;
296
297         asm volatile(
298                         "1: ldarx %[t],0,%[cnt]\n"
299                         "subf %[t],%[dec],%[t]\n"
300                         "stdcx. %[t],0,%[cnt]\n"
301                         "bne- 1b\n"
302                         : [t] "=&r" (t), "+m" (v->cnt)
303                         : [cnt] "r" (&v->cnt), [dec] "r" (dec), "m" (v->cnt)
304                         : "cc", "memory");
305 }
306
307 static inline void
308 rte_atomic64_inc(rte_atomic64_t *v)
309 {
310         long t;
311
312         asm volatile(
313                         "1: ldarx %[t],0,%[cnt]\n"
314                         "addic %[t],%[t],1\n"
315                         "stdcx. %[t],0,%[cnt]\n"
316                         "bne- 1b\n"
317                         : [t] "=&r" (t), "+m" (v->cnt)
318                         : [cnt] "r" (&v->cnt), "m" (v->cnt)
319                         : "cc", "xer", "memory");
320 }
321
322 static inline void
323 rte_atomic64_dec(rte_atomic64_t *v)
324 {
325         long t;
326
327         asm volatile(
328                         "1: ldarx %[t],0,%[cnt]\n"
329                         "addic %[t],%[t],-1\n"
330                         "stdcx. %[t],0,%[cnt]\n"
331                         "bne- 1b\n"
332                         : [t] "=&r" (t), "+m" (v->cnt)
333                         : [cnt] "r" (&v->cnt), "m" (v->cnt)
334                         : "cc", "xer", "memory");
335 }
336
337 static inline int64_t
338 rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
339 {
340         long ret;
341
342         asm volatile(
343                         "\n\tlwsync\n"
344                         "1: ldarx %[ret],0,%[cnt]\n"
345                         "add %[ret],%[inc],%[ret]\n"
346                         "stdcx. %[ret],0,%[cnt]\n"
347                         "bne- 1b\n"
348                         "isync\n"
349                         : [ret] "=&r" (ret)
350                         : [inc] "r" (inc), [cnt] "r" (&v->cnt)
351                         : "cc", "memory");
352
353         return ret;
354 }
355
356 static inline int64_t
357 rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
358 {
359         long ret;
360
361         asm volatile(
362                         "\n\tlwsync\n"
363                         "1: ldarx %[ret],0,%[cnt]\n"
364                         "subf %[ret],%[dec],%[ret]\n"
365                         "stdcx. %[ret],0,%[cnt]\n"
366                         "bne- 1b\n"
367                         "isync\n"
368                         : [ret] "=&r" (ret)
369                         : [dec] "r" (dec), [cnt] "r" (&v->cnt)
370                         : "cc", "memory");
371
372         return ret;
373 }
374
375 static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
376 {
377         long ret;
378
379         asm volatile(
380                         "\n\tlwsync\n"
381                         "1: ldarx %[ret],0,%[cnt]\n"
382                         "addic %[ret],%[ret],1\n"
383                         "stdcx. %[ret],0,%[cnt]\n"
384                         "bne- 1b\n"
385                         "isync\n"
386                         : [ret] "=&r" (ret)
387                         : [cnt] "r" (&v->cnt)
388                         : "cc", "xer", "memory");
389
390         return ret == 0;
391 }
392
393 static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
394 {
395         long ret;
396
397         asm volatile(
398                         "\n\tlwsync\n"
399                         "1: ldarx %[ret],0,%[cnt]\n"
400                         "addic %[ret],%[ret],-1\n"
401                         "stdcx. %[ret],0,%[cnt]\n"
402                         "bne- 1b\n"
403                         "isync\n"
404                         : [ret] "=&r" (ret)
405                         : [cnt] "r" (&v->cnt)
406                         : "cc", "xer", "memory");
407
408         return ret == 0;
409 }
410
411 static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
412 {
413         return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
414 }
415
416 /**
417  * Atomically set a 64-bit counter to 0.
418  *
419  * @param v
420  *   A pointer to the atomic counter.
421  */
422 static inline void rte_atomic64_clear(rte_atomic64_t *v)
423 {
424         v->cnt = 0;
425 }
426 #endif
427
428 #ifdef __cplusplus
429 }
430 #endif
431
432 #endif /* _RTE_ATOMIC_PPC_64_H_ */