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