xref: /dpdk/lib/eal/include/generic/rte_atomic.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #ifndef _RTE_ATOMIC_H_
699a2dd95SBruce Richardson #define _RTE_ATOMIC_H_
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson /**
999a2dd95SBruce Richardson  * @file
1099a2dd95SBruce Richardson  * Atomic Operations
1199a2dd95SBruce Richardson  *
1299a2dd95SBruce Richardson  * This file defines a generic API for atomic operations.
1399a2dd95SBruce Richardson  */
1499a2dd95SBruce Richardson 
1599a2dd95SBruce Richardson #include <stdint.h>
161ec6a845STyler Retzlaff 
1799a2dd95SBruce Richardson #include <rte_common.h>
181ec6a845STyler Retzlaff #include <rte_stdatomic.h>
1999a2dd95SBruce Richardson 
20*719834a6SMattias Rönnblom #ifdef __cplusplus
21*719834a6SMattias Rönnblom extern "C" {
22*719834a6SMattias Rönnblom #endif
23*719834a6SMattias Rönnblom 
2499a2dd95SBruce Richardson #ifdef __DOXYGEN__
2599a2dd95SBruce Richardson 
2699a2dd95SBruce Richardson /** @name Memory Barrier
2799a2dd95SBruce Richardson  */
2899a2dd95SBruce Richardson ///@{
2999a2dd95SBruce Richardson /**
3099a2dd95SBruce Richardson  * General memory barrier.
3199a2dd95SBruce Richardson  *
3299a2dd95SBruce Richardson  * Guarantees that the LOAD and STORE operations generated before the
3399a2dd95SBruce Richardson  * barrier occur before the LOAD and STORE operations generated after.
3499a2dd95SBruce Richardson  */
3599a2dd95SBruce Richardson static inline void rte_mb(void);
3699a2dd95SBruce Richardson 
3799a2dd95SBruce Richardson /**
3899a2dd95SBruce Richardson  * Write memory barrier.
3999a2dd95SBruce Richardson  *
4099a2dd95SBruce Richardson  * Guarantees that the STORE operations generated before the barrier
4199a2dd95SBruce Richardson  * occur before the STORE operations generated after.
4299a2dd95SBruce Richardson  */
4399a2dd95SBruce Richardson static inline void rte_wmb(void);
4499a2dd95SBruce Richardson 
4599a2dd95SBruce Richardson /**
4699a2dd95SBruce Richardson  * Read memory barrier.
4799a2dd95SBruce Richardson  *
4899a2dd95SBruce Richardson  * Guarantees that the LOAD operations generated before the barrier
4999a2dd95SBruce Richardson  * occur before the LOAD operations generated after.
5099a2dd95SBruce Richardson  */
5199a2dd95SBruce Richardson static inline void rte_rmb(void);
5299a2dd95SBruce Richardson ///@}
5399a2dd95SBruce Richardson 
5499a2dd95SBruce Richardson /** @name SMP Memory Barrier
5599a2dd95SBruce Richardson  */
5699a2dd95SBruce Richardson ///@{
5799a2dd95SBruce Richardson /**
5899a2dd95SBruce Richardson  * General memory barrier between lcores
5999a2dd95SBruce Richardson  *
6099a2dd95SBruce Richardson  * Guarantees that the LOAD and STORE operations that precede the
6199a2dd95SBruce Richardson  * rte_smp_mb() call are globally visible across the lcores
6299a2dd95SBruce Richardson  * before the LOAD and STORE operations that follows it.
63e7511996SRuifeng Wang  *
64e7511996SRuifeng Wang  * @note
65e7511996SRuifeng Wang  *  This function is deprecated.
66e7511996SRuifeng Wang  *  It provides similar synchronization primitive as atomic fence,
67e7511996SRuifeng Wang  *  but has different syntax and memory ordering semantic. Hence
68e7511996SRuifeng Wang  *  deprecated for the simplicity of memory ordering semantics in use.
69e7511996SRuifeng Wang  *
701ec6a845STyler Retzlaff  *  rte_atomic_thread_fence(rte_memory_order_acq_rel) should be used instead.
7199a2dd95SBruce Richardson  */
7299a2dd95SBruce Richardson static inline void rte_smp_mb(void);
7399a2dd95SBruce Richardson 
7499a2dd95SBruce Richardson /**
7599a2dd95SBruce Richardson  * Write memory barrier between lcores
7699a2dd95SBruce Richardson  *
7799a2dd95SBruce Richardson  * Guarantees that the STORE operations that precede the
7899a2dd95SBruce Richardson  * rte_smp_wmb() call are globally visible across the lcores
7999a2dd95SBruce Richardson  * before the STORE operations that follows it.
80e7511996SRuifeng Wang  *
81e7511996SRuifeng Wang  * @note
82e7511996SRuifeng Wang  *  This function is deprecated.
83e7511996SRuifeng Wang  *  It provides similar synchronization primitive as atomic fence,
84e7511996SRuifeng Wang  *  but has different syntax and memory ordering semantic. Hence
85e7511996SRuifeng Wang  *  deprecated for the simplicity of memory ordering semantics in use.
86e7511996SRuifeng Wang  *
871ec6a845STyler Retzlaff  *  rte_atomic_thread_fence(rte_memory_order_release) should be used instead.
88e7511996SRuifeng Wang  *  The fence also guarantees LOAD operations that precede the call
89e7511996SRuifeng Wang  *  are globally visible across the lcores before the STORE operations
90e7511996SRuifeng Wang  *  that follows it.
9199a2dd95SBruce Richardson  */
9299a2dd95SBruce Richardson static inline void rte_smp_wmb(void);
9399a2dd95SBruce Richardson 
9499a2dd95SBruce Richardson /**
9599a2dd95SBruce Richardson  * Read memory barrier between lcores
9699a2dd95SBruce Richardson  *
9799a2dd95SBruce Richardson  * Guarantees that the LOAD operations that precede the
9899a2dd95SBruce Richardson  * rte_smp_rmb() call are globally visible across the lcores
9999a2dd95SBruce Richardson  * before the LOAD operations that follows it.
100e7511996SRuifeng Wang  *
101e7511996SRuifeng Wang  * @note
102e7511996SRuifeng Wang  *  This function is deprecated.
103e7511996SRuifeng Wang  *  It provides similar synchronization primitive as atomic fence,
104e7511996SRuifeng Wang  *  but has different syntax and memory ordering semantic. Hence
105e7511996SRuifeng Wang  *  deprecated for the simplicity of memory ordering semantics in use.
106e7511996SRuifeng Wang  *
1071ec6a845STyler Retzlaff  *  rte_atomic_thread_fence(rte_memory_order_acquire) should be used instead.
108e7511996SRuifeng Wang  *  The fence also guarantees LOAD operations that precede the call
109e7511996SRuifeng Wang  *  are globally visible across the lcores before the STORE operations
110e7511996SRuifeng Wang  *  that follows it.
11199a2dd95SBruce Richardson  */
11299a2dd95SBruce Richardson static inline void rte_smp_rmb(void);
11399a2dd95SBruce Richardson ///@}
11499a2dd95SBruce Richardson 
11599a2dd95SBruce Richardson /** @name I/O Memory Barrier
11699a2dd95SBruce Richardson  */
11799a2dd95SBruce Richardson ///@{
11899a2dd95SBruce Richardson /**
11999a2dd95SBruce Richardson  * General memory barrier for I/O device
12099a2dd95SBruce Richardson  *
12199a2dd95SBruce Richardson  * Guarantees that the LOAD and STORE operations that precede the
12299a2dd95SBruce Richardson  * rte_io_mb() call are visible to I/O device or CPU before the
12399a2dd95SBruce Richardson  * LOAD and STORE operations that follow it.
12499a2dd95SBruce Richardson  */
12599a2dd95SBruce Richardson static inline void rte_io_mb(void);
12699a2dd95SBruce Richardson 
12799a2dd95SBruce Richardson /**
12899a2dd95SBruce Richardson  * Write memory barrier for I/O device
12999a2dd95SBruce Richardson  *
13099a2dd95SBruce Richardson  * Guarantees that the STORE operations that precede the
13199a2dd95SBruce Richardson  * rte_io_wmb() call are visible to I/O device before the STORE
13299a2dd95SBruce Richardson  * operations that follow it.
13399a2dd95SBruce Richardson  */
13499a2dd95SBruce Richardson static inline void rte_io_wmb(void);
13599a2dd95SBruce Richardson 
13699a2dd95SBruce Richardson /**
13799a2dd95SBruce Richardson  * Read memory barrier for IO device
13899a2dd95SBruce Richardson  *
13999a2dd95SBruce Richardson  * Guarantees that the LOAD operations on I/O device that precede the
14099a2dd95SBruce Richardson  * rte_io_rmb() call are visible to CPU before the LOAD
14199a2dd95SBruce Richardson  * operations that follow it.
14299a2dd95SBruce Richardson  */
14399a2dd95SBruce Richardson static inline void rte_io_rmb(void);
14499a2dd95SBruce Richardson ///@}
14599a2dd95SBruce Richardson 
14699a2dd95SBruce Richardson #endif /* __DOXYGEN__ */
14799a2dd95SBruce Richardson 
14899a2dd95SBruce Richardson /**
14999a2dd95SBruce Richardson  * Compiler barrier.
15099a2dd95SBruce Richardson  *
15199a2dd95SBruce Richardson  * Guarantees that operation reordering does not occur at compile time
15299a2dd95SBruce Richardson  * for operations directly before and after the barrier.
15399a2dd95SBruce Richardson  */
1542dbaa926STyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
1552dbaa926STyler Retzlaff #define rte_compiler_barrier() _ReadWriteBarrier()
1562dbaa926STyler Retzlaff #else
15799a2dd95SBruce Richardson #define	rte_compiler_barrier() do {		\
15899a2dd95SBruce Richardson 	asm volatile ("" : : : "memory");	\
15999a2dd95SBruce Richardson } while(0)
1602dbaa926STyler Retzlaff #endif
16199a2dd95SBruce Richardson 
16299a2dd95SBruce Richardson /**
16399a2dd95SBruce Richardson  * Synchronization fence between threads based on the specified memory order.
16499a2dd95SBruce Richardson  */
1651ec6a845STyler Retzlaff static inline void rte_atomic_thread_fence(rte_memory_order memorder);
16699a2dd95SBruce Richardson 
16799a2dd95SBruce Richardson /*------------------------- 16 bit atomic operations -------------------------*/
16899a2dd95SBruce Richardson 
16927da6a12STyler Retzlaff #ifndef RTE_TOOLCHAIN_MSVC
17027da6a12STyler Retzlaff 
17199a2dd95SBruce Richardson /**
17299a2dd95SBruce Richardson  * Atomic compare and set.
17399a2dd95SBruce Richardson  *
17499a2dd95SBruce Richardson  * (atomic) equivalent to:
17599a2dd95SBruce Richardson  *   if (*dst == exp)
17699a2dd95SBruce Richardson  *     *dst = src (all 16-bit words)
17799a2dd95SBruce Richardson  *
17899a2dd95SBruce Richardson  * @param dst
17999a2dd95SBruce Richardson  *   The destination location into which the value will be written.
18099a2dd95SBruce Richardson  * @param exp
18199a2dd95SBruce Richardson  *   The expected value.
18299a2dd95SBruce Richardson  * @param src
18399a2dd95SBruce Richardson  *   The new value.
18499a2dd95SBruce Richardson  * @return
18599a2dd95SBruce Richardson  *   Non-zero on success; 0 on failure.
18699a2dd95SBruce Richardson  */
18799a2dd95SBruce Richardson static inline int
18899a2dd95SBruce Richardson rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src);
18999a2dd95SBruce Richardson 
19099a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
19199a2dd95SBruce Richardson static inline int
19299a2dd95SBruce Richardson rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src)
19399a2dd95SBruce Richardson {
19499a2dd95SBruce Richardson 	return __sync_bool_compare_and_swap(dst, exp, src);
19599a2dd95SBruce Richardson }
19699a2dd95SBruce Richardson #endif
19799a2dd95SBruce Richardson 
19899a2dd95SBruce Richardson /**
19999a2dd95SBruce Richardson  * Atomic exchange.
20099a2dd95SBruce Richardson  *
20199a2dd95SBruce Richardson  * (atomic) equivalent to:
20299a2dd95SBruce Richardson  *   ret = *dst
20399a2dd95SBruce Richardson  *   *dst = val;
20499a2dd95SBruce Richardson  *   return ret;
20599a2dd95SBruce Richardson  *
20699a2dd95SBruce Richardson  * @param dst
20799a2dd95SBruce Richardson  *   The destination location into which the value will be written.
20899a2dd95SBruce Richardson  * @param val
20999a2dd95SBruce Richardson  *   The new value.
21099a2dd95SBruce Richardson  * @return
21199a2dd95SBruce Richardson  *   The original value at that location
21299a2dd95SBruce Richardson  */
21399a2dd95SBruce Richardson static inline uint16_t
21499a2dd95SBruce Richardson rte_atomic16_exchange(volatile uint16_t *dst, uint16_t val);
21599a2dd95SBruce Richardson 
21699a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
21799a2dd95SBruce Richardson static inline uint16_t
21899a2dd95SBruce Richardson rte_atomic16_exchange(volatile uint16_t *dst, uint16_t val)
21999a2dd95SBruce Richardson {
2201ec6a845STyler Retzlaff 	return rte_atomic_exchange_explicit(dst, val, rte_memory_order_seq_cst);
22199a2dd95SBruce Richardson }
22299a2dd95SBruce Richardson #endif
22399a2dd95SBruce Richardson 
22499a2dd95SBruce Richardson /**
22599a2dd95SBruce Richardson  * The atomic counter structure.
22699a2dd95SBruce Richardson  */
22799a2dd95SBruce Richardson typedef struct {
22899a2dd95SBruce Richardson 	volatile int16_t cnt; /**< An internal counter value. */
22999a2dd95SBruce Richardson } rte_atomic16_t;
23099a2dd95SBruce Richardson 
23199a2dd95SBruce Richardson /**
23299a2dd95SBruce Richardson  * Static initializer for an atomic counter.
23399a2dd95SBruce Richardson  */
23499a2dd95SBruce Richardson #define RTE_ATOMIC16_INIT(val) { (val) }
23599a2dd95SBruce Richardson 
23699a2dd95SBruce Richardson /**
23799a2dd95SBruce Richardson  * Initialize an atomic counter.
23899a2dd95SBruce Richardson  *
23999a2dd95SBruce Richardson  * @param v
24099a2dd95SBruce Richardson  *   A pointer to the atomic counter.
24199a2dd95SBruce Richardson  */
24299a2dd95SBruce Richardson static inline void
24399a2dd95SBruce Richardson rte_atomic16_init(rte_atomic16_t *v)
24499a2dd95SBruce Richardson {
24599a2dd95SBruce Richardson 	v->cnt = 0;
24699a2dd95SBruce Richardson }
24799a2dd95SBruce Richardson 
24899a2dd95SBruce Richardson /**
24999a2dd95SBruce Richardson  * Atomically read a 16-bit value from a counter.
25099a2dd95SBruce Richardson  *
25199a2dd95SBruce Richardson  * @param v
25299a2dd95SBruce Richardson  *   A pointer to the atomic counter.
25399a2dd95SBruce Richardson  * @return
25499a2dd95SBruce Richardson  *   The value of the counter.
25599a2dd95SBruce Richardson  */
25699a2dd95SBruce Richardson static inline int16_t
25799a2dd95SBruce Richardson rte_atomic16_read(const rte_atomic16_t *v)
25899a2dd95SBruce Richardson {
25999a2dd95SBruce Richardson 	return v->cnt;
26099a2dd95SBruce Richardson }
26199a2dd95SBruce Richardson 
26299a2dd95SBruce Richardson /**
26399a2dd95SBruce Richardson  * Atomically set a counter to a 16-bit value.
26499a2dd95SBruce Richardson  *
26599a2dd95SBruce Richardson  * @param v
26699a2dd95SBruce Richardson  *   A pointer to the atomic counter.
26799a2dd95SBruce Richardson  * @param new_value
26899a2dd95SBruce Richardson  *   The new value for the counter.
26999a2dd95SBruce Richardson  */
27099a2dd95SBruce Richardson static inline void
27199a2dd95SBruce Richardson rte_atomic16_set(rte_atomic16_t *v, int16_t new_value)
27299a2dd95SBruce Richardson {
27399a2dd95SBruce Richardson 	v->cnt = new_value;
27499a2dd95SBruce Richardson }
27599a2dd95SBruce Richardson 
27699a2dd95SBruce Richardson /**
27799a2dd95SBruce Richardson  * Atomically add a 16-bit value to an atomic counter.
27899a2dd95SBruce Richardson  *
27999a2dd95SBruce Richardson  * @param v
28099a2dd95SBruce Richardson  *   A pointer to the atomic counter.
28199a2dd95SBruce Richardson  * @param inc
28299a2dd95SBruce Richardson  *   The value to be added to the counter.
28399a2dd95SBruce Richardson  */
28499a2dd95SBruce Richardson static inline void
28599a2dd95SBruce Richardson rte_atomic16_add(rte_atomic16_t *v, int16_t inc)
28699a2dd95SBruce Richardson {
2879290f8beSTyler Retzlaff 	rte_atomic_fetch_add_explicit((volatile __rte_atomic int16_t *)&v->cnt, inc,
2889290f8beSTyler Retzlaff 		rte_memory_order_seq_cst);
28999a2dd95SBruce Richardson }
29099a2dd95SBruce Richardson 
29199a2dd95SBruce Richardson /**
29299a2dd95SBruce Richardson  * Atomically subtract a 16-bit value from an atomic counter.
29399a2dd95SBruce Richardson  *
29499a2dd95SBruce Richardson  * @param v
29599a2dd95SBruce Richardson  *   A pointer to the atomic counter.
29699a2dd95SBruce Richardson  * @param dec
29799a2dd95SBruce Richardson  *   The value to be subtracted from the counter.
29899a2dd95SBruce Richardson  */
29999a2dd95SBruce Richardson static inline void
30099a2dd95SBruce Richardson rte_atomic16_sub(rte_atomic16_t *v, int16_t dec)
30199a2dd95SBruce Richardson {
3029290f8beSTyler Retzlaff 	rte_atomic_fetch_sub_explicit((volatile __rte_atomic int16_t *)&v->cnt, dec,
3039290f8beSTyler Retzlaff 		rte_memory_order_seq_cst);
30499a2dd95SBruce Richardson }
30599a2dd95SBruce Richardson 
30699a2dd95SBruce Richardson /**
30799a2dd95SBruce Richardson  * Atomically increment a counter by one.
30899a2dd95SBruce Richardson  *
30999a2dd95SBruce Richardson  * @param v
31099a2dd95SBruce Richardson  *   A pointer to the atomic counter.
31199a2dd95SBruce Richardson  */
31299a2dd95SBruce Richardson static inline void
31399a2dd95SBruce Richardson rte_atomic16_inc(rte_atomic16_t *v);
31499a2dd95SBruce Richardson 
31599a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
31699a2dd95SBruce Richardson static inline void
31799a2dd95SBruce Richardson rte_atomic16_inc(rte_atomic16_t *v)
31899a2dd95SBruce Richardson {
31999a2dd95SBruce Richardson 	rte_atomic16_add(v, 1);
32099a2dd95SBruce Richardson }
32199a2dd95SBruce Richardson #endif
32299a2dd95SBruce Richardson 
32399a2dd95SBruce Richardson /**
32499a2dd95SBruce Richardson  * Atomically decrement a counter by one.
32599a2dd95SBruce Richardson  *
32699a2dd95SBruce Richardson  * @param v
32799a2dd95SBruce Richardson  *   A pointer to the atomic counter.
32899a2dd95SBruce Richardson  */
32999a2dd95SBruce Richardson static inline void
33099a2dd95SBruce Richardson rte_atomic16_dec(rte_atomic16_t *v);
33199a2dd95SBruce Richardson 
33299a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
33399a2dd95SBruce Richardson static inline void
33499a2dd95SBruce Richardson rte_atomic16_dec(rte_atomic16_t *v)
33599a2dd95SBruce Richardson {
33699a2dd95SBruce Richardson 	rte_atomic16_sub(v, 1);
33799a2dd95SBruce Richardson }
33899a2dd95SBruce Richardson #endif
33999a2dd95SBruce Richardson 
34099a2dd95SBruce Richardson /**
34199a2dd95SBruce Richardson  * Atomically add a 16-bit value to a counter and return the result.
34299a2dd95SBruce Richardson  *
34399a2dd95SBruce Richardson  * Atomically adds the 16-bits value (inc) to the atomic counter (v) and
34499a2dd95SBruce Richardson  * returns the value of v after addition.
34599a2dd95SBruce Richardson  *
34699a2dd95SBruce Richardson  * @param v
34799a2dd95SBruce Richardson  *   A pointer to the atomic counter.
34899a2dd95SBruce Richardson  * @param inc
34999a2dd95SBruce Richardson  *   The value to be added to the counter.
35099a2dd95SBruce Richardson  * @return
35199a2dd95SBruce Richardson  *   The value of v after the addition.
35299a2dd95SBruce Richardson  */
35399a2dd95SBruce Richardson static inline int16_t
35499a2dd95SBruce Richardson rte_atomic16_add_return(rte_atomic16_t *v, int16_t inc)
35599a2dd95SBruce Richardson {
3569290f8beSTyler Retzlaff 	return rte_atomic_fetch_add_explicit((volatile __rte_atomic int16_t *)&v->cnt, inc,
3579290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) + inc;
35899a2dd95SBruce Richardson }
35999a2dd95SBruce Richardson 
36099a2dd95SBruce Richardson /**
36199a2dd95SBruce Richardson  * Atomically subtract a 16-bit value from a counter and return
36299a2dd95SBruce Richardson  * the result.
36399a2dd95SBruce Richardson  *
36499a2dd95SBruce Richardson  * Atomically subtracts the 16-bit value (inc) from the atomic counter
36599a2dd95SBruce Richardson  * (v) and returns the value of v after the subtraction.
36699a2dd95SBruce Richardson  *
36799a2dd95SBruce Richardson  * @param v
36899a2dd95SBruce Richardson  *   A pointer to the atomic counter.
36999a2dd95SBruce Richardson  * @param dec
37099a2dd95SBruce Richardson  *   The value to be subtracted from the counter.
37199a2dd95SBruce Richardson  * @return
37299a2dd95SBruce Richardson  *   The value of v after the subtraction.
37399a2dd95SBruce Richardson  */
37499a2dd95SBruce Richardson static inline int16_t
37599a2dd95SBruce Richardson rte_atomic16_sub_return(rte_atomic16_t *v, int16_t dec)
37699a2dd95SBruce Richardson {
3779290f8beSTyler Retzlaff 	return rte_atomic_fetch_sub_explicit((volatile __rte_atomic int16_t *)&v->cnt, dec,
3789290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) - dec;
37999a2dd95SBruce Richardson }
38099a2dd95SBruce Richardson 
38199a2dd95SBruce Richardson /**
38299a2dd95SBruce Richardson  * Atomically increment a 16-bit counter by one and test.
38399a2dd95SBruce Richardson  *
38499a2dd95SBruce Richardson  * Atomically increments the atomic counter (v) by one and returns true if
38599a2dd95SBruce Richardson  * the result is 0, or false in all other cases.
38699a2dd95SBruce Richardson  *
38799a2dd95SBruce Richardson  * @param v
38899a2dd95SBruce Richardson  *   A pointer to the atomic counter.
38999a2dd95SBruce Richardson  * @return
39099a2dd95SBruce Richardson  *   True if the result after the increment operation is 0; false otherwise.
39199a2dd95SBruce Richardson  */
39299a2dd95SBruce Richardson static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v);
39399a2dd95SBruce Richardson 
39499a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
39599a2dd95SBruce Richardson static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v)
39699a2dd95SBruce Richardson {
3979290f8beSTyler Retzlaff 	return rte_atomic_fetch_add_explicit((volatile __rte_atomic int16_t *)&v->cnt, 1,
3989290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) + 1 == 0;
39999a2dd95SBruce Richardson }
40099a2dd95SBruce Richardson #endif
40199a2dd95SBruce Richardson 
40299a2dd95SBruce Richardson /**
40399a2dd95SBruce Richardson  * Atomically decrement a 16-bit counter by one and test.
40499a2dd95SBruce Richardson  *
40599a2dd95SBruce Richardson  * Atomically decrements the atomic counter (v) by one and returns true if
40699a2dd95SBruce Richardson  * the result is 0, or false in all other cases.
40799a2dd95SBruce Richardson  *
40899a2dd95SBruce Richardson  * @param v
40999a2dd95SBruce Richardson  *   A pointer to the atomic counter.
41099a2dd95SBruce Richardson  * @return
41199a2dd95SBruce Richardson  *   True if the result after the decrement operation is 0; false otherwise.
41299a2dd95SBruce Richardson  */
41399a2dd95SBruce Richardson static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v);
41499a2dd95SBruce Richardson 
41599a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
41699a2dd95SBruce Richardson static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v)
41799a2dd95SBruce Richardson {
4189290f8beSTyler Retzlaff 	return rte_atomic_fetch_sub_explicit((volatile __rte_atomic int16_t *)&v->cnt, 1,
4199290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) - 1 == 0;
42099a2dd95SBruce Richardson }
42199a2dd95SBruce Richardson #endif
42299a2dd95SBruce Richardson 
42399a2dd95SBruce Richardson /**
42499a2dd95SBruce Richardson  * Atomically test and set a 16-bit atomic counter.
42599a2dd95SBruce Richardson  *
42699a2dd95SBruce Richardson  * If the counter value is already set, return 0 (failed). Otherwise, set
42799a2dd95SBruce Richardson  * the counter value to 1 and return 1 (success).
42899a2dd95SBruce Richardson  *
42999a2dd95SBruce Richardson  * @param v
43099a2dd95SBruce Richardson  *   A pointer to the atomic counter.
43199a2dd95SBruce Richardson  * @return
43299a2dd95SBruce Richardson  *   0 if failed; else 1, success.
43399a2dd95SBruce Richardson  */
43499a2dd95SBruce Richardson static inline int rte_atomic16_test_and_set(rte_atomic16_t *v);
43599a2dd95SBruce Richardson 
43699a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
43799a2dd95SBruce Richardson static inline int rte_atomic16_test_and_set(rte_atomic16_t *v)
43899a2dd95SBruce Richardson {
43999a2dd95SBruce Richardson 	return rte_atomic16_cmpset((volatile uint16_t *)&v->cnt, 0, 1);
44099a2dd95SBruce Richardson }
44199a2dd95SBruce Richardson #endif
44299a2dd95SBruce Richardson 
44399a2dd95SBruce Richardson /**
44499a2dd95SBruce Richardson  * Atomically set a 16-bit counter to 0.
44599a2dd95SBruce Richardson  *
44699a2dd95SBruce Richardson  * @param v
44799a2dd95SBruce Richardson  *   A pointer to the atomic counter.
44899a2dd95SBruce Richardson  */
44999a2dd95SBruce Richardson static inline void rte_atomic16_clear(rte_atomic16_t *v)
45099a2dd95SBruce Richardson {
45199a2dd95SBruce Richardson 	v->cnt = 0;
45299a2dd95SBruce Richardson }
45399a2dd95SBruce Richardson 
45499a2dd95SBruce Richardson /*------------------------- 32 bit atomic operations -------------------------*/
45599a2dd95SBruce Richardson 
45699a2dd95SBruce Richardson /**
45799a2dd95SBruce Richardson  * Atomic compare and set.
45899a2dd95SBruce Richardson  *
45999a2dd95SBruce Richardson  * (atomic) equivalent to:
46099a2dd95SBruce Richardson  *   if (*dst == exp)
46199a2dd95SBruce Richardson  *     *dst = src (all 32-bit words)
46299a2dd95SBruce Richardson  *
46399a2dd95SBruce Richardson  * @param dst
46499a2dd95SBruce Richardson  *   The destination location into which the value will be written.
46599a2dd95SBruce Richardson  * @param exp
46699a2dd95SBruce Richardson  *   The expected value.
46799a2dd95SBruce Richardson  * @param src
46899a2dd95SBruce Richardson  *   The new value.
46999a2dd95SBruce Richardson  * @return
47099a2dd95SBruce Richardson  *   Non-zero on success; 0 on failure.
47199a2dd95SBruce Richardson  */
47299a2dd95SBruce Richardson static inline int
47399a2dd95SBruce Richardson rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src);
47499a2dd95SBruce Richardson 
47599a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
47699a2dd95SBruce Richardson static inline int
47799a2dd95SBruce Richardson rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
47899a2dd95SBruce Richardson {
47999a2dd95SBruce Richardson 	return __sync_bool_compare_and_swap(dst, exp, src);
48099a2dd95SBruce Richardson }
48199a2dd95SBruce Richardson #endif
48299a2dd95SBruce Richardson 
48399a2dd95SBruce Richardson /**
48499a2dd95SBruce Richardson  * Atomic exchange.
48599a2dd95SBruce Richardson  *
48699a2dd95SBruce Richardson  * (atomic) equivalent to:
48799a2dd95SBruce Richardson  *   ret = *dst
48899a2dd95SBruce Richardson  *   *dst = val;
48999a2dd95SBruce Richardson  *   return ret;
49099a2dd95SBruce Richardson  *
49199a2dd95SBruce Richardson  * @param dst
49299a2dd95SBruce Richardson  *   The destination location into which the value will be written.
49399a2dd95SBruce Richardson  * @param val
49499a2dd95SBruce Richardson  *   The new value.
49599a2dd95SBruce Richardson  * @return
49699a2dd95SBruce Richardson  *   The original value at that location
49799a2dd95SBruce Richardson  */
49899a2dd95SBruce Richardson static inline uint32_t
49999a2dd95SBruce Richardson rte_atomic32_exchange(volatile uint32_t *dst, uint32_t val);
50099a2dd95SBruce Richardson 
50199a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
50299a2dd95SBruce Richardson static inline uint32_t
50399a2dd95SBruce Richardson rte_atomic32_exchange(volatile uint32_t *dst, uint32_t val)
50499a2dd95SBruce Richardson {
5051ec6a845STyler Retzlaff 	return rte_atomic_exchange_explicit(dst, val, rte_memory_order_seq_cst);
50699a2dd95SBruce Richardson }
50799a2dd95SBruce Richardson #endif
50899a2dd95SBruce Richardson 
50999a2dd95SBruce Richardson /**
51099a2dd95SBruce Richardson  * The atomic counter structure.
51199a2dd95SBruce Richardson  */
51299a2dd95SBruce Richardson typedef struct {
51399a2dd95SBruce Richardson 	volatile int32_t cnt; /**< An internal counter value. */
51499a2dd95SBruce Richardson } rte_atomic32_t;
51599a2dd95SBruce Richardson 
51699a2dd95SBruce Richardson /**
51799a2dd95SBruce Richardson  * Static initializer for an atomic counter.
51899a2dd95SBruce Richardson  */
51999a2dd95SBruce Richardson #define RTE_ATOMIC32_INIT(val) { (val) }
52099a2dd95SBruce Richardson 
52199a2dd95SBruce Richardson /**
52299a2dd95SBruce Richardson  * Initialize an atomic counter.
52399a2dd95SBruce Richardson  *
52499a2dd95SBruce Richardson  * @param v
52599a2dd95SBruce Richardson  *   A pointer to the atomic counter.
52699a2dd95SBruce Richardson  */
52799a2dd95SBruce Richardson static inline void
52899a2dd95SBruce Richardson rte_atomic32_init(rte_atomic32_t *v)
52999a2dd95SBruce Richardson {
53099a2dd95SBruce Richardson 	v->cnt = 0;
53199a2dd95SBruce Richardson }
53299a2dd95SBruce Richardson 
53399a2dd95SBruce Richardson /**
53499a2dd95SBruce Richardson  * Atomically read a 32-bit value from a counter.
53599a2dd95SBruce Richardson  *
53699a2dd95SBruce Richardson  * @param v
53799a2dd95SBruce Richardson  *   A pointer to the atomic counter.
53899a2dd95SBruce Richardson  * @return
53999a2dd95SBruce Richardson  *   The value of the counter.
54099a2dd95SBruce Richardson  */
54199a2dd95SBruce Richardson static inline int32_t
54299a2dd95SBruce Richardson rte_atomic32_read(const rte_atomic32_t *v)
54399a2dd95SBruce Richardson {
54499a2dd95SBruce Richardson 	return v->cnt;
54599a2dd95SBruce Richardson }
54699a2dd95SBruce Richardson 
54799a2dd95SBruce Richardson /**
54899a2dd95SBruce Richardson  * Atomically set a counter to a 32-bit value.
54999a2dd95SBruce Richardson  *
55099a2dd95SBruce Richardson  * @param v
55199a2dd95SBruce Richardson  *   A pointer to the atomic counter.
55299a2dd95SBruce Richardson  * @param new_value
55399a2dd95SBruce Richardson  *   The new value for the counter.
55499a2dd95SBruce Richardson  */
55599a2dd95SBruce Richardson static inline void
55699a2dd95SBruce Richardson rte_atomic32_set(rte_atomic32_t *v, int32_t new_value)
55799a2dd95SBruce Richardson {
55899a2dd95SBruce Richardson 	v->cnt = new_value;
55999a2dd95SBruce Richardson }
56099a2dd95SBruce Richardson 
56199a2dd95SBruce Richardson /**
56299a2dd95SBruce Richardson  * Atomically add a 32-bit value to an atomic counter.
56399a2dd95SBruce Richardson  *
56499a2dd95SBruce Richardson  * @param v
56599a2dd95SBruce Richardson  *   A pointer to the atomic counter.
56699a2dd95SBruce Richardson  * @param inc
56799a2dd95SBruce Richardson  *   The value to be added to the counter.
56899a2dd95SBruce Richardson  */
56999a2dd95SBruce Richardson static inline void
57099a2dd95SBruce Richardson rte_atomic32_add(rte_atomic32_t *v, int32_t inc)
57199a2dd95SBruce Richardson {
5729290f8beSTyler Retzlaff 	rte_atomic_fetch_add_explicit((volatile __rte_atomic int32_t *)&v->cnt, inc,
5739290f8beSTyler Retzlaff 		rte_memory_order_seq_cst);
57499a2dd95SBruce Richardson }
57599a2dd95SBruce Richardson 
57699a2dd95SBruce Richardson /**
57799a2dd95SBruce Richardson  * Atomically subtract a 32-bit value from an atomic counter.
57899a2dd95SBruce Richardson  *
57999a2dd95SBruce Richardson  * @param v
58099a2dd95SBruce Richardson  *   A pointer to the atomic counter.
58199a2dd95SBruce Richardson  * @param dec
58299a2dd95SBruce Richardson  *   The value to be subtracted from the counter.
58399a2dd95SBruce Richardson  */
58499a2dd95SBruce Richardson static inline void
58599a2dd95SBruce Richardson rte_atomic32_sub(rte_atomic32_t *v, int32_t dec)
58699a2dd95SBruce Richardson {
5879290f8beSTyler Retzlaff 	rte_atomic_fetch_sub_explicit((volatile __rte_atomic int32_t *)&v->cnt, dec,
5889290f8beSTyler Retzlaff 		rte_memory_order_seq_cst);
58999a2dd95SBruce Richardson }
59099a2dd95SBruce Richardson 
59199a2dd95SBruce Richardson /**
59299a2dd95SBruce Richardson  * Atomically increment a counter by one.
59399a2dd95SBruce Richardson  *
59499a2dd95SBruce Richardson  * @param v
59599a2dd95SBruce Richardson  *   A pointer to the atomic counter.
59699a2dd95SBruce Richardson  */
59799a2dd95SBruce Richardson static inline void
59899a2dd95SBruce Richardson rte_atomic32_inc(rte_atomic32_t *v);
59999a2dd95SBruce Richardson 
60099a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
60199a2dd95SBruce Richardson static inline void
60299a2dd95SBruce Richardson rte_atomic32_inc(rte_atomic32_t *v)
60399a2dd95SBruce Richardson {
60499a2dd95SBruce Richardson 	rte_atomic32_add(v, 1);
60599a2dd95SBruce Richardson }
60699a2dd95SBruce Richardson #endif
60799a2dd95SBruce Richardson 
60899a2dd95SBruce Richardson /**
60999a2dd95SBruce Richardson  * Atomically decrement a counter by one.
61099a2dd95SBruce Richardson  *
61199a2dd95SBruce Richardson  * @param v
61299a2dd95SBruce Richardson  *   A pointer to the atomic counter.
61399a2dd95SBruce Richardson  */
61499a2dd95SBruce Richardson static inline void
61599a2dd95SBruce Richardson rte_atomic32_dec(rte_atomic32_t *v);
61699a2dd95SBruce Richardson 
61799a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
61899a2dd95SBruce Richardson static inline void
61999a2dd95SBruce Richardson rte_atomic32_dec(rte_atomic32_t *v)
62099a2dd95SBruce Richardson {
62199a2dd95SBruce Richardson 	rte_atomic32_sub(v,1);
62299a2dd95SBruce Richardson }
62399a2dd95SBruce Richardson #endif
62499a2dd95SBruce Richardson 
62599a2dd95SBruce Richardson /**
62699a2dd95SBruce Richardson  * Atomically add a 32-bit value to a counter and return the result.
62799a2dd95SBruce Richardson  *
62899a2dd95SBruce Richardson  * Atomically adds the 32-bits value (inc) to the atomic counter (v) and
62999a2dd95SBruce Richardson  * returns the value of v after addition.
63099a2dd95SBruce Richardson  *
63199a2dd95SBruce Richardson  * @param v
63299a2dd95SBruce Richardson  *   A pointer to the atomic counter.
63399a2dd95SBruce Richardson  * @param inc
63499a2dd95SBruce Richardson  *   The value to be added to the counter.
63599a2dd95SBruce Richardson  * @return
63699a2dd95SBruce Richardson  *   The value of v after the addition.
63799a2dd95SBruce Richardson  */
63899a2dd95SBruce Richardson static inline int32_t
63999a2dd95SBruce Richardson rte_atomic32_add_return(rte_atomic32_t *v, int32_t inc)
64099a2dd95SBruce Richardson {
6419290f8beSTyler Retzlaff 	return rte_atomic_fetch_add_explicit((volatile __rte_atomic int32_t *)&v->cnt, inc,
6429290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) + inc;
64399a2dd95SBruce Richardson }
64499a2dd95SBruce Richardson 
64599a2dd95SBruce Richardson /**
64699a2dd95SBruce Richardson  * Atomically subtract a 32-bit value from a counter and return
64799a2dd95SBruce Richardson  * the result.
64899a2dd95SBruce Richardson  *
64999a2dd95SBruce Richardson  * Atomically subtracts the 32-bit value (inc) from the atomic counter
65099a2dd95SBruce Richardson  * (v) and returns the value of v after the subtraction.
65199a2dd95SBruce Richardson  *
65299a2dd95SBruce Richardson  * @param v
65399a2dd95SBruce Richardson  *   A pointer to the atomic counter.
65499a2dd95SBruce Richardson  * @param dec
65599a2dd95SBruce Richardson  *   The value to be subtracted from the counter.
65699a2dd95SBruce Richardson  * @return
65799a2dd95SBruce Richardson  *   The value of v after the subtraction.
65899a2dd95SBruce Richardson  */
65999a2dd95SBruce Richardson static inline int32_t
66099a2dd95SBruce Richardson rte_atomic32_sub_return(rte_atomic32_t *v, int32_t dec)
66199a2dd95SBruce Richardson {
6629290f8beSTyler Retzlaff 	return rte_atomic_fetch_sub_explicit((volatile __rte_atomic int32_t *)&v->cnt, dec,
6639290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) - dec;
66499a2dd95SBruce Richardson }
66599a2dd95SBruce Richardson 
66699a2dd95SBruce Richardson /**
66799a2dd95SBruce Richardson  * Atomically increment a 32-bit counter by one and test.
66899a2dd95SBruce Richardson  *
66999a2dd95SBruce Richardson  * Atomically increments the atomic counter (v) by one and returns true if
67099a2dd95SBruce Richardson  * the result is 0, or false in all other cases.
67199a2dd95SBruce Richardson  *
67299a2dd95SBruce Richardson  * @param v
67399a2dd95SBruce Richardson  *   A pointer to the atomic counter.
67499a2dd95SBruce Richardson  * @return
67599a2dd95SBruce Richardson  *   True if the result after the increment operation is 0; false otherwise.
67699a2dd95SBruce Richardson  */
67799a2dd95SBruce Richardson static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v);
67899a2dd95SBruce Richardson 
67999a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
68099a2dd95SBruce Richardson static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v)
68199a2dd95SBruce Richardson {
6829290f8beSTyler Retzlaff 	return rte_atomic_fetch_add_explicit((volatile __rte_atomic int32_t *)&v->cnt, 1,
6839290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) + 1 == 0;
68499a2dd95SBruce Richardson }
68599a2dd95SBruce Richardson #endif
68699a2dd95SBruce Richardson 
68799a2dd95SBruce Richardson /**
68899a2dd95SBruce Richardson  * Atomically decrement a 32-bit counter by one and test.
68999a2dd95SBruce Richardson  *
69099a2dd95SBruce Richardson  * Atomically decrements the atomic counter (v) by one and returns true if
69199a2dd95SBruce Richardson  * the result is 0, or false in all other cases.
69299a2dd95SBruce Richardson  *
69399a2dd95SBruce Richardson  * @param v
69499a2dd95SBruce Richardson  *   A pointer to the atomic counter.
69599a2dd95SBruce Richardson  * @return
69699a2dd95SBruce Richardson  *   True if the result after the decrement operation is 0; false otherwise.
69799a2dd95SBruce Richardson  */
69899a2dd95SBruce Richardson static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v);
69999a2dd95SBruce Richardson 
70099a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
70199a2dd95SBruce Richardson static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)
70299a2dd95SBruce Richardson {
7039290f8beSTyler Retzlaff 	return rte_atomic_fetch_sub_explicit((volatile __rte_atomic int32_t *)&v->cnt, 1,
7049290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) - 1 == 0;
70599a2dd95SBruce Richardson }
70699a2dd95SBruce Richardson #endif
70799a2dd95SBruce Richardson 
70899a2dd95SBruce Richardson /**
70999a2dd95SBruce Richardson  * Atomically test and set a 32-bit atomic counter.
71099a2dd95SBruce Richardson  *
71199a2dd95SBruce Richardson  * If the counter value is already set, return 0 (failed). Otherwise, set
71299a2dd95SBruce Richardson  * the counter value to 1 and return 1 (success).
71399a2dd95SBruce Richardson  *
71499a2dd95SBruce Richardson  * @param v
71599a2dd95SBruce Richardson  *   A pointer to the atomic counter.
71699a2dd95SBruce Richardson  * @return
71799a2dd95SBruce Richardson  *   0 if failed; else 1, success.
71899a2dd95SBruce Richardson  */
71999a2dd95SBruce Richardson static inline int rte_atomic32_test_and_set(rte_atomic32_t *v);
72099a2dd95SBruce Richardson 
72199a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
72299a2dd95SBruce Richardson static inline int rte_atomic32_test_and_set(rte_atomic32_t *v)
72399a2dd95SBruce Richardson {
72499a2dd95SBruce Richardson 	return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1);
72599a2dd95SBruce Richardson }
72699a2dd95SBruce Richardson #endif
72799a2dd95SBruce Richardson 
72899a2dd95SBruce Richardson /**
72999a2dd95SBruce Richardson  * Atomically set a 32-bit counter to 0.
73099a2dd95SBruce Richardson  *
73199a2dd95SBruce Richardson  * @param v
73299a2dd95SBruce Richardson  *   A pointer to the atomic counter.
73399a2dd95SBruce Richardson  */
73499a2dd95SBruce Richardson static inline void rte_atomic32_clear(rte_atomic32_t *v)
73599a2dd95SBruce Richardson {
73699a2dd95SBruce Richardson 	v->cnt = 0;
73799a2dd95SBruce Richardson }
73899a2dd95SBruce Richardson 
73999a2dd95SBruce Richardson /*------------------------- 64 bit atomic operations -------------------------*/
74099a2dd95SBruce Richardson 
74199a2dd95SBruce Richardson /**
74299a2dd95SBruce Richardson  * An atomic compare and set function used by the mutex functions.
74399a2dd95SBruce Richardson  * (atomic) equivalent to:
74499a2dd95SBruce Richardson  *   if (*dst == exp)
74599a2dd95SBruce Richardson  *     *dst = src (all 64-bit words)
74699a2dd95SBruce Richardson  *
74799a2dd95SBruce Richardson  * @param dst
74899a2dd95SBruce Richardson  *   The destination into which the value will be written.
74999a2dd95SBruce Richardson  * @param exp
75099a2dd95SBruce Richardson  *   The expected value.
75199a2dd95SBruce Richardson  * @param src
75299a2dd95SBruce Richardson  *   The new value.
75399a2dd95SBruce Richardson  * @return
75499a2dd95SBruce Richardson  *   Non-zero on success; 0 on failure.
75599a2dd95SBruce Richardson  */
75699a2dd95SBruce Richardson static inline int
75799a2dd95SBruce Richardson rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src);
75899a2dd95SBruce Richardson 
75999a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
76099a2dd95SBruce Richardson static inline int
76199a2dd95SBruce Richardson rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src)
76299a2dd95SBruce Richardson {
76399a2dd95SBruce Richardson 	return __sync_bool_compare_and_swap(dst, exp, src);
76499a2dd95SBruce Richardson }
76599a2dd95SBruce Richardson #endif
76699a2dd95SBruce Richardson 
76799a2dd95SBruce Richardson /**
76899a2dd95SBruce Richardson  * Atomic exchange.
76999a2dd95SBruce Richardson  *
77099a2dd95SBruce Richardson  * (atomic) equivalent to:
77199a2dd95SBruce Richardson  *   ret = *dst
77299a2dd95SBruce Richardson  *   *dst = val;
77399a2dd95SBruce Richardson  *   return ret;
77499a2dd95SBruce Richardson  *
77599a2dd95SBruce Richardson  * @param dst
77699a2dd95SBruce Richardson  *   The destination location into which the value will be written.
77799a2dd95SBruce Richardson  * @param val
77899a2dd95SBruce Richardson  *   The new value.
77999a2dd95SBruce Richardson  * @return
78099a2dd95SBruce Richardson  *   The original value at that location
78199a2dd95SBruce Richardson  */
78299a2dd95SBruce Richardson static inline uint64_t
78399a2dd95SBruce Richardson rte_atomic64_exchange(volatile uint64_t *dst, uint64_t val);
78499a2dd95SBruce Richardson 
78599a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
78699a2dd95SBruce Richardson static inline uint64_t
78799a2dd95SBruce Richardson rte_atomic64_exchange(volatile uint64_t *dst, uint64_t val)
78899a2dd95SBruce Richardson {
7891ec6a845STyler Retzlaff 	return rte_atomic_exchange_explicit(dst, val, rte_memory_order_seq_cst);
79099a2dd95SBruce Richardson }
79199a2dd95SBruce Richardson #endif
79299a2dd95SBruce Richardson 
79399a2dd95SBruce Richardson /**
79499a2dd95SBruce Richardson  * The atomic counter structure.
79599a2dd95SBruce Richardson  */
79699a2dd95SBruce Richardson typedef struct {
79799a2dd95SBruce Richardson 	volatile int64_t cnt;  /**< Internal counter value. */
79899a2dd95SBruce Richardson } rte_atomic64_t;
79999a2dd95SBruce Richardson 
80099a2dd95SBruce Richardson /**
80199a2dd95SBruce Richardson  * Static initializer for an atomic counter.
80299a2dd95SBruce Richardson  */
80399a2dd95SBruce Richardson #define RTE_ATOMIC64_INIT(val) { (val) }
80499a2dd95SBruce Richardson 
80599a2dd95SBruce Richardson /**
80699a2dd95SBruce Richardson  * Initialize the atomic counter.
80799a2dd95SBruce Richardson  *
80899a2dd95SBruce Richardson  * @param v
80999a2dd95SBruce Richardson  *   A pointer to the atomic counter.
81099a2dd95SBruce Richardson  */
81199a2dd95SBruce Richardson static inline void
81299a2dd95SBruce Richardson rte_atomic64_init(rte_atomic64_t *v);
81399a2dd95SBruce Richardson 
81499a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
81599a2dd95SBruce Richardson static inline void
81699a2dd95SBruce Richardson rte_atomic64_init(rte_atomic64_t *v)
81799a2dd95SBruce Richardson {
81899a2dd95SBruce Richardson #ifdef __LP64__
81999a2dd95SBruce Richardson 	v->cnt = 0;
82099a2dd95SBruce Richardson #else
82199a2dd95SBruce Richardson 	int success = 0;
82299a2dd95SBruce Richardson 	uint64_t tmp;
82399a2dd95SBruce Richardson 
82499a2dd95SBruce Richardson 	while (success == 0) {
82599a2dd95SBruce Richardson 		tmp = v->cnt;
82699a2dd95SBruce Richardson 		success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt,
82799a2dd95SBruce Richardson 		                              tmp, 0);
82899a2dd95SBruce Richardson 	}
82999a2dd95SBruce Richardson #endif
83099a2dd95SBruce Richardson }
83199a2dd95SBruce Richardson #endif
83299a2dd95SBruce Richardson 
83399a2dd95SBruce Richardson /**
83499a2dd95SBruce Richardson  * Atomically read a 64-bit counter.
83599a2dd95SBruce Richardson  *
83699a2dd95SBruce Richardson  * @param v
83799a2dd95SBruce Richardson  *   A pointer to the atomic counter.
83899a2dd95SBruce Richardson  * @return
83999a2dd95SBruce Richardson  *   The value of the counter.
84099a2dd95SBruce Richardson  */
84199a2dd95SBruce Richardson static inline int64_t
84299a2dd95SBruce Richardson rte_atomic64_read(rte_atomic64_t *v);
84399a2dd95SBruce Richardson 
84499a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
84599a2dd95SBruce Richardson static inline int64_t
84699a2dd95SBruce Richardson rte_atomic64_read(rte_atomic64_t *v)
84799a2dd95SBruce Richardson {
84899a2dd95SBruce Richardson #ifdef __LP64__
84999a2dd95SBruce Richardson 	return v->cnt;
85099a2dd95SBruce Richardson #else
85199a2dd95SBruce Richardson 	int success = 0;
85299a2dd95SBruce Richardson 	uint64_t tmp;
85399a2dd95SBruce Richardson 
85499a2dd95SBruce Richardson 	while (success == 0) {
85599a2dd95SBruce Richardson 		tmp = v->cnt;
85699a2dd95SBruce Richardson 		/* replace the value by itself */
85799a2dd95SBruce Richardson 		success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt,
85899a2dd95SBruce Richardson 		                              tmp, tmp);
85999a2dd95SBruce Richardson 	}
86099a2dd95SBruce Richardson 	return tmp;
86199a2dd95SBruce Richardson #endif
86299a2dd95SBruce Richardson }
86399a2dd95SBruce Richardson #endif
86499a2dd95SBruce Richardson 
86599a2dd95SBruce Richardson /**
86699a2dd95SBruce Richardson  * Atomically set a 64-bit counter.
86799a2dd95SBruce Richardson  *
86899a2dd95SBruce Richardson  * @param v
86999a2dd95SBruce Richardson  *   A pointer to the atomic counter.
87099a2dd95SBruce Richardson  * @param new_value
87199a2dd95SBruce Richardson  *   The new value of the counter.
87299a2dd95SBruce Richardson  */
87399a2dd95SBruce Richardson static inline void
87499a2dd95SBruce Richardson rte_atomic64_set(rte_atomic64_t *v, int64_t new_value);
87599a2dd95SBruce Richardson 
87699a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
87799a2dd95SBruce Richardson static inline void
87899a2dd95SBruce Richardson rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
87999a2dd95SBruce Richardson {
88099a2dd95SBruce Richardson #ifdef __LP64__
88199a2dd95SBruce Richardson 	v->cnt = new_value;
88299a2dd95SBruce Richardson #else
88399a2dd95SBruce Richardson 	int success = 0;
88499a2dd95SBruce Richardson 	uint64_t tmp;
88599a2dd95SBruce Richardson 
88699a2dd95SBruce Richardson 	while (success == 0) {
88799a2dd95SBruce Richardson 		tmp = v->cnt;
88899a2dd95SBruce Richardson 		success = rte_atomic64_cmpset((volatile uint64_t *)&v->cnt,
88999a2dd95SBruce Richardson 		                              tmp, new_value);
89099a2dd95SBruce Richardson 	}
89199a2dd95SBruce Richardson #endif
89299a2dd95SBruce Richardson }
89399a2dd95SBruce Richardson #endif
89499a2dd95SBruce Richardson 
89599a2dd95SBruce Richardson /**
89699a2dd95SBruce Richardson  * Atomically add a 64-bit value to a counter.
89799a2dd95SBruce Richardson  *
89899a2dd95SBruce Richardson  * @param v
89999a2dd95SBruce Richardson  *   A pointer to the atomic counter.
90099a2dd95SBruce Richardson  * @param inc
90199a2dd95SBruce Richardson  *   The value to be added to the counter.
90299a2dd95SBruce Richardson  */
90399a2dd95SBruce Richardson static inline void
90499a2dd95SBruce Richardson rte_atomic64_add(rte_atomic64_t *v, int64_t inc);
90599a2dd95SBruce Richardson 
90699a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
90799a2dd95SBruce Richardson static inline void
90899a2dd95SBruce Richardson rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
90999a2dd95SBruce Richardson {
9109290f8beSTyler Retzlaff 	rte_atomic_fetch_add_explicit((volatile __rte_atomic int64_t *)&v->cnt, inc,
9119290f8beSTyler Retzlaff 		rte_memory_order_seq_cst);
91299a2dd95SBruce Richardson }
91399a2dd95SBruce Richardson #endif
91499a2dd95SBruce Richardson 
91599a2dd95SBruce Richardson /**
91699a2dd95SBruce Richardson  * Atomically subtract a 64-bit value from a counter.
91799a2dd95SBruce Richardson  *
91899a2dd95SBruce Richardson  * @param v
91999a2dd95SBruce Richardson  *   A pointer to the atomic counter.
92099a2dd95SBruce Richardson  * @param dec
92199a2dd95SBruce Richardson  *   The value to be subtracted from the counter.
92299a2dd95SBruce Richardson  */
92399a2dd95SBruce Richardson static inline void
92499a2dd95SBruce Richardson rte_atomic64_sub(rte_atomic64_t *v, int64_t dec);
92599a2dd95SBruce Richardson 
92699a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
92799a2dd95SBruce Richardson static inline void
92899a2dd95SBruce Richardson rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
92999a2dd95SBruce Richardson {
9309290f8beSTyler Retzlaff 	rte_atomic_fetch_sub_explicit((volatile __rte_atomic int64_t *)&v->cnt, dec,
9319290f8beSTyler Retzlaff 		rte_memory_order_seq_cst);
93299a2dd95SBruce Richardson }
93399a2dd95SBruce Richardson #endif
93499a2dd95SBruce Richardson 
93599a2dd95SBruce Richardson /**
93699a2dd95SBruce Richardson  * Atomically increment a 64-bit counter by one and test.
93799a2dd95SBruce Richardson  *
93899a2dd95SBruce Richardson  * @param v
93999a2dd95SBruce Richardson  *   A pointer to the atomic counter.
94099a2dd95SBruce Richardson  */
94199a2dd95SBruce Richardson static inline void
94299a2dd95SBruce Richardson rte_atomic64_inc(rte_atomic64_t *v);
94399a2dd95SBruce Richardson 
94499a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
94599a2dd95SBruce Richardson static inline void
94699a2dd95SBruce Richardson rte_atomic64_inc(rte_atomic64_t *v)
94799a2dd95SBruce Richardson {
94899a2dd95SBruce Richardson 	rte_atomic64_add(v, 1);
94999a2dd95SBruce Richardson }
95099a2dd95SBruce Richardson #endif
95199a2dd95SBruce Richardson 
95299a2dd95SBruce Richardson /**
95399a2dd95SBruce Richardson  * Atomically decrement a 64-bit counter by one and test.
95499a2dd95SBruce Richardson  *
95599a2dd95SBruce Richardson  * @param v
95699a2dd95SBruce Richardson  *   A pointer to the atomic counter.
95799a2dd95SBruce Richardson  */
95899a2dd95SBruce Richardson static inline void
95999a2dd95SBruce Richardson rte_atomic64_dec(rte_atomic64_t *v);
96099a2dd95SBruce Richardson 
96199a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
96299a2dd95SBruce Richardson static inline void
96399a2dd95SBruce Richardson rte_atomic64_dec(rte_atomic64_t *v)
96499a2dd95SBruce Richardson {
96599a2dd95SBruce Richardson 	rte_atomic64_sub(v, 1);
96699a2dd95SBruce Richardson }
96799a2dd95SBruce Richardson #endif
96899a2dd95SBruce Richardson 
96999a2dd95SBruce Richardson /**
97099a2dd95SBruce Richardson  * Add a 64-bit value to an atomic counter and return the result.
97199a2dd95SBruce Richardson  *
97299a2dd95SBruce Richardson  * Atomically adds the 64-bit value (inc) to the atomic counter (v) and
97399a2dd95SBruce Richardson  * returns the value of v after the addition.
97499a2dd95SBruce Richardson  *
97599a2dd95SBruce Richardson  * @param v
97699a2dd95SBruce Richardson  *   A pointer to the atomic counter.
97799a2dd95SBruce Richardson  * @param inc
97899a2dd95SBruce Richardson  *   The value to be added to the counter.
97999a2dd95SBruce Richardson  * @return
98099a2dd95SBruce Richardson  *   The value of v after the addition.
98199a2dd95SBruce Richardson  */
98299a2dd95SBruce Richardson static inline int64_t
98399a2dd95SBruce Richardson rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc);
98499a2dd95SBruce Richardson 
98599a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
98699a2dd95SBruce Richardson static inline int64_t
98799a2dd95SBruce Richardson rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
98899a2dd95SBruce Richardson {
9899290f8beSTyler Retzlaff 	return rte_atomic_fetch_add_explicit((volatile __rte_atomic int64_t *)&v->cnt, inc,
9909290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) + inc;
99199a2dd95SBruce Richardson }
99299a2dd95SBruce Richardson #endif
99399a2dd95SBruce Richardson 
99499a2dd95SBruce Richardson /**
99599a2dd95SBruce Richardson  * Subtract a 64-bit value from an atomic counter and return the result.
99699a2dd95SBruce Richardson  *
99799a2dd95SBruce Richardson  * Atomically subtracts the 64-bit value (dec) from the atomic counter (v)
99899a2dd95SBruce Richardson  * and returns the value of v after the subtraction.
99999a2dd95SBruce Richardson  *
100099a2dd95SBruce Richardson  * @param v
100199a2dd95SBruce Richardson  *   A pointer to the atomic counter.
100299a2dd95SBruce Richardson  * @param dec
100399a2dd95SBruce Richardson  *   The value to be subtracted from the counter.
100499a2dd95SBruce Richardson  * @return
100599a2dd95SBruce Richardson  *   The value of v after the subtraction.
100699a2dd95SBruce Richardson  */
100799a2dd95SBruce Richardson static inline int64_t
100899a2dd95SBruce Richardson rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec);
100999a2dd95SBruce Richardson 
101099a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
101199a2dd95SBruce Richardson static inline int64_t
101299a2dd95SBruce Richardson rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
101399a2dd95SBruce Richardson {
10149290f8beSTyler Retzlaff 	return rte_atomic_fetch_sub_explicit((volatile __rte_atomic int64_t *)&v->cnt, dec,
10159290f8beSTyler Retzlaff 		rte_memory_order_seq_cst) - dec;
101699a2dd95SBruce Richardson }
101799a2dd95SBruce Richardson #endif
101899a2dd95SBruce Richardson 
101999a2dd95SBruce Richardson /**
102099a2dd95SBruce Richardson  * Atomically increment a 64-bit counter by one and test.
102199a2dd95SBruce Richardson  *
102299a2dd95SBruce Richardson  * Atomically increments the atomic counter (v) by one and returns
102399a2dd95SBruce Richardson  * true if the result is 0, or false in all other cases.
102499a2dd95SBruce Richardson  *
102599a2dd95SBruce Richardson  * @param v
102699a2dd95SBruce Richardson  *   A pointer to the atomic counter.
102799a2dd95SBruce Richardson  * @return
102899a2dd95SBruce Richardson  *   True if the result after the addition is 0; false otherwise.
102999a2dd95SBruce Richardson  */
103099a2dd95SBruce Richardson static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v);
103199a2dd95SBruce Richardson 
103299a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
103399a2dd95SBruce Richardson static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
103499a2dd95SBruce Richardson {
103599a2dd95SBruce Richardson 	return rte_atomic64_add_return(v, 1) == 0;
103699a2dd95SBruce Richardson }
103799a2dd95SBruce Richardson #endif
103899a2dd95SBruce Richardson 
103999a2dd95SBruce Richardson /**
104099a2dd95SBruce Richardson  * Atomically decrement a 64-bit counter by one and test.
104199a2dd95SBruce Richardson  *
104299a2dd95SBruce Richardson  * Atomically decrements the atomic counter (v) by one and returns true if
104399a2dd95SBruce Richardson  * the result is 0, or false in all other cases.
104499a2dd95SBruce Richardson  *
104599a2dd95SBruce Richardson  * @param v
104699a2dd95SBruce Richardson  *   A pointer to the atomic counter.
104799a2dd95SBruce Richardson  * @return
104899a2dd95SBruce Richardson  *   True if the result after subtraction is 0; false otherwise.
104999a2dd95SBruce Richardson  */
105099a2dd95SBruce Richardson static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v);
105199a2dd95SBruce Richardson 
105299a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
105399a2dd95SBruce Richardson static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
105499a2dd95SBruce Richardson {
105599a2dd95SBruce Richardson 	return rte_atomic64_sub_return(v, 1) == 0;
105699a2dd95SBruce Richardson }
105799a2dd95SBruce Richardson #endif
105899a2dd95SBruce Richardson 
105999a2dd95SBruce Richardson /**
106099a2dd95SBruce Richardson  * Atomically test and set a 64-bit atomic counter.
106199a2dd95SBruce Richardson  *
106299a2dd95SBruce Richardson  * If the counter value is already set, return 0 (failed). Otherwise, set
106399a2dd95SBruce Richardson  * the counter value to 1 and return 1 (success).
106499a2dd95SBruce Richardson  *
106599a2dd95SBruce Richardson  * @param v
106699a2dd95SBruce Richardson  *   A pointer to the atomic counter.
106799a2dd95SBruce Richardson  * @return
106899a2dd95SBruce Richardson  *   0 if failed; else 1, success.
106999a2dd95SBruce Richardson  */
107099a2dd95SBruce Richardson static inline int rte_atomic64_test_and_set(rte_atomic64_t *v);
107199a2dd95SBruce Richardson 
107299a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
107399a2dd95SBruce Richardson static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
107499a2dd95SBruce Richardson {
107599a2dd95SBruce Richardson 	return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
107699a2dd95SBruce Richardson }
107799a2dd95SBruce Richardson #endif
107899a2dd95SBruce Richardson 
107999a2dd95SBruce Richardson /**
108099a2dd95SBruce Richardson  * Atomically set a 64-bit counter to 0.
108199a2dd95SBruce Richardson  *
108299a2dd95SBruce Richardson  * @param v
108399a2dd95SBruce Richardson  *   A pointer to the atomic counter.
108499a2dd95SBruce Richardson  */
108599a2dd95SBruce Richardson static inline void rte_atomic64_clear(rte_atomic64_t *v);
108699a2dd95SBruce Richardson 
108799a2dd95SBruce Richardson #ifdef RTE_FORCE_INTRINSICS
108899a2dd95SBruce Richardson static inline void rte_atomic64_clear(rte_atomic64_t *v)
108999a2dd95SBruce Richardson {
109099a2dd95SBruce Richardson 	rte_atomic64_set(v, 0);
109199a2dd95SBruce Richardson }
109299a2dd95SBruce Richardson #endif
109399a2dd95SBruce Richardson 
109427da6a12STyler Retzlaff #endif
109527da6a12STyler Retzlaff 
109699a2dd95SBruce Richardson /*------------------------ 128 bit atomic operations -------------------------*/
109799a2dd95SBruce Richardson 
109899a2dd95SBruce Richardson /**
109999a2dd95SBruce Richardson  * 128-bit integer structure.
110099a2dd95SBruce Richardson  */
1101c6552d9aSTyler Retzlaff typedef struct __rte_aligned(16) {
110299a2dd95SBruce Richardson 	union {
110399a2dd95SBruce Richardson 		uint64_t val[2];
110499a2dd95SBruce Richardson #ifdef RTE_ARCH_64
110527da6a12STyler Retzlaff #ifndef RTE_TOOLCHAIN_MSVC
110699a2dd95SBruce Richardson 		__extension__ __int128 int128;
110799a2dd95SBruce Richardson #endif
110827da6a12STyler Retzlaff #endif
110999a2dd95SBruce Richardson 	};
1110c6552d9aSTyler Retzlaff } rte_int128_t;
111199a2dd95SBruce Richardson 
111299a2dd95SBruce Richardson #ifdef __DOXYGEN__
111399a2dd95SBruce Richardson 
111499a2dd95SBruce Richardson /**
111599a2dd95SBruce Richardson  * An atomic compare and set function used by the mutex functions.
111699a2dd95SBruce Richardson  * (Atomically) Equivalent to:
111799a2dd95SBruce Richardson  * @code
111899a2dd95SBruce Richardson  *   if (*dst == *exp)
111999a2dd95SBruce Richardson  *     *dst = *src
112099a2dd95SBruce Richardson  *   else
112199a2dd95SBruce Richardson  *     *exp = *dst
112299a2dd95SBruce Richardson  * @endcode
112399a2dd95SBruce Richardson  *
112499a2dd95SBruce Richardson  * @note This function is currently available for the x86-64 and aarch64
112599a2dd95SBruce Richardson  * platforms.
112699a2dd95SBruce Richardson  *
112799a2dd95SBruce Richardson  * @note The success and failure arguments must be one of the __ATOMIC_* values
112899a2dd95SBruce Richardson  * defined in the C++11 standard. For details on their behavior, refer to the
112999a2dd95SBruce Richardson  * standard.
113099a2dd95SBruce Richardson  *
113199a2dd95SBruce Richardson  * @param dst
113299a2dd95SBruce Richardson  *   The destination into which the value will be written.
113399a2dd95SBruce Richardson  * @param exp
113499a2dd95SBruce Richardson  *   Pointer to the expected value. If the operation fails, this memory is
113599a2dd95SBruce Richardson  *   updated with the actual value.
113699a2dd95SBruce Richardson  * @param src
113799a2dd95SBruce Richardson  *   Pointer to the new value.
113899a2dd95SBruce Richardson  * @param weak
113999a2dd95SBruce Richardson  *   A value of true allows the comparison to spuriously fail and allows the
114099a2dd95SBruce Richardson  *   'exp' update to occur non-atomically (i.e. a torn read may occur).
114199a2dd95SBruce Richardson  *   Implementations may ignore this argument and only implement the strong
114299a2dd95SBruce Richardson  *   variant.
114399a2dd95SBruce Richardson  * @param success
114499a2dd95SBruce Richardson  *   If successful, the operation's memory behavior conforms to this (or a
114599a2dd95SBruce Richardson  *   stronger) model.
114699a2dd95SBruce Richardson  * @param failure
114799a2dd95SBruce Richardson  *   If unsuccessful, the operation's memory behavior conforms to this (or a
11481ec6a845STyler Retzlaff  *   stronger) model. This argument cannot be rte_memory_order_release,
11491ec6a845STyler Retzlaff  *   rte_memory_order_acq_rel, or a stronger model than success.
115099a2dd95SBruce Richardson  * @return
115199a2dd95SBruce Richardson  *   Non-zero on success; 0 on failure.
115299a2dd95SBruce Richardson  */
115399a2dd95SBruce Richardson static inline int
115499a2dd95SBruce Richardson rte_atomic128_cmp_exchange(rte_int128_t *dst,
115599a2dd95SBruce Richardson 			   rte_int128_t *exp,
115699a2dd95SBruce Richardson 			   const rte_int128_t *src,
115799a2dd95SBruce Richardson 			   unsigned int weak,
115899a2dd95SBruce Richardson 			   int success,
115999a2dd95SBruce Richardson 			   int failure);
116099a2dd95SBruce Richardson 
116199a2dd95SBruce Richardson #endif /* __DOXYGEN__ */
116299a2dd95SBruce Richardson 
1163*719834a6SMattias Rönnblom #ifdef __cplusplus
1164*719834a6SMattias Rönnblom }
1165*719834a6SMattias Rönnblom #endif
1166*719834a6SMattias Rönnblom 
116799a2dd95SBruce Richardson #endif /* _RTE_ATOMIC_H_ */
1168