Source file src/runtime/internal/atomic/atomic_wasm.go

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

View as plain text