github.com/primecitizens/pcz/std@v0.2.1/core/atomic/atomic_mipsx.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2016 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 //go:build mips || mipsle 9 10 package atomic 11 12 import ( 13 "unsafe" 14 15 "github.com/primecitizens/pcz/std/core/cpu" 16 ) 17 18 // TODO implement lock striping 19 var lock struct { 20 state uint32 21 pad [cpu.CacheLinePadSize - 4]byte 22 } 23 24 //go:noescape 25 func spinLock(state *uint32) 26 27 //go:noescape 28 func spinUnlock(state *uint32) 29 30 //go:nosplit 31 func lockAndCheck(addr *uint64) { 32 // ensure 8-byte alignment 33 if uintptr(unsafe.Pointer(addr))&7 != 0 { 34 panicUnaligned() 35 } 36 // force dereference before taking lock 37 _ = *addr 38 39 spinLock(&lock.state) 40 } 41 42 //go:nosplit 43 func unlock() { 44 spinUnlock(&lock.state) 45 } 46 47 //go:nosplit 48 func unlockNoFence() { 49 lock.state = 0 50 } 51 52 // 53 // Store 54 // 55 56 //go:noescape 57 func Store8(ptr *uint8, val uint8) 58 59 //go:noescape 60 func Store32(ptr *uint32, val uint32) 61 62 //go:nosplit 63 func Store64(addr *uint64, val uint64) { 64 lockAndCheck(addr) 65 66 *addr = val 67 68 unlock() 69 return 70 } 71 72 // NO go:noescape annotation; see atomic_pointer.go. 73 func StorePointer(ptr unsafe.Pointer, val unsafe.Pointer) 74 75 // 76 // StoreRel 77 // 78 79 //go:noescape 80 func StoreRel32(ptr *uint32, val uint32) 81 82 //go:noescape 83 func StoreRelUintptr(ptr *uintptr, val uintptr) 84 85 // 86 // Load 87 // 88 89 //go:noescape 90 func Load8(ptr *uint8) uint8 91 92 //go:noescape 93 func Load32(ptr *uint32) uint32 94 95 //go:nosplit 96 func Load64(addr *uint64) (val uint64) { 97 lockAndCheck(addr) 98 99 val = *addr 100 101 unlock() 102 return 103 } 104 105 // NO go:noescape annotation; *ptr escapes if result escapes (#31525) 106 func LoadPointer(ptr unsafe.Pointer) unsafe.Pointer 107 108 // LoadAcq 109 110 //go:noescape 111 func LoadAcq32(ptr *uint32) uint32 112 113 //go:noescape 114 func LoadAcqUintptr(ptr *uintptr) uintptr 115 116 // 117 // Swap 118 // 119 120 //go:noescape 121 func Swap32(ptr *uint32, new uint32) uint32 122 123 //go:nosplit 124 func Swap64(addr *uint64, new uint64) (old uint64) { 125 lockAndCheck(addr) 126 127 old = *addr 128 *addr = new 129 130 unlock() 131 return 132 } 133 134 //go:noescape 135 func SwapUintptr(ptr *uintptr, new uintptr) uintptr 136 137 // 138 // Add 139 // 140 141 //go:noescape 142 func Add32(ptr *uint32, delta int32) uint32 143 144 //go:nosplit 145 func Add64(addr *uint64, delta int64) (new uint64) { 146 lockAndCheck(addr) 147 148 new = *addr + uint64(delta) 149 *addr = new 150 151 unlock() 152 return 153 } 154 155 //go:noescape 156 func AddUintptr(ptr *uintptr, delta uintptr) uintptr 157 158 // 159 // Compare and swap 160 // 161 162 //go:nosplit 163 func Cas64(addr *uint64, old, new uint64) (swapped bool) { 164 lockAndCheck(addr) 165 166 if (*addr) == old { 167 *addr = new 168 unlock() 169 return true 170 } 171 172 unlockNoFence() 173 return false 174 } 175 176 // 177 // bitwise 178 // 179 180 //go:noescape 181 func And8(ptr *uint8, val uint8) 182 183 //go:noescape 184 func And32(ptr *uint32, val uint32) 185 186 //go:noescape 187 func Or8(ptr *uint8, val uint8) 188 189 //go:noescape 190 func Or32(ptr *uint32, val uint32) 191 192 // 193 // CasRel 194 // 195 196 //go:noescape 197 func CasRel32(addr *uint32, old, new uint32) bool