1 /* atomic.c -- implement atomic routines for Go.
2 
3    Copyright 2011 The Go Authors. All rights reserved.
4    Use of this source code is governed by a BSD-style
5    license that can be found in the LICENSE file.  */
6 
7 #include <stdint.h>
8 
9 #include "runtime.h"
10 
11 int32_t SwapInt32 (int32_t *, int32_t)
12   __asm__ (GOSYM_PREFIX "sync_atomic.SwapInt32")
13   __attribute__ ((no_split_stack));
14 
15 int32_t
SwapInt32(int32_t * addr,int32_t new)16 SwapInt32 (int32_t *addr, int32_t new)
17 {
18   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
19 }
20 
21 int64_t SwapInt64 (int64_t *, int64_t)
22   __asm__ (GOSYM_PREFIX "sync_atomic.SwapInt64")
23   __attribute__ ((no_split_stack));
24 
25 int64_t
SwapInt64(int64_t * addr,int64_t new)26 SwapInt64 (int64_t *addr, int64_t new)
27 {
28   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
29 }
30 
31 uint32_t SwapUint32 (uint32_t *, uint32_t)
32   __asm__ (GOSYM_PREFIX "sync_atomic.SwapUint32")
33   __attribute__ ((no_split_stack));
34 
35 uint32_t
SwapUint32(uint32_t * addr,uint32_t new)36 SwapUint32 (uint32_t *addr, uint32_t new)
37 {
38   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
39 }
40 
41 uint64_t SwapUint64 (uint64_t *, uint64_t)
42   __asm__ (GOSYM_PREFIX "sync_atomic.SwapUint64")
43   __attribute__ ((no_split_stack));
44 
45 uint64_t
SwapUint64(uint64_t * addr,uint64_t new)46 SwapUint64 (uint64_t *addr, uint64_t new)
47 {
48   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
49 }
50 
51 uintptr_t SwapUintptr (uintptr_t *, uintptr_t)
52   __asm__ (GOSYM_PREFIX "sync_atomic.SwapUintptr")
53   __attribute__ ((no_split_stack));
54 
55 uintptr_t
SwapUintptr(uintptr_t * addr,uintptr_t new)56 SwapUintptr (uintptr_t *addr, uintptr_t new)
57 {
58   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
59 }
60 
61 void *SwapPointer (void **, void *)
62   __asm__ (GOSYM_PREFIX "sync_atomic.SwapPointer")
63   __attribute__ ((no_split_stack));
64 
65 void *
SwapPointer(void ** addr,void * new)66 SwapPointer (void **addr, void *new)
67 {
68   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
69 }
70 
71 _Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t)
72   __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt32")
73   __attribute__ ((no_split_stack));
74 
75 _Bool
CompareAndSwapInt32(int32_t * val,int32_t old,int32_t new)76 CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new)
77 {
78   return __sync_bool_compare_and_swap (val, old, new);
79 }
80 
81 _Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t)
82   __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt64")
83   __attribute__ ((no_split_stack));
84 
85 _Bool
CompareAndSwapInt64(int64_t * val,int64_t old,int64_t new)86 CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
87 {
88   return __sync_bool_compare_and_swap (val, old, new);
89 }
90 
91 _Bool CompareAndSwapUint32 (uint32_t *, uint32_t, uint32_t)
92   __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint32")
93   __attribute__ ((no_split_stack));
94 
95 _Bool
CompareAndSwapUint32(uint32_t * val,uint32_t old,uint32_t new)96 CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new)
97 {
98   return __sync_bool_compare_and_swap (val, old, new);
99 }
100 
101 _Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t)
102   __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint64")
103   __attribute__ ((no_split_stack));
104 
105 _Bool
CompareAndSwapUint64(uint64_t * val,uint64_t old,uint64_t new)106 CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
107 {
108   return __sync_bool_compare_and_swap (val, old, new);
109 }
110 
111 _Bool CompareAndSwapUintptr (uintptr_t *, uintptr_t, uintptr_t)
112   __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUintptr")
113   __attribute__ ((no_split_stack));
114 
115 _Bool
CompareAndSwapUintptr(uintptr_t * val,uintptr_t old,uintptr_t new)116 CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
117 {
118   return __sync_bool_compare_and_swap (val, old, new);
119 }
120 
121 _Bool CompareAndSwapPointer (void **, void *, void *)
122   __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapPointer")
123   __attribute__ ((no_split_stack));
124 
125 _Bool
CompareAndSwapPointer(void ** val,void * old,void * new)126 CompareAndSwapPointer (void **val, void *old, void *new)
127 {
128   return __sync_bool_compare_and_swap (val, old, new);
129 }
130 
131 int32_t AddInt32 (int32_t *, int32_t)
132   __asm__ (GOSYM_PREFIX "sync_atomic.AddInt32")
133   __attribute__ ((no_split_stack));
134 
135 int32_t
AddInt32(int32_t * val,int32_t delta)136 AddInt32 (int32_t *val, int32_t delta)
137 {
138   return __sync_add_and_fetch (val, delta);
139 }
140 
141 uint32_t AddUint32 (uint32_t *, uint32_t)
142   __asm__ (GOSYM_PREFIX "sync_atomic.AddUint32")
143   __attribute__ ((no_split_stack));
144 
145 uint32_t
AddUint32(uint32_t * val,uint32_t delta)146 AddUint32 (uint32_t *val, uint32_t delta)
147 {
148   return __sync_add_and_fetch (val, delta);
149 }
150 
151 int64_t AddInt64 (int64_t *, int64_t)
152   __asm__ (GOSYM_PREFIX "sync_atomic.AddInt64")
153   __attribute__ ((no_split_stack));
154 
155 int64_t
AddInt64(int64_t * val,int64_t delta)156 AddInt64 (int64_t *val, int64_t delta)
157 {
158   return __sync_add_and_fetch (val, delta);
159 }
160 
161 uint64_t AddUint64 (uint64_t *, uint64_t)
162   __asm__ (GOSYM_PREFIX "sync_atomic.AddUint64")
163   __attribute__ ((no_split_stack));
164 
165 uint64_t
AddUint64(uint64_t * val,uint64_t delta)166 AddUint64 (uint64_t *val, uint64_t delta)
167 {
168   return __sync_add_and_fetch (val, delta);
169 }
170 
171 uintptr_t AddUintptr (uintptr_t *, uintptr_t)
172   __asm__ (GOSYM_PREFIX "sync_atomic.AddUintptr")
173   __attribute__ ((no_split_stack));
174 
175 uintptr_t
AddUintptr(uintptr_t * val,uintptr_t delta)176 AddUintptr (uintptr_t *val, uintptr_t delta)
177 {
178   return __sync_add_and_fetch (val, delta);
179 }
180 
181 int32_t LoadInt32 (int32_t *addr)
182   __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt32")
183   __attribute__ ((no_split_stack));
184 
185 int32_t
LoadInt32(int32_t * addr)186 LoadInt32 (int32_t *addr)
187 {
188   int32_t v;
189 
190   v = *addr;
191   while (! __sync_bool_compare_and_swap (addr, v, v))
192     v = *addr;
193   return v;
194 }
195 
196 int64_t LoadInt64 (int64_t *addr)
197   __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt64")
198   __attribute__ ((no_split_stack));
199 
200 int64_t
LoadInt64(int64_t * addr)201 LoadInt64 (int64_t *addr)
202 {
203   int64_t v;
204 
205   v = *addr;
206   while (! __sync_bool_compare_and_swap (addr, v, v))
207     v = *addr;
208   return v;
209 }
210 
211 uint32_t LoadUint32 (uint32_t *addr)
212   __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint32")
213   __attribute__ ((no_split_stack));
214 
215 uint32_t
LoadUint32(uint32_t * addr)216 LoadUint32 (uint32_t *addr)
217 {
218   uint32_t v;
219 
220   v = *addr;
221   while (! __sync_bool_compare_and_swap (addr, v, v))
222     v = *addr;
223   return v;
224 }
225 
226 uint64_t LoadUint64 (uint64_t *addr)
227   __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint64")
228   __attribute__ ((no_split_stack));
229 
230 uint64_t
LoadUint64(uint64_t * addr)231 LoadUint64 (uint64_t *addr)
232 {
233   uint64_t v;
234 
235   v = *addr;
236   while (! __sync_bool_compare_and_swap (addr, v, v))
237     v = *addr;
238   return v;
239 }
240 
241 uintptr_t LoadUintptr (uintptr_t *addr)
242   __asm__ (GOSYM_PREFIX "sync_atomic.LoadUintptr")
243   __attribute__ ((no_split_stack));
244 
245 uintptr_t
LoadUintptr(uintptr_t * addr)246 LoadUintptr (uintptr_t *addr)
247 {
248   uintptr_t v;
249 
250   v = *addr;
251   while (! __sync_bool_compare_and_swap (addr, v, v))
252     v = *addr;
253   return v;
254 }
255 
256 void *LoadPointer (void **addr)
257   __asm__ (GOSYM_PREFIX "sync_atomic.LoadPointer")
258   __attribute__ ((no_split_stack));
259 
260 void *
LoadPointer(void ** addr)261 LoadPointer (void **addr)
262 {
263   void *v;
264 
265   v = *addr;
266   while (! __sync_bool_compare_and_swap (addr, v, v))
267     v = *addr;
268   return v;
269 }
270 
271 void StoreInt32 (int32_t *addr, int32_t val)
272   __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt32")
273   __attribute__ ((no_split_stack));
274 
275 void
StoreInt32(int32_t * addr,int32_t val)276 StoreInt32 (int32_t *addr, int32_t val)
277 {
278   int32_t v;
279 
280   v = *addr;
281   while (! __sync_bool_compare_and_swap (addr, v, val))
282     v = *addr;
283 }
284 
285 void StoreInt64 (int64_t *addr, int64_t val)
286   __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt64")
287   __attribute__ ((no_split_stack));
288 
289 void
StoreInt64(int64_t * addr,int64_t val)290 StoreInt64 (int64_t *addr, int64_t val)
291 {
292   int64_t v;
293 
294   v = *addr;
295   while (! __sync_bool_compare_and_swap (addr, v, val))
296     v = *addr;
297 }
298 
299 void StoreUint32 (uint32_t *addr, uint32_t val)
300   __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint32")
301   __attribute__ ((no_split_stack));
302 
303 void
StoreUint32(uint32_t * addr,uint32_t val)304 StoreUint32 (uint32_t *addr, uint32_t val)
305 {
306   uint32_t v;
307 
308   v = *addr;
309   while (! __sync_bool_compare_and_swap (addr, v, val))
310     v = *addr;
311 }
312 
313 void StoreUint64 (uint64_t *addr, uint64_t val)
314   __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint64")
315   __attribute__ ((no_split_stack));
316 
317 void
StoreUint64(uint64_t * addr,uint64_t val)318 StoreUint64 (uint64_t *addr, uint64_t val)
319 {
320   uint64_t v;
321 
322   v = *addr;
323   while (! __sync_bool_compare_and_swap (addr, v, val))
324     v = *addr;
325 }
326 
327 void StoreUintptr (uintptr_t *addr, uintptr_t val)
328   __asm__ (GOSYM_PREFIX "sync_atomic.StoreUintptr")
329   __attribute__ ((no_split_stack));
330 
331 void
StoreUintptr(uintptr_t * addr,uintptr_t val)332 StoreUintptr (uintptr_t *addr, uintptr_t val)
333 {
334   uintptr_t v;
335 
336   v = *addr;
337   while (! __sync_bool_compare_and_swap (addr, v, val))
338     v = *addr;
339 }
340 
341 void StorePointer (void **addr, void *val)
342   __asm__ (GOSYM_PREFIX "sync_atomic.StorePointer")
343   __attribute__ ((no_split_stack));
344 
345 void
StorePointer(void ** addr,void * val)346 StorePointer (void **addr, void *val)
347 {
348   void *v;
349 
350   v = *addr;
351   while (! __sync_bool_compare_and_swap (addr, v, val))
352     v = *addr;
353 }
354