change the internal socketcall selection logic
[musl] / src / internal / atomic.h
1 #ifndef _ATOMIC_H
2 #define _ATOMIC_H
3
4 #include <stdint.h>
5
6 #include "atomic_arch.h"
7
8 #ifdef a_ll
9
10 #ifndef a_pre_llsc
11 #define a_pre_llsc()
12 #endif
13
14 #ifndef a_post_llsc
15 #define a_post_llsc()
16 #endif
17
18 #ifndef a_cas
19 #define a_cas a_cas
20 static inline int a_cas(volatile int *p, int t, int s)
21 {
22         int old;
23         a_pre_llsc();
24         do old = a_ll(p);
25         while (old==t && !a_sc(p, s));
26         a_post_llsc();
27         return old;
28 }
29 #endif
30
31 #ifndef a_swap
32 #define a_swap a_swap
33 static inline int a_swap(volatile int *p, int v)
34 {
35         int old;
36         a_pre_llsc();
37         do old = a_ll(p);
38         while (!a_sc(p, v));
39         a_post_llsc();
40         return old;
41 }
42 #endif
43
44 #ifndef a_fetch_add
45 #define a_fetch_add a_fetch_add
46 static inline int a_fetch_add(volatile int *p, int v)
47 {
48         int old;
49         a_pre_llsc();
50         do old = a_ll(p);
51         while (!a_sc(p, (unsigned)old + v));
52         a_post_llsc();
53         return old;
54 }
55 #endif
56
57 #ifndef a_fetch_and
58 #define a_fetch_and a_fetch_and
59 static inline int a_fetch_and(volatile int *p, int v)
60 {
61         int old;
62         a_pre_llsc();
63         do old = a_ll(p);
64         while (!a_sc(p, old & v));
65         a_post_llsc();
66         return old;
67 }
68 #endif
69
70 #ifndef a_fetch_or
71 #define a_fetch_or a_fetch_or
72 static inline int a_fetch_or(volatile int *p, int v)
73 {
74         int old;
75         a_pre_llsc();
76         do old = a_ll(p);
77         while (!a_sc(p, old | v));
78         a_post_llsc();
79         return old;
80 }
81 #endif
82
83 #endif
84
85 #ifndef a_cas
86 #error missing definition of a_cas
87 #endif
88
89 #ifndef a_swap
90 #define a_swap a_swap
91 static inline int a_swap(volatile int *p, int v)
92 {
93         int old;
94         do old = *p;
95         while (a_cas(p, old, v) != old);
96         return old;
97 }
98 #endif
99
100 #ifndef a_fetch_add
101 #define a_fetch_add a_fetch_add
102 static inline int a_fetch_add(volatile int *p, int v)
103 {
104         int old;
105         do old = *p;
106         while (a_cas(p, old, (unsigned)old+v) != old);
107         return old;
108 }
109 #endif
110
111 #ifndef a_fetch_and
112 #define a_fetch_and a_fetch_and
113 static inline int a_fetch_and(volatile int *p, int v)
114 {
115         int old;
116         do old = *p;
117         while (a_cas(p, old, old&v) != old);
118         return old;
119 }
120 #endif
121 #ifndef a_fetch_or
122 #define a_fetch_or a_fetch_or
123 static inline int a_fetch_or(volatile int *p, int v)
124 {
125         int old;
126         do old = *p;
127         while (a_cas(p, old, old|v) != old);
128         return old;
129 }
130 #endif
131
132 #ifndef a_and
133 #define a_and a_and
134 static inline void a_and(volatile int *p, int v)
135 {
136         a_fetch_and(p, v);
137 }
138 #endif
139
140 #ifndef a_or
141 #define a_or a_or
142 static inline void a_or(volatile int *p, int v)
143 {
144         a_fetch_or(p, v);
145 }
146 #endif
147
148 #ifndef a_inc
149 #define a_inc a_inc
150 static inline void a_inc(volatile int *p)
151 {
152         a_fetch_add(p, 1);
153 }
154 #endif
155
156 #ifndef a_dec
157 #define a_dec a_dec
158 static inline void a_dec(volatile int *p)
159 {
160         a_fetch_add(p, -1);
161 }
162 #endif
163
164 #ifndef a_store
165 #define a_store a_store
166 static inline void a_store(volatile int *p, int v)
167 {
168 #ifdef a_barrier
169         a_barrier();
170         *p = v;
171         a_barrier();
172 #else
173         a_swap(p, v);
174 #endif
175 }
176 #endif
177
178 #ifndef a_barrier
179 #define a_barrier a_barrier
180 static void a_barrier()
181 {
182         volatile int tmp = 0;
183         a_cas(&tmp, 0, 0);
184 }
185 #endif
186
187 #ifndef a_spin
188 #define a_spin a_barrier
189 #endif
190
191 #ifndef a_and_64
192 #define a_and_64 a_and_64
193 static inline void a_and_64(volatile uint64_t *p, uint64_t v)
194 {
195         union { uint64_t v; uint32_t r[2]; } u = { v };
196         if (u.r[0]+1) a_and((int *)p, u.r[0]);
197         if (u.r[1]+1) a_and((int *)p+1, u.r[1]);
198 }
199 #endif
200
201 #ifndef a_or_64
202 #define a_or_64 a_or_64
203 static inline void a_or_64(volatile uint64_t *p, uint64_t v)
204 {
205         union { uint64_t v; uint32_t r[2]; } u = { v };
206         if (u.r[0]) a_or((int *)p, u.r[0]);
207         if (u.r[1]) a_or((int *)p+1, u.r[1]);
208 }
209 #endif
210
211 #ifndef a_cas_p
212 #define a_cas_p a_cas_p
213 static inline void *a_cas_p(volatile void *p, void *t, void *s)
214 {
215         return (void *)a_cas((volatile int *)p, (int)t, (int)s);
216 }
217 #endif
218
219 #ifndef a_or_l
220 #define a_or_l a_or_l
221 static inline void a_or_l(volatile void *p, long v)
222 {
223         if (sizeof(long) == sizeof(int)) a_or(p, v);
224         else a_or_64(p, v);
225 }
226 #endif
227
228 #ifndef a_crash
229 #define a_crash a_crash
230 static inline void a_crash()
231 {
232         *(volatile char *)0=0;
233 }
234 #endif
235
236 #ifndef a_ctz_64
237 #define a_ctz_64 a_ctz_64
238 static inline int a_ctz_64(uint64_t x)
239 {
240         static const char debruijn64[64] = {
241                 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
242                 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
243                 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
244                 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
245         };
246         static const char debruijn32[32] = {
247                 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
248                 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
249         };
250         if (sizeof(long) < 8) {
251                 uint32_t y = x;
252                 if (!y) {
253                         y = x>>32;
254                         return 32 + debruijn32[(y&-y)*0x076be629 >> 27];
255                 }
256                 return debruijn32[(y&-y)*0x076be629 >> 27];
257         }
258         return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
259 }
260 #endif
261
262 #ifndef a_ctz_l
263 #define a_ctz_l a_ctz_l
264 static inline int a_ctz_l(unsigned long x)
265 {
266         static const char debruijn32[32] = {
267                 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
268                 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
269         };
270         if (sizeof(long) == 8) return a_ctz_64(x);
271         return debruijn32[(x&-x)*0x076be629 >> 27];
272 }
273 #endif
274
275 #endif