Imported Upstream version 16.11
[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 void
75 rte_atomic64_init(rte_atomic64_t *v)
76 {
77         v->cnt = 0;
78 }
79
80 static inline int64_t
81 rte_atomic64_read(rte_atomic64_t *v)
82 {
83         return v->cnt;
84 }
85
86 static inline void
87 rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
88 {
89         v->cnt = new_value;
90 }
91
92 static inline void
93 rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
94 {
95         asm volatile(
96                         MPLOCKED
97                         "addq %[inc], %[cnt]"
98                         : [cnt] "=m" (v->cnt)   /* output */
99                         : [inc] "ir" (inc),     /* input */
100                           "m" (v->cnt)
101                         );
102 }
103
104 static inline void
105 rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
106 {
107         asm volatile(
108                         MPLOCKED
109                         "subq %[dec], %[cnt]"
110                         : [cnt] "=m" (v->cnt)   /* output */
111                         : [dec] "ir" (dec),     /* input */
112                           "m" (v->cnt)
113                         );
114 }
115
116 static inline void
117 rte_atomic64_inc(rte_atomic64_t *v)
118 {
119         asm volatile(
120                         MPLOCKED
121                         "incq %[cnt]"
122                         : [cnt] "=m" (v->cnt)   /* output */
123                         : "m" (v->cnt)          /* input */
124                         );
125 }
126
127 static inline void
128 rte_atomic64_dec(rte_atomic64_t *v)
129 {
130         asm volatile(
131                         MPLOCKED
132                         "decq %[cnt]"
133                         : [cnt] "=m" (v->cnt)   /* output */
134                         : "m" (v->cnt)          /* input */
135                         );
136 }
137
138 static inline int64_t
139 rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
140 {
141         int64_t prev = inc;
142
143         asm volatile(
144                         MPLOCKED
145                         "xaddq %[prev], %[cnt]"
146                         : [prev] "+r" (prev),   /* output */
147                           [cnt] "=m" (v->cnt)
148                         : "m" (v->cnt)          /* input */
149                         );
150         return prev + inc;
151 }
152
153 static inline int64_t
154 rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
155 {
156         return rte_atomic64_add_return(v, -dec);
157 }
158
159 static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
160 {
161         uint8_t ret;
162
163         asm volatile(
164                         MPLOCKED
165                         "incq %[cnt] ; "
166                         "sete %[ret]"
167                         : [cnt] "+m" (v->cnt), /* output */
168                           [ret] "=qm" (ret)
169                         );
170
171         return ret != 0;
172 }
173
174 static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
175 {
176         uint8_t ret;
177
178         asm volatile(
179                         MPLOCKED
180                         "decq %[cnt] ; "
181                         "sete %[ret]"
182                         : [cnt] "+m" (v->cnt),  /* output */
183                           [ret] "=qm" (ret)
184                         );
185         return ret != 0;
186 }
187
188 static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
189 {
190         return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
191 }
192
193 static inline void rte_atomic64_clear(rte_atomic64_t *v)
194 {
195         v->cnt = 0;
196 }
197 #endif
198
199 #endif /* _RTE_ATOMIC_X86_64_H_ */