atomic_wasm.mx raw
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // TODO(neelance): implement with actual atomic operations as soon as threads are available
6 // See https://github.com/WebAssembly/design/issues/1073
7
8 // Export some functions via linkname to assembly in sync/atomic.
9 //
10 //go:linkname Load
11 //go:linkname Loadp
12 //go:linkname Load64
13 //go:linkname Loadint32
14 //go:linkname Loadint64
15 //go:linkname Loaduintptr
16 //go:linkname LoadAcquintptr
17 //go:linkname Xadd
18 //go:linkname Xaddint32
19 //go:linkname Xaddint64
20 //go:linkname Xadd64
21 //go:linkname Xadduintptr
22 //go:linkname Xchg
23 //go:linkname Xchg64
24 //go:linkname Xchgint32
25 //go:linkname Xchgint64
26 //go:linkname Xchguintptr
27 //go:linkname Cas
28 //go:linkname Cas64
29 //go:linkname Casint32
30 //go:linkname Casint64
31 //go:linkname Casuintptr
32 //go:linkname Store
33 //go:linkname Store64
34 //go:linkname Storeint32
35 //go:linkname Storeint64
36 //go:linkname Storeuintptr
37 //go:linkname StoreReluintptr
38
39 package atomic
40
41 import "unsafe"
42
43 //go:nosplit
44 //go:noinline
45 func Load(ptr *uint32) uint32 {
46 return *ptr
47 }
48
49 //go:nosplit
50 //go:noinline
51 func Loadp(ptr unsafe.Pointer) unsafe.Pointer {
52 return *(*unsafe.Pointer)(ptr)
53 }
54
55 //go:nosplit
56 //go:noinline
57 func LoadAcq(ptr *uint32) uint32 {
58 return *ptr
59 }
60
61 //go:nosplit
62 //go:noinline
63 func LoadAcq64(ptr *uint64) uint64 {
64 return *ptr
65 }
66
67 //go:nosplit
68 //go:noinline
69 func LoadAcquintptr(ptr *uintptr) uintptr {
70 return *ptr
71 }
72
73 //go:nosplit
74 //go:noinline
75 func Load8(ptr *uint8) uint8 {
76 return *ptr
77 }
78
79 //go:nosplit
80 //go:noinline
81 func Load64(ptr *uint64) uint64 {
82 return *ptr
83 }
84
85 //go:nosplit
86 //go:noinline
87 func Xadd(ptr *uint32, delta int32) uint32 {
88 new := *ptr + uint32(delta)
89 *ptr = new
90 return new
91 }
92
93 //go:nosplit
94 //go:noinline
95 func Xadd64(ptr *uint64, delta int64) uint64 {
96 new := *ptr + uint64(delta)
97 *ptr = new
98 return new
99 }
100
101 //go:nosplit
102 //go:noinline
103 func Xadduintptr(ptr *uintptr, delta uintptr) uintptr {
104 new := *ptr + delta
105 *ptr = new
106 return new
107 }
108
109 //go:nosplit
110 //go:noinline
111 func Xchg(ptr *uint32, new uint32) uint32 {
112 old := *ptr
113 *ptr = new
114 return old
115 }
116
117 //go:nosplit
118 func Xchg8(addr *uint8, v uint8) uint8 {
119 return goXchg8(addr, v)
120 }
121
122 //go:nosplit
123 //go:noinline
124 func Xchg64(ptr *uint64, new uint64) uint64 {
125 old := *ptr
126 *ptr = new
127 return old
128 }
129
130 //go:nosplit
131 //go:noinline
132 func Xchgint32(ptr *int32, new int32) int32 {
133 old := *ptr
134 *ptr = new
135 return old
136 }
137
138 //go:nosplit
139 //go:noinline
140 func Xchgint64(ptr *int64, new int64) int64 {
141 old := *ptr
142 *ptr = new
143 return old
144 }
145
146 //go:nosplit
147 //go:noinline
148 func Xchguintptr(ptr *uintptr, new uintptr) uintptr {
149 old := *ptr
150 *ptr = new
151 return old
152 }
153
154 //go:nosplit
155 //go:noinline
156 func And8(ptr *uint8, val uint8) {
157 *ptr = *ptr & val
158 }
159
160 //go:nosplit
161 //go:noinline
162 func Or8(ptr *uint8, val uint8) {
163 *ptr = *ptr | val
164 }
165
166 // NOTE: Do not add atomicxor8 (XOR is not idempotent).
167
168 //go:nosplit
169 //go:noinline
170 func And(ptr *uint32, val uint32) {
171 *ptr = *ptr & val
172 }
173
174 //go:nosplit
175 //go:noinline
176 func Or(ptr *uint32, val uint32) {
177 *ptr = *ptr | val
178 }
179
180 //go:nosplit
181 //go:noinline
182 func Cas64(ptr *uint64, old, new uint64) bool {
183 if *ptr == old {
184 *ptr = new
185 return true
186 }
187 return false
188 }
189
190 //go:nosplit
191 //go:noinline
192 func Store(ptr *uint32, val uint32) {
193 *ptr = val
194 }
195
196 //go:nosplit
197 //go:noinline
198 func StoreRel(ptr *uint32, val uint32) {
199 *ptr = val
200 }
201
202 //go:nosplit
203 //go:noinline
204 func StoreRel64(ptr *uint64, val uint64) {
205 *ptr = val
206 }
207
208 //go:nosplit
209 //go:noinline
210 func StoreReluintptr(ptr *uintptr, val uintptr) {
211 *ptr = val
212 }
213
214 //go:nosplit
215 //go:noinline
216 func Store8(ptr *uint8, val uint8) {
217 *ptr = val
218 }
219
220 //go:nosplit
221 //go:noinline
222 func Store64(ptr *uint64, val uint64) {
223 *ptr = val
224 }
225
226 // StorepNoWB performs *ptr = val atomically and without a write
227 // barrier.
228 //
229 // NO go:noescape annotation; see atomic_pointer.go.
230 func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
231
232 //go:nosplit
233 //go:noinline
234 func Casint32(ptr *int32, old, new int32) bool {
235 if *ptr == old {
236 *ptr = new
237 return true
238 }
239 return false
240 }
241
242 //go:nosplit
243 //go:noinline
244 func Casint64(ptr *int64, old, new int64) bool {
245 if *ptr == old {
246 *ptr = new
247 return true
248 }
249 return false
250 }
251
252 //go:nosplit
253 //go:noinline
254 func Cas(ptr *uint32, old, new uint32) bool {
255 if *ptr == old {
256 *ptr = new
257 return true
258 }
259 return false
260 }
261
262 //go:nosplit
263 //go:noinline
264 func Casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
265 if *ptr == old {
266 *ptr = new
267 return true
268 }
269 return false
270 }
271
272 //go:nosplit
273 //go:noinline
274 func Casuintptr(ptr *uintptr, old, new uintptr) bool {
275 if *ptr == old {
276 *ptr = new
277 return true
278 }
279 return false
280 }
281
282 //go:nosplit
283 //go:noinline
284 func CasRel(ptr *uint32, old, new uint32) bool {
285 if *ptr == old {
286 *ptr = new
287 return true
288 }
289 return false
290 }
291
292 //go:nosplit
293 //go:noinline
294 func Storeint32(ptr *int32, new int32) {
295 *ptr = new
296 }
297
298 //go:nosplit
299 //go:noinline
300 func Storeint64(ptr *int64, new int64) {
301 *ptr = new
302 }
303
304 //go:nosplit
305 //go:noinline
306 func Storeuintptr(ptr *uintptr, new uintptr) {
307 *ptr = new
308 }
309
310 //go:nosplit
311 //go:noinline
312 func Loaduintptr(ptr *uintptr) uintptr {
313 return *ptr
314 }
315
316 //go:nosplit
317 //go:noinline
318 func Loaduint(ptr *uint) uint {
319 return *ptr
320 }
321
322 //go:nosplit
323 //go:noinline
324 func Loadint32(ptr *int32) int32 {
325 return *ptr
326 }
327
328 //go:nosplit
329 //go:noinline
330 func Loadint64(ptr *int64) int64 {
331 return *ptr
332 }
333
334 //go:nosplit
335 //go:noinline
336 func Xaddint32(ptr *int32, delta int32) int32 {
337 new := *ptr + delta
338 *ptr = new
339 return new
340 }
341
342 //go:nosplit
343 //go:noinline
344 func Xaddint64(ptr *int64, delta int64) int64 {
345 new := *ptr + delta
346 *ptr = new
347 return new
348 }
349