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