8fb796c635be064ee55e190d2ae11dd576875d95
[dpdk.git] / lib / librte_eal / common / include / arch / x86 / rte_atomic.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #ifndef _RTE_ATOMIC_X86_H_
6 #define _RTE_ATOMIC_X86_H_
7
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11
12 #include <stdint.h>
13 #include <rte_common.h>
14 #include <rte_config.h>
15 #include <emmintrin.h>
16 #include "generic/rte_atomic.h"
17
18 #if RTE_MAX_LCORE == 1
19 #define MPLOCKED                        /**< No need to insert MP lock prefix. */
20 #else
21 #define MPLOCKED        "lock ; "       /**< Insert MP lock prefix. */
22 #endif
23
24 #define rte_mb() _mm_mfence()
25
26 #define rte_wmb() _mm_sfence()
27
28 #define rte_rmb() _mm_lfence()
29
30 #define rte_smp_mb() rte_mb()
31
32 #define rte_smp_wmb() rte_compiler_barrier()
33
34 #define rte_smp_rmb() rte_compiler_barrier()
35
36 #define rte_io_mb() rte_mb()
37
38 #define rte_io_wmb() rte_compiler_barrier()
39
40 #define rte_io_rmb() rte_compiler_barrier()
41
42 #define rte_cio_wmb() rte_compiler_barrier()
43
44 #define rte_cio_rmb() rte_compiler_barrier()
45
46 /*------------------------- 16 bit atomic operations -------------------------*/
47
48 #ifndef RTE_FORCE_INTRINSICS
49 static inline int
50 rte_atomic16_cmpset(volatile uint16_t *dst, uint16_t exp, uint16_t src)
51 {
52         uint8_t res;
53
54         asm volatile(
55                         MPLOCKED
56                         "cmpxchgw %[src], %[dst];"
57                         "sete %[res];"
58                         : [res] "=a" (res),     /* output */
59                           [dst] "=m" (*dst)
60                         : [src] "r" (src),      /* input */
61                           "a" (exp),
62                           "m" (*dst)
63                         : "memory");            /* no-clobber list */
64         return res;
65 }
66
67 static inline int rte_atomic16_test_and_set(rte_atomic16_t *v)
68 {
69         return rte_atomic16_cmpset((volatile uint16_t *)&v->cnt, 0, 1);
70 }
71
72 static inline void
73 rte_atomic16_inc(rte_atomic16_t *v)
74 {
75         asm volatile(
76                         MPLOCKED
77                         "incw %[cnt]"
78                         : [cnt] "=m" (v->cnt)   /* output */
79                         : "m" (v->cnt)          /* input */
80                         );
81 }
82
83 static inline void
84 rte_atomic16_dec(rte_atomic16_t *v)
85 {
86         asm volatile(
87                         MPLOCKED
88                         "decw %[cnt]"
89                         : [cnt] "=m" (v->cnt)   /* output */
90                         : "m" (v->cnt)          /* input */
91                         );
92 }
93
94 static inline int rte_atomic16_inc_and_test(rte_atomic16_t *v)
95 {
96         uint8_t ret;
97
98         asm volatile(
99                         MPLOCKED
100                         "incw %[cnt] ; "
101                         "sete %[ret]"
102                         : [cnt] "+m" (v->cnt),  /* output */
103                           [ret] "=qm" (ret)
104                         );
105         return ret != 0;
106 }
107
108 static inline int rte_atomic16_dec_and_test(rte_atomic16_t *v)
109 {
110         uint8_t ret;
111
112         asm volatile(MPLOCKED
113                         "decw %[cnt] ; "
114                         "sete %[ret]"
115                         : [cnt] "+m" (v->cnt),  /* output */
116                           [ret] "=qm" (ret)
117                         );
118         return ret != 0;
119 }
120
121 /*------------------------- 32 bit atomic operations -------------------------*/
122
123 static inline int
124 rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
125 {
126         uint8_t res;
127
128         asm volatile(
129                         MPLOCKED
130                         "cmpxchgl %[src], %[dst];"
131                         "sete %[res];"
132                         : [res] "=a" (res),     /* output */
133                           [dst] "=m" (*dst)
134                         : [src] "r" (src),      /* input */
135                           "a" (exp),
136                           "m" (*dst)
137                         : "memory");            /* no-clobber list */
138         return res;
139 }
140
141 static inline int rte_atomic32_test_and_set(rte_atomic32_t *v)
142 {
143         return rte_atomic32_cmpset((volatile uint32_t *)&v->cnt, 0, 1);
144 }
145
146 static inline void
147 rte_atomic32_inc(rte_atomic32_t *v)
148 {
149         asm volatile(
150                         MPLOCKED
151                         "incl %[cnt]"
152                         : [cnt] "=m" (v->cnt)   /* output */
153                         : "m" (v->cnt)          /* input */
154                         );
155 }
156
157 static inline void
158 rte_atomic32_dec(rte_atomic32_t *v)
159 {
160         asm volatile(
161                         MPLOCKED
162                         "decl %[cnt]"
163                         : [cnt] "=m" (v->cnt)   /* output */
164                         : "m" (v->cnt)          /* input */
165                         );
166 }
167
168 static inline int rte_atomic32_inc_and_test(rte_atomic32_t *v)
169 {
170         uint8_t ret;
171
172         asm volatile(
173                         MPLOCKED
174                         "incl %[cnt] ; "
175                         "sete %[ret]"
176                         : [cnt] "+m" (v->cnt),  /* output */
177                           [ret] "=qm" (ret)
178                         );
179         return ret != 0;
180 }
181
182 static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)
183 {
184         uint8_t ret;
185
186         asm volatile(MPLOCKED
187                         "decl %[cnt] ; "
188                         "sete %[ret]"
189                         : [cnt] "+m" (v->cnt),  /* output */
190                           [ret] "=qm" (ret)
191                         );
192         return ret != 0;
193 }
194 #endif
195
196 #ifdef RTE_ARCH_I686
197 #include "rte_atomic_32.h"
198 #else
199 #include "rte_atomic_64.h"
200 #endif
201
202 #ifdef __cplusplus
203 }
204 #endif
205
206 #endif /* _RTE_ATOMIC_X86_H_ */