github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/runtime/internal/atomic/atomic_mipsx.go (about)

     1  // Copyright 2016 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  //go:build mips || mipsle
     6  
     7  // Export some functions via linkname to assembly in sync/atomic.
     8  //go:linkname Xadd64
     9  //go:linkname Xchg64
    10  //go:linkname Cas64
    11  //go:linkname Load64
    12  //go:linkname Store64
    13  
    14  package atomic
    15  
    16  import (
    17  	"internal/cpu"
    18  	"unsafe"
    19  )
    20  
    21  // TODO implement lock striping
    22  var lock struct {
    23  	state uint32
    24  	pad   [cpu.CacheLinePadSize - 4]byte
    25  }
    26  
    27  //go:noescape
    28  func spinLock(state *uint32)
    29  
    30  //go:noescape
    31  func spinUnlock(state *uint32)
    32  
    33  //go:nosplit
    34  func lockAndCheck(addr *uint64) {
    35  	// ensure 8-byte alignment
    36  	if uintptr(unsafe.Pointer(addr))&7 != 0 {
    37  		panicUnaligned()
    38  	}
    39  	// force dereference before taking lock
    40  	_ = *addr
    41  
    42  	spinLock(&lock.state)
    43  }
    44  
    45  //go:nosplit
    46  func unlock() {
    47  	spinUnlock(&lock.state)
    48  }
    49  
    50  //go:nosplit
    51  func unlockNoFence() {
    52  	lock.state = 0
    53  }
    54  
    55  //go:nosplit
    56  func Xadd64(addr *uint64, delta int64) (new uint64) {
    57  	lockAndCheck(addr)
    58  
    59  	new = *addr + uint64(delta)
    60  	*addr = new
    61  
    62  	unlock()
    63  	return
    64  }
    65  
    66  //go:nosplit
    67  func Xchg64(addr *uint64, new uint64) (old uint64) {
    68  	lockAndCheck(addr)
    69  
    70  	old = *addr
    71  	*addr = new
    72  
    73  	unlock()
    74  	return
    75  }
    76  
    77  //go:nosplit
    78  func Cas64(addr *uint64, old, new uint64) (swapped bool) {
    79  	lockAndCheck(addr)
    80  
    81  	if (*addr) == old {
    82  		*addr = new
    83  		unlock()
    84  		return true
    85  	}
    86  
    87  	unlockNoFence()
    88  	return false
    89  }
    90  
    91  //go:nosplit
    92  func Load64(addr *uint64) (val uint64) {
    93  	lockAndCheck(addr)
    94  
    95  	val = *addr
    96  
    97  	unlock()
    98  	return
    99  }
   100  
   101  //go:nosplit
   102  func Store64(addr *uint64, val uint64) {
   103  	lockAndCheck(addr)
   104  
   105  	*addr = val
   106  
   107  	unlock()
   108  	return
   109  }
   110  
   111  //go:noescape
   112  func Xadd(ptr *uint32, delta int32) uint32
   113  
   114  //go:noescape
   115  func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
   116  
   117  //go:noescape
   118  func Xchg(ptr *uint32, new uint32) uint32
   119  
   120  //go:noescape
   121  func Xchguintptr(ptr *uintptr, new uintptr) uintptr
   122  
   123  //go:noescape
   124  func Load(ptr *uint32) uint32
   125  
   126  //go:noescape
   127  func Load8(ptr *uint8) uint8
   128  
   129  // NO go:noescape annotation; *ptr escapes if result escapes (#31525)
   130  func Loadp(ptr unsafe.Pointer) unsafe.Pointer
   131  
   132  //go:noescape
   133  func LoadAcq(ptr *uint32) uint32
   134  
   135  //go:noescape
   136  func LoadAcquintptr(ptr *uintptr) uintptr
   137  
   138  //go:noescape
   139  func And8(ptr *uint8, val uint8)
   140  
   141  //go:noescape
   142  func Or8(ptr *uint8, val uint8)
   143  
   144  //go:noescape
   145  func And(ptr *uint32, val uint32)
   146  
   147  //go:noescape
   148  func Or(ptr *uint32, val uint32)
   149  
   150  //go:noescape
   151  func Store(ptr *uint32, val uint32)
   152  
   153  //go:noescape
   154  func Store8(ptr *uint8, val uint8)
   155  
   156  // NO go:noescape annotation; see atomic_pointer.go.
   157  func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
   158  
   159  //go:noescape
   160  func StoreRel(ptr *uint32, val uint32)
   161  
   162  //go:noescape
   163  func StoreReluintptr(ptr *uintptr, val uintptr)
   164  
   165  //go:noescape
   166  func CasRel(addr *uint32, old, new uint32) bool