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