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..z2fatomic.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..z2fatomic.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   if (((uintptr_t) addr & 7) != 0)
29     panicmem ();
30   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
31 }
32 
33 uint32_t SwapUint32 (uint32_t *, uint32_t)
34   __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUint32")
35   __attribute__ ((no_split_stack));
36 
37 uint32_t
SwapUint32(uint32_t * addr,uint32_t new)38 SwapUint32 (uint32_t *addr, uint32_t new)
39 {
40   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
41 }
42 
43 uint64_t SwapUint64 (uint64_t *, uint64_t)
44   __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUint64")
45   __attribute__ ((no_split_stack));
46 
47 uint64_t
SwapUint64(uint64_t * addr,uint64_t new)48 SwapUint64 (uint64_t *addr, uint64_t new)
49 {
50   if (((uintptr_t) addr & 7) != 0)
51     panicmem ();
52   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
53 }
54 
55 uintptr_t SwapUintptr (uintptr_t *, uintptr_t)
56   __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUintptr")
57   __attribute__ ((no_split_stack));
58 
59 uintptr_t
SwapUintptr(uintptr_t * addr,uintptr_t new)60 SwapUintptr (uintptr_t *addr, uintptr_t new)
61 {
62   return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
63 }
64 
65 _Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t)
66   __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapInt32")
67   __attribute__ ((no_split_stack));
68 
69 _Bool
CompareAndSwapInt32(int32_t * val,int32_t old,int32_t new)70 CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new)
71 {
72   return __atomic_compare_exchange_n (val, &old, new, false, __ATOMIC_SEQ_CST,
73 				      __ATOMIC_RELAXED);
74 }
75 
76 _Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t)
77   __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapInt64")
78   __attribute__ ((no_split_stack));
79 
80 _Bool
CompareAndSwapInt64(int64_t * val,int64_t old,int64_t new)81 CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
82 {
83   if (((uintptr_t) val & 7) != 0)
84     val = NULL;
85   return __atomic_compare_exchange_n (val, &old, new, false, __ATOMIC_SEQ_CST,
86 				      __ATOMIC_RELAXED);
87 }
88 
89 _Bool CompareAndSwapUint32 (uint32_t *, uint32_t, uint32_t)
90   __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUint32")
91   __attribute__ ((no_split_stack));
92 
93 _Bool
CompareAndSwapUint32(uint32_t * val,uint32_t old,uint32_t new)94 CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new)
95 {
96   return __atomic_compare_exchange_n (val, &old, new, false, __ATOMIC_SEQ_CST,
97 				      __ATOMIC_RELAXED);
98 }
99 
100 _Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t)
101   __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUint64")
102   __attribute__ ((no_split_stack));
103 
104 _Bool
CompareAndSwapUint64(uint64_t * val,uint64_t old,uint64_t new)105 CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
106 {
107   if (((uintptr_t) val & 7) != 0)
108     val = NULL;
109   return __atomic_compare_exchange_n (val, &old, new, false, __ATOMIC_SEQ_CST,
110 				      __ATOMIC_RELAXED);
111 }
112 
113 _Bool CompareAndSwapUintptr (uintptr_t *, uintptr_t, uintptr_t)
114   __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUintptr")
115   __attribute__ ((no_split_stack));
116 
117 _Bool
CompareAndSwapUintptr(uintptr_t * val,uintptr_t old,uintptr_t new)118 CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
119 {
120   return __atomic_compare_exchange_n (val, &old, new, false, __ATOMIC_SEQ_CST,
121 				      __ATOMIC_RELAXED);
122 }
123 
124 int32_t AddInt32 (int32_t *, int32_t)
125   __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddInt32")
126   __attribute__ ((no_split_stack));
127 
128 int32_t
AddInt32(int32_t * val,int32_t delta)129 AddInt32 (int32_t *val, int32_t delta)
130 {
131   return __atomic_add_fetch (val, delta, __ATOMIC_SEQ_CST);
132 }
133 
134 uint32_t AddUint32 (uint32_t *, uint32_t)
135   __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUint32")
136   __attribute__ ((no_split_stack));
137 
138 uint32_t
AddUint32(uint32_t * val,uint32_t delta)139 AddUint32 (uint32_t *val, uint32_t delta)
140 {
141   return __atomic_add_fetch (val, delta, __ATOMIC_SEQ_CST);
142 }
143 
144 int64_t AddInt64 (int64_t *, int64_t)
145   __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddInt64")
146   __attribute__ ((no_split_stack));
147 
148 int64_t
AddInt64(int64_t * val,int64_t delta)149 AddInt64 (int64_t *val, int64_t delta)
150 {
151   if (((uintptr_t) val & 7) != 0)
152     val = NULL;
153   return __atomic_add_fetch (val, delta, __ATOMIC_SEQ_CST);
154 }
155 
156 uint64_t AddUint64 (uint64_t *, uint64_t)
157   __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUint64")
158   __attribute__ ((no_split_stack));
159 
160 uint64_t
AddUint64(uint64_t * val,uint64_t delta)161 AddUint64 (uint64_t *val, uint64_t delta)
162 {
163   if (((uintptr_t) val & 7) != 0)
164     val = NULL;
165   return __atomic_add_fetch (val, delta, __ATOMIC_SEQ_CST);
166 }
167 
168 uintptr_t AddUintptr (uintptr_t *, uintptr_t)
169   __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUintptr")
170   __attribute__ ((no_split_stack));
171 
172 uintptr_t
AddUintptr(uintptr_t * val,uintptr_t delta)173 AddUintptr (uintptr_t *val, uintptr_t delta)
174 {
175   return __atomic_add_fetch (val, delta, __ATOMIC_SEQ_CST);
176 }
177 
178 int32_t LoadInt32 (int32_t *addr)
179   __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt32")
180   __attribute__ ((no_split_stack));
181 
182 int32_t
LoadInt32(int32_t * addr)183 LoadInt32 (int32_t *addr)
184 {
185   return __atomic_load_n (addr, __ATOMIC_SEQ_CST);
186 }
187 
188 int64_t LoadInt64 (int64_t *addr)
189   __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt64")
190   __attribute__ ((no_split_stack));
191 
192 int64_t
LoadInt64(int64_t * addr)193 LoadInt64 (int64_t *addr)
194 {
195   if (((uintptr_t) addr & 7) != 0)
196     panicmem ();
197   return __atomic_load_n (addr, __ATOMIC_SEQ_CST);
198 }
199 
200 uint32_t LoadUint32 (uint32_t *addr)
201   __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint32")
202   __attribute__ ((no_split_stack));
203 
204 uint32_t
LoadUint32(uint32_t * addr)205 LoadUint32 (uint32_t *addr)
206 {
207   return __atomic_load_n (addr, __ATOMIC_SEQ_CST);
208 }
209 
210 uint64_t LoadUint64 (uint64_t *addr)
211   __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint64")
212   __attribute__ ((no_split_stack));
213 
214 uint64_t
LoadUint64(uint64_t * addr)215 LoadUint64 (uint64_t *addr)
216 {
217   if (((uintptr_t) addr & 7) != 0)
218     panicmem ();
219   return __atomic_load_n (addr, __ATOMIC_SEQ_CST);
220 }
221 
222 uintptr_t LoadUintptr (uintptr_t *addr)
223   __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUintptr")
224   __attribute__ ((no_split_stack));
225 
226 uintptr_t
LoadUintptr(uintptr_t * addr)227 LoadUintptr (uintptr_t *addr)
228 {
229   return __atomic_load_n (addr, __ATOMIC_SEQ_CST);
230 }
231 
232 void *LoadPointer (void **addr)
233   __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadPointer")
234   __attribute__ ((no_split_stack));
235 
236 void *
LoadPointer(void ** addr)237 LoadPointer (void **addr)
238 {
239   return __atomic_load_n (addr, __ATOMIC_SEQ_CST);
240 }
241 
242 void StoreInt32 (int32_t *addr, int32_t val)
243   __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreInt32")
244   __attribute__ ((no_split_stack));
245 
246 void
StoreInt32(int32_t * addr,int32_t val)247 StoreInt32 (int32_t *addr, int32_t val)
248 {
249   __atomic_store_n (addr, val, __ATOMIC_SEQ_CST);
250 }
251 
252 void StoreInt64 (int64_t *addr, int64_t val)
253   __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreInt64")
254   __attribute__ ((no_split_stack));
255 
256 void
StoreInt64(int64_t * addr,int64_t val)257 StoreInt64 (int64_t *addr, int64_t val)
258 {
259   if (((uintptr_t) addr & 7) != 0)
260     panicmem ();
261   __atomic_store_n (addr, val, __ATOMIC_SEQ_CST);
262 }
263 
264 void StoreUint32 (uint32_t *addr, uint32_t val)
265   __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUint32")
266   __attribute__ ((no_split_stack));
267 
268 void
StoreUint32(uint32_t * addr,uint32_t val)269 StoreUint32 (uint32_t *addr, uint32_t val)
270 {
271   __atomic_store_n (addr, val, __ATOMIC_SEQ_CST);
272 }
273 
274 void StoreUint64 (uint64_t *addr, uint64_t val)
275   __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUint64")
276   __attribute__ ((no_split_stack));
277 
278 void
StoreUint64(uint64_t * addr,uint64_t val)279 StoreUint64 (uint64_t *addr, uint64_t val)
280 {
281   if (((uintptr_t) addr & 7) != 0)
282     panicmem ();
283   __atomic_store_n (addr, val, __ATOMIC_SEQ_CST);
284 }
285 
286 void StoreUintptr (uintptr_t *addr, uintptr_t val)
287   __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUintptr")
288   __attribute__ ((no_split_stack));
289 
290 void
StoreUintptr(uintptr_t * addr,uintptr_t val)291 StoreUintptr (uintptr_t *addr, uintptr_t val)
292 {
293   __atomic_store_n (addr, val, __ATOMIC_SEQ_CST);
294 }
295