Source file src/internal/runtime/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 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  

View as plain text