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