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  //go:noinline
   119  func Xchg64(ptr *uint64, new uint64) uint64 {
   120  	old := *ptr
   121  	*ptr = new
   122  	return old
   123  }
   124  
   125  //go:nosplit
   126  //go:noinline
   127  func Xchgint32(ptr *int32, new int32) int32 {
   128  	old := *ptr
   129  	*ptr = new
   130  	return old
   131  }
   132  
   133  //go:nosplit
   134  //go:noinline
   135  func Xchgint64(ptr *int64, new int64) int64 {
   136  	old := *ptr
   137  	*ptr = new
   138  	return old
   139  }
   140  
   141  //go:nosplit
   142  //go:noinline
   143  func Xchguintptr(ptr *uintptr, new uintptr) uintptr {
   144  	old := *ptr
   145  	*ptr = new
   146  	return old
   147  }
   148  
   149  //go:nosplit
   150  //go:noinline
   151  func And8(ptr *uint8, val uint8) {
   152  	*ptr = *ptr & val
   153  }
   154  
   155  //go:nosplit
   156  //go:noinline
   157  func Or8(ptr *uint8, val uint8) {
   158  	*ptr = *ptr | val
   159  }
   160  
   161  // NOTE: Do not add atomicxor8 (XOR is not idempotent).
   162  
   163  //go:nosplit
   164  //go:noinline
   165  func And(ptr *uint32, val uint32) {
   166  	*ptr = *ptr & val
   167  }
   168  
   169  //go:nosplit
   170  //go:noinline
   171  func Or(ptr *uint32, val uint32) {
   172  	*ptr = *ptr | val
   173  }
   174  
   175  //go:nosplit
   176  //go:noinline
   177  func Cas64(ptr *uint64, old, new uint64) bool {
   178  	if *ptr == old {
   179  		*ptr = new
   180  		return true
   181  	}
   182  	return false
   183  }
   184  
   185  //go:nosplit
   186  //go:noinline
   187  func Store(ptr *uint32, val uint32) {
   188  	*ptr = val
   189  }
   190  
   191  //go:nosplit
   192  //go:noinline
   193  func StoreRel(ptr *uint32, val uint32) {
   194  	*ptr = val
   195  }
   196  
   197  //go:nosplit
   198  //go:noinline
   199  func StoreRel64(ptr *uint64, val uint64) {
   200  	*ptr = val
   201  }
   202  
   203  //go:nosplit
   204  //go:noinline
   205  func StoreReluintptr(ptr *uintptr, val uintptr) {
   206  	*ptr = val
   207  }
   208  
   209  //go:nosplit
   210  //go:noinline
   211  func Store8(ptr *uint8, val uint8) {
   212  	*ptr = val
   213  }
   214  
   215  //go:nosplit
   216  //go:noinline
   217  func Store64(ptr *uint64, val uint64) {
   218  	*ptr = val
   219  }
   220  
   221  // StorepNoWB performs *ptr = val atomically and without a write
   222  // barrier.
   223  //
   224  // NO go:noescape annotation; see atomic_pointer.go.
   225  func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
   226  
   227  //go:nosplit
   228  //go:noinline
   229  func Casint32(ptr *int32, old, new int32) bool {
   230  	if *ptr == old {
   231  		*ptr = new
   232  		return true
   233  	}
   234  	return false
   235  }
   236  
   237  //go:nosplit
   238  //go:noinline
   239  func Casint64(ptr *int64, old, new int64) bool {
   240  	if *ptr == old {
   241  		*ptr = new
   242  		return true
   243  	}
   244  	return false
   245  }
   246  
   247  //go:nosplit
   248  //go:noinline
   249  func Cas(ptr *uint32, old, new uint32) bool {
   250  	if *ptr == old {
   251  		*ptr = new
   252  		return true
   253  	}
   254  	return false
   255  }
   256  
   257  //go:nosplit
   258  //go:noinline
   259  func Casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
   260  	if *ptr == old {
   261  		*ptr = new
   262  		return true
   263  	}
   264  	return false
   265  }
   266  
   267  //go:nosplit
   268  //go:noinline
   269  func Casuintptr(ptr *uintptr, old, new uintptr) bool {
   270  	if *ptr == old {
   271  		*ptr = new
   272  		return true
   273  	}
   274  	return false
   275  }
   276  
   277  //go:nosplit
   278  //go:noinline
   279  func CasRel(ptr *uint32, old, new uint32) bool {
   280  	if *ptr == old {
   281  		*ptr = new
   282  		return true
   283  	}
   284  	return false
   285  }
   286  
   287  //go:nosplit
   288  //go:noinline
   289  func Storeint32(ptr *int32, new int32) {
   290  	*ptr = new
   291  }
   292  
   293  //go:nosplit
   294  //go:noinline
   295  func Storeint64(ptr *int64, new int64) {
   296  	*ptr = new
   297  }
   298  
   299  //go:nosplit
   300  //go:noinline
   301  func Storeuintptr(ptr *uintptr, new uintptr) {
   302  	*ptr = new
   303  }
   304  
   305  //go:nosplit
   306  //go:noinline
   307  func Loaduintptr(ptr *uintptr) uintptr {
   308  	return *ptr
   309  }
   310  
   311  //go:nosplit
   312  //go:noinline
   313  func Loaduint(ptr *uint) uint {
   314  	return *ptr
   315  }
   316  
   317  //go:nosplit
   318  //go:noinline
   319  func Loadint32(ptr *int32) int32 {
   320  	return *ptr
   321  }
   322  
   323  //go:nosplit
   324  //go:noinline
   325  func Loadint64(ptr *int64) int64 {
   326  	return *ptr
   327  }
   328  
   329  //go:nosplit
   330  //go:noinline
   331  func Xaddint32(ptr *int32, delta int32) int32 {
   332  	new := *ptr + delta
   333  	*ptr = new
   334  	return new
   335  }
   336  
   337  //go:nosplit
   338  //go:noinline
   339  func Xaddint64(ptr *int64, delta int64) int64 {
   340  	new := *ptr + delta
   341  	*ptr = new
   342  	return new
   343  }
   344  

View as plain text