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