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

View as plain text