remove extra parentheses in return statement
[dpdk.git] / lib / librte_eal / common / include / generic / rte_atomic.h
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #ifndef _RTE_ATOMIC_H_
35 #define _RTE_ATOMIC_H_
36
37 /**
38  * @file
39  * Atomic Operations
40  *
41  * This file defines a generic API for atomic operations.
42  */
43
44 #include <stdint.h>
45
46 #ifdef __DOXYGEN__
47
48 /**
49  * General memory barrier.
50  *
51  * Guarantees that the LOAD and STORE operations generated before the
52  * barrier occur before the LOAD and STORE operations generated after.
53  * This function is architecture dependent.
54  */
55 static inline void rte_mb(void);
56
57 /**
58  * Write memory barrier.
59  *
60  * Guarantees that the STORE operations generated before the barrier
61  * occur before the STORE operations generated after.
62  * This function is architecture dependent.
63  */
64 static inline void rte_wmb(void);
65
66 /**
67  * Read memory barrier.
68  *
69  * Guarantees that the LOAD operations generated before the barrier
70  * occur before the LOAD operations generated after.
71  * This function is architecture dependent.
72  */
73 static inline void rte_rmb(void);
74
75 /**
76  * General memory barrier between lcores
77  *
78  * Guarantees that the LOAD and STORE operations that precede the
79  * rte_smp_mb() call are globally visible across the lcores
80  * before the the LOAD and STORE operations that follows it.
81  */
82 static inline void rte_smp_mb(void);
83
84 /**
85  * Write memory barrier between lcores
86  *
87  * Guarantees that the STORE operations that precede the
88  * rte_smp_wmb() call are globally visible across the lcores
89  * before the the STORE operations that follows it.
90  */
91 static inline void rte_smp_wmb(void);
92
93 /**
94  * Read memory barrier between lcores
95  *
96  * Guarantees that the LOAD operations that precede the
97  * rte_smp_rmb() call are globally visible across the lcores
98  * before the the LOAD operations that follows it.
99  */
100 static inline void rte_smp_rmb(void);
101
102 #endif /* __DOXYGEN__ */
103
104 /**
105  * Compiler barrier.
106  *
107  * Guarantees that operation reordering does not occur at compile time
108  * for operations directly before and after the barrier.
109  */
110 #define rte_compiler_barrier() do {             \
111         asm volatile ("" : : : "memory");       \
112 } while(0)
113
114 /*------------------------- 16 bit atomic operations -------------------------*/
115
116 /**
117  * Atomic compare and set.
118  *
119  * (atomic) equivalent to:
120  *   if (*dst == exp)
121  *     *dst = src (all 16-bit words)
122  *
123  * @param dst
124  *   The destination location into which the value will be written.
125  * @param exp
126  *   The expected value.
127  * @param src
128  *   The new value.
129  * @return
130  *   Non-zero on success; 0 on failure.
131  */
132 static inline int
133 rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src);
134
135 #ifdef RTE_FORCE_INTRINSICS
136 static inline int
137 rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src)
138 {
139         return __sync_bool_compare_and_swap(dst, exp, src);
140 }
141 #endif
142
143 /**
144  * The atomic counter structure.
145  */
146 typedef struct {
147         volatile int16_t cnt; /**< An internal counter value. */
148 } rte_atomic16_t;
149
150 /**
151  * Static initializer for an atomic counter.
152  */
153 #define RTE_ATOMIC16_INIT(val) { (val) }
154
155 /**
156  * Initialize an atomic counter.
157  *
158  * @param v
159  *   A pointer to the atomic counter.
160  */
161 static inline void
162 rte_atomic16_init(rte_atomic16_t *v)
163 {
164         v->cnt = 0;
165 }
166
167 /**
168  * Atomically read a 16-bit value from a counter.
169  *
170  * @param v
171  *   A pointer to the atomic counter.
172  * @return
173  *   The value of the counter.
174  */
175 static inline int16_t
176 rte_atomic16_read(const rte_atomic16_t *v)
177 {
178         return v->cnt;
179 }
180
181 /**
182  * Atomically set a counter to a 16-bit value.
183  *
184  * @param v
185  *   A pointer to the atomic counter.
186  * @param new_value
187  *   The new value for the counter.
188  */
189 static inline void
190 rte_atomic16_set(rte_atomic16_t *v, int16_t new_value)
191 {
192         v->cnt = new_value;
193 }
194
195 /**
196  * Atomically add a 16-bit value to an atomic counter.
197  *
198  * @param v
199  *   A pointer to the atomic counter.
200  * @param inc
201  *   The value to be added to the counter.
202  */
203 static inline void
204 rte_atomic16_add(rte_atomic16_t *v, int16_t inc)
205 {
206         __sync_fetch_and_add(&v->cnt, inc);
207 }
208
209 /**
210  * Atomically subtract a 16-bit value from an atomic counter.
211  *
212  * @param v
213  *   A pointer to the atomic counter.
214  * @param dec
215  *   The value to be subtracted from the counter.
216  */
217 static inline void
218 rte_atomic16_sub(rte_atomic16_t *v, int16_t dec)
219 {
220         __sync_fetch_and_sub(&v->cnt, dec);
221 }
222
223 /**
224  * Atomically increment a counter by one.
225  *
226  * @param v
227  *   A pointer to the atomic counter.
228  */
229 static inline void
230 rte_atomic16_inc(rte_atomic16_t *v);
231
232 #ifdef RTE_FORCE_INTRINSICS
233 static inline void
234 rte_atomic16_inc(rte_atomic16_t *v)
235 {
236         rte_atomic16_add(v, 1);
237 }
238 #endif
239
240 /**
241  * Atomically decrement a counter by one.
242  *
243  * @param v
244  *   A pointer to the atomic counter.
245  */
246 static inline void
247 rte_atomic16_dec(rte_atomic16_t *v);
248
249 #ifdef RTE_FORCE_INTRINSICS
250 static inline void
251 rte_atomic16_dec(rte_atomic16_t *v)
252 {
253         rte_atomic16_sub(v, 1);
254 }
255 #endif
256
257 /**
258  * Atomically add a 16-bit value to a counter and return the result.
259  *
260  * Atomically adds the 16-bits value (inc) to the atomic counter (v) and
261  * returns the value of v after addition.
262  *
263  * @param v
264  *   A pointer to the atomic counter.
265  * @param inc
266  *   The value to be added to the counter.
267  * @return
268  *   The value of v after the addition.
269  */
270 static inline int16_t
271 rte_atomic16_add_return(rte_atomic16_t *v, int16_t inc)
272 {
273         return __sync_add_and_fetch(&v->cnt, inc);
274 }
275
276 /**
277  * Atomically subtract a 16-bit value from a counter and return
278  * the result.
279  *
280  * Atomically subtracts the 16-bit value (inc) from the atomic counter
281  * (v) and returns the value of v after the subtraction.
282  *
283  * @param v
284  *   A pointer to the atomic counter.
285  * @param dec
286  *   The value to be subtracted from the counter.
287  * @return
288  *   The value of v after the subtraction.
289  */
290 static inline int16_t
291 rte_atomic16_sub_return(rte_atomic16_t *v, int16_t dec)
292 {
293         return __sync_sub_and_fetch(&v->cnt, dec);
294 }
295
296 /**
297  * Atomically increment a 16-bit counter by one and test.
298  *
299  * Atomically increments the atomic counter (v) by one and returns true if
300  * the result is 0, or false in all other cases.
301  *
302  * @param v
303  *   A pointer to the atomic counter.
304  * @return
305  *   True if the result after the increment operation is 0; false otherwise.
306  */
307 static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v);
308
309 #ifdef RTE_FORCE_INTRINSICS
310 static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v)
311 {
312         return __sync_add_and_fetch(&v->cnt, 1) == 0;
313 }
314 #endif
315
316 /**
317  * Atomically decrement a 16-bit counter by one and test.
318  *
319  * Atomically decrements the atomic counter (v) by one and returns true if
320  * the result is 0, or false in all other cases.
321  *
322  * @param v
323  *   A pointer to the atomic counter.
324  * @return
325  *   True if the result after the decrement operation is 0; false otherwise.
326  */
327 static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v);
328
329 #ifdef RTE_FORCE_INTRINSICS
330 static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v)
331 {
332         return __sync_sub_and_fetch(&v->cnt, 1) == 0;
333 }
334 #endif
335
336 /**
337  * Atomically test and set a 16-bit atomic counter.
338  *
339  * If the counter value is already set, return 0 (failed). Otherwise, set
340  * the counter value to 1 and return 1 (success).
341  *
342  * @param v
343  *   A pointer to the atomic counter.
344  * @return
345  *   0 if failed; else 1, success.
346  */
347 static inline int rte_atomic16_test_and_set(rte_atomic16_t *v);
348
349 #ifdef RTE_FORCE_INTRINSICS
350 static inline int rte_atomic16_test_and_set(rte_atomic16_t *v)
351 {
352         return rte_atomic16_cmpset((volatile uint16_t *)&v->cnt, 0, 1);
353 }
354 #endif
355
356 /**
357  * Atomically set a 16-bit counter to 0.
358  *
359  * @param v
360  *   A pointer to the atomic counter.
361  */
362 static inline void rte_atomic16_clear(rte_atomic16_t *v)
363 {
364         v->cnt = 0;
365 }
366
367 /*------------------------- 32 bit atomic operations -------------------------*/
368
369 /**
370  * Atomic compare and set.
371  *
372  * (atomic) equivalent to:
373  *   if (*dst == exp)
374  *     *dst = src (all 32-bit words)
375  *
376  * @param dst
377  *   The destination location into which the value will be written.
378  * @param exp
379  *   The expected value.
380  * @param src
381  *   The new value.
382  * @return
383  *   Non-zero on success; 0 on failure.
384  */
385 static inline int
386 rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src);
387
388 #ifdef RTE_FORCE_INTRINSICS
389 static inline int
390 rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
391 {
392         return __sync_bool_compare_and_swap(dst, exp, src);
393 }
394 #endif
395
396 /**
397  * The atomic counter structure.
398  */
399 typedef struct {
400         volatile int32_t cnt; /**< An internal counter value. */
401 } rte_atomic32_t;
402
403 /**
404  * Static initializer for an atomic counter.
405  */
406 #define RTE_ATOMIC32_INIT(val) { (val) }
407
408 /**
409  * Initialize an atomic counter.
410  *
411  * @param v
412  *   A pointer to the atomic counter.
413  */
414 static inline void
415 rte_atomic32_init(rte_atomic32_t *v)
416 {
417         v->cnt = 0;
418 }
419
420 /**
421  * Atomically read a 32-bit value from a counter.
422  *
423  * @param v
424  *   A pointer to the atomic counter.
425  * @return
426  *   The value of the counter.
427  */
428 static inline int32_t
429 rte_atomic32_read(const rte_atomic32_t *v)
430 {
431         return v->cnt;
432 }
433
434 /**
435  * Atomically set a counter to a 32-bit value.
436  *
437  * @param v
438  *   A pointer to the atomic counter.
439  * @param new_value
440  *   The new value for the counter.
441  */
442 static inline void
443 rte_atomic32_set(rte_atomic32_t *v, int32_t new_value)
444 {
445         v->cnt = new_value;
446 }
447
448 /**
449  * Atomically add a 32-bit value to an atomic counter.
450  *
451  * @param v
452  *   A pointer to the atomic counter.
453  * @param inc
454  *   The value to be added to the counter.
455  */
456 static inline void
457 rte_atomic32_add(rte_atomic32_t *v, int32_t inc)
458 {
459         __sync_fetch_and_add(&v->cnt, inc);
460 }
461
462 /**
463  * Atomically subtract a 32-bit value from an atomic counter.
464  *
465  * @param v
466  *   A pointer to the atomic counter.
467  * @param dec
468  *   The value to be subtracted from the counter.
469  */
470 static inline void
471 rte_atomic32_sub(rte_atomic32_t *v, int32_t dec)
472 {
473         __sync_fetch_and_sub(&v->cnt, dec);
474 }
475
476 /**
477  * Atomically increment a counter by one.
478  *
479  * @param v
480  *   A pointer to the atomic counter.
481  */
482 static inline void
483 rte_atomic32_inc(rte_atomic32_t *v);
484
485 #ifdef RTE_FORCE_INTRINSICS
486 static inline void
487 rte_atomic32_inc(rte_atomic32_t *v)
488 {
489         rte_atomic32_add(v, 1);
490 }
491 #endif
492
493 /**
494  * Atomically decrement a counter by one.
495  *
496  * @param v
497  *   A pointer to the atomic counter.
498  */
499 static inline void
500 rte_atomic32_dec(rte_atomic32_t *v);
501
502 #ifdef RTE_FORCE_INTRINSICS
503 static inline void
504 rte_atomic32_dec(rte_atomic32_t *v)
505 {
506         rte_atomic32_sub(v,1);
507 }
508 #endif
509
510 /**
511  * Atomically add a 32-bit value to a counter and return the result.
512  *
513  * Atomically adds the 32-bits value (inc) to the atomic counter (v) and
514  * returns the value of v after addition.
515  *
516  * @param v
517  *   A pointer to the atomic counter.
518  * @param inc
519  *   The value to be added to the counter.
520  * @return
521  *   The value of v after the addition.
522  */
523 static inline int32_t
524 rte_atomic32_add_return(rte_atomic32_t *v, int32_t inc)
525 {
526         return __sync_add_and_fetch(&v->cnt, inc);
527 }
528
529 /**
530  * Atomically subtract a 32-bit value from a counter and return
531  * the result.
532  *
533  * Atomically subtracts the 32-bit value (inc) from the atomic counter
534  * (v) and returns the value of v after the subtraction.
535  *
536  * @param v
537  *   A pointer to the atomic counter.
538  * @param dec
539  *   The value to be subtracted from the counter.
540  * @return
541  *   The value of v after the subtraction.
542  */
543 static inline int32_t
544 rte_atomic32_sub_return(rte_atomic32_t *v, int32_t dec)
545 {
546         return __sync_sub_and_fetch(&v->cnt, dec);
547 }
548
549 /**
550  * Atomically increment a 32-bit counter by one and test.
551  *
552  * Atomically increments the atomic counter (v) by one and returns true if
553  * the result is 0, or false in all other cases.
554  *
555  * @param v
556  *   A pointer to the atomic counter.
557  * @return
558  *   True if the result after the increment operation is 0; false otherwise.
559  */
560 static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v);
561
562 #ifdef RTE_FORCE_INTRINSICS
563 static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v)
564 {
565         return __sync_add_and_fetch(&v->cnt, 1) == 0;
566 }
567 #endif
568
569 /**
570  * Atomically decrement a 32-bit counter by one and test.
571  *
572  * Atomically decrements the atomic counter (v) by one and returns true if
573  * the result is 0, or false in all other cases.
574  *
575  * @param v
576  *   A pointer to the atomic counter.
577  * @return
578  *   True if the result after the decrement operation is 0; false otherwise.
579  */
580 static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v);
581
582 #ifdef RTE_FORCE_INTRINSICS
583 static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)
584 {
585         return __sync_sub_and_fetch(&v->cnt, 1) == 0;
586 }
587 #endif
588
589 /**
590  * Atomically test and set a 32-bit atomic counter.
591  *
592  * If the counter value is already set, return 0 (failed). Otherwise, set
593  * the counter value to 1 and return 1 (success).
594  *
595  * @param v
596  *   A pointer to the atomic counter.
597  * @return
598  *   0 if failed; else 1, success.
599  */
600 static inline int rte_atomic32_test_and_set(rte_atomic32_t *v);
601
602 #ifdef RTE_FORCE_INTRINSICS
603 static inline int rte_atomic32_test_and_set(rte_atomic32_t *v)
604 {
605         return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1);
606 }
607 #endif
608
609 /**
610  * Atomically set a 32-bit counter to 0.
611  *
612  * @param v
613  *   A pointer to the atomic counter.
614  */
615 static inline void rte_atomic32_clear(rte_atomic32_t *v)
616 {
617         v->cnt = 0;
618 }
619
620 /*------------------------- 64 bit atomic operations -------------------------*/
621
622 /**
623  * An atomic compare and set function used by the mutex functions.
624  * (atomic) equivalent to:
625  *   if (*dst == exp)
626  *     *dst = src (all 64-bit words)
627  *
628  * @param dst
629  *   The destination into which the value will be written.
630  * @param exp
631  *   The expected value.
632  * @param src
633  *   The new value.
634  * @return
635  *   Non-zero on success; 0 on failure.
636  */
637 static inline int
638 rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src);
639
640 #ifdef RTE_FORCE_INTRINSICS
641 static inline int
642 rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src)
643 {
644         return __sync_bool_compare_and_swap(dst, exp, src);
645 }
646 #endif
647
648 /**
649  * The atomic counter structure.
650  */
651 typedef struct {
652         volatile int64_t cnt;  /**< Internal counter value. */
653 } rte_atomic64_t;
654
655 /**
656  * Static initializer for an atomic counter.
657  */
658 #define RTE_ATOMIC64_INIT(val) { (val) }
659
660 /**
661  * Initialize the atomic counter.
662  *
663  * @param v
664  *   A pointer to the atomic counter.
665  */
666 static inline void
667 rte_atomic64_init(rte_atomic64_t *v);
668
669 #ifdef RTE_FORCE_INTRINSICS
670 static inline void
671 rte_atomic64_init(rte_atomic64_t *v)
672 {
673 #ifdef __LP64__
674         v->cnt = 0;
675 #else
676         int success = 0;
677         uint64_t tmp;
678
679         while (success == 0) {
680                 tmp = v->cnt;
681                 success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt,
682                                               tmp, 0);
683         }
684 #endif
685 }
686 #endif
687
688 /**
689  * Atomically read a 64-bit counter.
690  *
691  * @param v
692  *   A pointer to the atomic counter.
693  * @return
694  *   The value of the counter.
695  */
696 static inline int64_t
697 rte_atomic64_read(rte_atomic64_t *v);
698
699 #ifdef RTE_FORCE_INTRINSICS
700 static inline int64_t
701 rte_atomic64_read(rte_atomic64_t *v)
702 {
703 #ifdef __LP64__
704         return v->cnt;
705 #else
706         int success = 0;
707         uint64_t tmp;
708
709         while (success == 0) {
710                 tmp = v->cnt;
711                 /* replace the value by itself */
712                 success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt,
713                                               tmp, tmp);
714         }
715         return tmp;
716 #endif
717 }
718 #endif
719
720 /**
721  * Atomically set a 64-bit counter.
722  *
723  * @param v
724  *   A pointer to the atomic counter.
725  * @param new_value
726  *   The new value of the counter.
727  */
728 static inline void
729 rte_atomic64_set(rte_atomic64_t *v, int64_t new_value);
730
731 #ifdef RTE_FORCE_INTRINSICS
732 static inline void
733 rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
734 {
735 #ifdef __LP64__
736         v->cnt = new_value;
737 #else
738         int success = 0;
739         uint64_t tmp;
740
741         while (success == 0) {
742                 tmp = v->cnt;
743                 success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt,
744                                               tmp, new_value);
745         }
746 #endif
747 }
748 #endif
749
750 /**
751  * Atomically add a 64-bit value to a counter.
752  *
753  * @param v
754  *   A pointer to the atomic counter.
755  * @param inc
756  *   The value to be added to the counter.
757  */
758 static inline void
759 rte_atomic64_add(rte_atomic64_t *v, int64_t inc);
760
761 #ifdef RTE_FORCE_INTRINSICS
762 static inline void
763 rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
764 {
765         __sync_fetch_and_add(&v->cnt, inc);
766 }
767 #endif
768
769 /**
770  * Atomically subtract a 64-bit value from a counter.
771  *
772  * @param v
773  *   A pointer to the atomic counter.
774  * @param dec
775  *   The value to be subtracted from the counter.
776  */
777 static inline void
778 rte_atomic64_sub(rte_atomic64_t *v, int64_t dec);
779
780 #ifdef RTE_FORCE_INTRINSICS
781 static inline void
782 rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
783 {
784         __sync_fetch_and_sub(&v->cnt, dec);
785 }
786 #endif
787
788 /**
789  * Atomically increment a 64-bit counter by one and test.
790  *
791  * @param v
792  *   A pointer to the atomic counter.
793  */
794 static inline void
795 rte_atomic64_inc(rte_atomic64_t *v);
796
797 #ifdef RTE_FORCE_INTRINSICS
798 static inline void
799 rte_atomic64_inc(rte_atomic64_t *v)
800 {
801         rte_atomic64_add(v, 1);
802 }
803 #endif
804
805 /**
806  * Atomically decrement a 64-bit counter by one and test.
807  *
808  * @param v
809  *   A pointer to the atomic counter.
810  */
811 static inline void
812 rte_atomic64_dec(rte_atomic64_t *v);
813
814 #ifdef RTE_FORCE_INTRINSICS
815 static inline void
816 rte_atomic64_dec(rte_atomic64_t *v)
817 {
818         rte_atomic64_sub(v, 1);
819 }
820 #endif
821
822 /**
823  * Add a 64-bit value to an atomic counter and return the result.
824  *
825  * Atomically adds the 64-bit value (inc) to the atomic counter (v) and
826  * returns the value of v after the addition.
827  *
828  * @param v
829  *   A pointer to the atomic counter.
830  * @param inc
831  *   The value to be added to the counter.
832  * @return
833  *   The value of v after the addition.
834  */
835 static inline int64_t
836 rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc);
837
838 #ifdef RTE_FORCE_INTRINSICS
839 static inline int64_t
840 rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
841 {
842         return __sync_add_and_fetch(&v->cnt, inc);
843 }
844 #endif
845
846 /**
847  * Subtract a 64-bit value from an atomic counter and return the result.
848  *
849  * Atomically subtracts the 64-bit value (dec) from the atomic counter (v)
850  * and returns the value of v after the subtraction.
851  *
852  * @param v
853  *   A pointer to the atomic counter.
854  * @param dec
855  *   The value to be subtracted from the counter.
856  * @return
857  *   The value of v after the subtraction.
858  */
859 static inline int64_t
860 rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec);
861
862 #ifdef RTE_FORCE_INTRINSICS
863 static inline int64_t
864 rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
865 {
866         return __sync_sub_and_fetch(&v->cnt, dec);
867 }
868 #endif
869
870 /**
871  * Atomically increment a 64-bit counter by one and test.
872  *
873  * Atomically increments the atomic counter (v) by one and returns
874  * true if the result is 0, or false in all other cases.
875  *
876  * @param v
877  *   A pointer to the atomic counter.
878  * @return
879  *   True if the result after the addition is 0; false otherwise.
880  */
881 static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v);
882
883 #ifdef RTE_FORCE_INTRINSICS
884 static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
885 {
886         return rte_atomic64_add_return(v, 1) == 0;
887 }
888 #endif
889
890 /**
891  * Atomically decrement a 64-bit counter by one and test.
892  *
893  * Atomically decrements the atomic counter (v) by one and returns true if
894  * the result is 0, or false in all other cases.
895  *
896  * @param v
897  *   A pointer to the atomic counter.
898  * @return
899  *   True if the result after subtraction is 0; false otherwise.
900  */
901 static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v);
902
903 #ifdef RTE_FORCE_INTRINSICS
904 static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
905 {
906         return rte_atomic64_sub_return(v, 1) == 0;
907 }
908 #endif
909
910 /**
911  * Atomically test and set a 64-bit atomic counter.
912  *
913  * If the counter value is already set, return 0 (failed). Otherwise, set
914  * the counter value to 1 and return 1 (success).
915  *
916  * @param v
917  *   A pointer to the atomic counter.
918  * @return
919  *   0 if failed; else 1, success.
920  */
921 static inline int rte_atomic64_test_and_set(rte_atomic64_t *v);
922
923 #ifdef RTE_FORCE_INTRINSICS
924 static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
925 {
926         return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
927 }
928 #endif
929
930 /**
931  * Atomically set a 64-bit counter to 0.
932  *
933  * @param v
934  *   A pointer to the atomic counter.
935  */
936 static inline void rte_atomic64_clear(rte_atomic64_t *v);
937
938 #ifdef RTE_FORCE_INTRINSICS
939 static inline void rte_atomic64_clear(rte_atomic64_t *v)
940 {
941         rte_atomic64_set(v, 0);
942 }
943 #endif
944
945 #endif /* _RTE_ATOMIC_H_ */