New upstream version 18.08
[deb_dpdk.git] / lib / librte_eal / common / include / arch / x86 / rte_atomic_64.h
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 /*
35  * Inspired from FreeBSD src/sys/amd64/include/atomic.h
36  * Copyright (c) 1998 Doug Rabson
37  * All rights reserved.
38  */
39
40 #ifndef _RTE_ATOMIC_X86_H_
41 #error do not include this file directly, use <rte_atomic.h> instead
42 #endif
43
44 #ifndef _RTE_ATOMIC_X86_64_H_
45 #define _RTE_ATOMIC_X86_64_H_
46
47 #include <stdint.h>
48 #include <rte_common.h>
49 #include <rte_atomic.h>
50
51 /*------------------------- 64 bit atomic operations -------------------------*/
52
53 #ifndef RTE_FORCE_INTRINSICS
54 static inline int
55 rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src)
56 {
57         uint8_t res;
58
59
60         asm volatile(
61                         MPLOCKED
62                         "cmpxchgq %[src], %[dst];"
63                         "sete %[res];"
64                         : [res] "=a" (res),     /* output */
65                           [dst] "=m" (*dst)
66                         : [src] "r" (src),      /* input */
67                           "a" (exp),
68                           "m" (*dst)
69                         : "memory");            /* no-clobber list */
70
71         return res;
72 }
73
74 static inline uint64_t
75 rte_atomic64_exchange(volatile uint64_t *dst, uint64_t val)
76 {
77         asm volatile(
78                         MPLOCKED
79                         "xchgq %0, %1;"
80                         : "=r" (val), "=m" (*dst)
81                         : "0" (val),  "m" (*dst)
82                         : "memory");         /* no-clobber list */
83         return val;
84 }
85
86 static inline void
87 rte_atomic64_init(rte_atomic64_t *v)
88 {
89         v->cnt = 0;
90 }
91
92 static inline int64_t
93 rte_atomic64_read(rte_atomic64_t *v)
94 {
95         return v->cnt;
96 }
97
98 static inline void
99 rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
100 {
101         v->cnt = new_value;
102 }
103
104 static inline void
105 rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
106 {
107         asm volatile(
108                         MPLOCKED
109                         "addq %[inc], %[cnt]"
110                         : [cnt] "=m" (v->cnt)   /* output */
111                         : [inc] "ir" (inc),     /* input */
112                           "m" (v->cnt)
113                         );
114 }
115
116 static inline void
117 rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
118 {
119         asm volatile(
120                         MPLOCKED
121                         "subq %[dec], %[cnt]"
122                         : [cnt] "=m" (v->cnt)   /* output */
123                         : [dec] "ir" (dec),     /* input */
124                           "m" (v->cnt)
125                         );
126 }
127
128 static inline void
129 rte_atomic64_inc(rte_atomic64_t *v)
130 {
131         asm volatile(
132                         MPLOCKED
133                         "incq %[cnt]"
134                         : [cnt] "=m" (v->cnt)   /* output */
135                         : "m" (v->cnt)          /* input */
136                         );
137 }
138
139 static inline void
140 rte_atomic64_dec(rte_atomic64_t *v)
141 {
142         asm volatile(
143                         MPLOCKED
144                         "decq %[cnt]"
145                         : [cnt] "=m" (v->cnt)   /* output */
146                         : "m" (v->cnt)          /* input */
147                         );
148 }
149
150 static inline int64_t
151 rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
152 {
153         int64_t prev = inc;
154
155         asm volatile(
156                         MPLOCKED
157                         "xaddq %[prev], %[cnt]"
158                         : [prev] "+r" (prev),   /* output */
159                           [cnt] "=m" (v->cnt)
160                         : "m" (v->cnt)          /* input */
161                         );
162         return prev + inc;
163 }
164
165 static inline int64_t
166 rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
167 {
168         return rte_atomic64_add_return(v, -dec);
169 }
170
171 static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
172 {
173         uint8_t ret;
174
175         asm volatile(
176                         MPLOCKED
177                         "incq %[cnt] ; "
178                         "sete %[ret]"
179                         : [cnt] "+m" (v->cnt), /* output */
180                           [ret] "=qm" (ret)
181                         );
182
183         return ret != 0;
184 }
185
186 static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
187 {
188         uint8_t ret;
189
190         asm volatile(
191                         MPLOCKED
192                         "decq %[cnt] ; "
193                         "sete %[ret]"
194                         : [cnt] "+m" (v->cnt),  /* output */
195                           [ret] "=qm" (ret)
196                         );
197         return ret != 0;
198 }
199
200 static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
201 {
202         return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
203 }
204
205 static inline void rte_atomic64_clear(rte_atomic64_t *v)
206 {
207         v->cnt = 0;
208 }
209 #endif
210
211 #endif /* _RTE_ATOMIC_X86_64_H_ */