github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/atomicbitops/32b_32bit.go (about) 1 // Copyright 2022 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build arm || mips || mipsle || 386 16 // +build arm mips mipsle 386 17 18 package atomicbitops 19 20 import ( 21 "sync/atomic" 22 23 "github.com/sagernet/gvisor/pkg/sync" 24 ) 25 26 // Note that this file is *identical* to 32b_64bit.go, as go_stateify gets 27 // confused about build tags if these are not separated. 28 29 // LINT.IfChange 30 31 // Int32 is an atomic int32. 32 // 33 // The default value is zero. 34 // 35 // Don't add fields to this struct. It is important that it remain the same 36 // size as its builtin analogue. 37 // 38 // +stateify savable 39 type Int32 struct { 40 _ sync.NoCopy 41 value int32 42 } 43 44 // FromInt32 returns an Int32 initialized to value v. 45 // 46 //go:nosplit 47 func FromInt32(v int32) Int32 { 48 return Int32{value: v} 49 } 50 51 // Load is analogous to atomic.LoadInt32. 52 // 53 //go:nosplit 54 func (i *Int32) Load() int32 { 55 return atomic.LoadInt32(&i.value) 56 } 57 58 // RacyLoad is analogous to reading an atomic value without using 59 // synchronization. 60 // 61 // It may be helpful to document why a racy operation is permitted. 62 // 63 //go:nosplit 64 func (i *Int32) RacyLoad() int32 { 65 return i.value 66 } 67 68 // Store is analogous to atomic.StoreInt32. 69 // 70 //go:nosplit 71 func (i *Int32) Store(v int32) { 72 atomic.StoreInt32(&i.value, v) 73 } 74 75 // RacyStore is analogous to setting an atomic value without using 76 // synchronization. 77 // 78 // It may be helpful to document why a racy operation is permitted. 79 // 80 //go:nosplit 81 func (i *Int32) RacyStore(v int32) { 82 i.value = v 83 } 84 85 // Add is analogous to atomic.AddInt32. 86 // 87 //go:nosplit 88 func (i *Int32) Add(v int32) int32 { 89 return atomic.AddInt32(&i.value, v) 90 } 91 92 // RacyAdd is analogous to adding to an atomic value without using 93 // synchronization. 94 // 95 // It may be helpful to document why a racy operation is permitted. 96 // 97 //go:nosplit 98 func (i *Int32) RacyAdd(v int32) int32 { 99 i.value += v 100 return i.value 101 } 102 103 // Swap is analogous to atomic.SwapInt32. 104 // 105 //go:nosplit 106 func (i *Int32) Swap(v int32) int32 { 107 return atomic.SwapInt32(&i.value, v) 108 } 109 110 // CompareAndSwap is analogous to atomic.CompareAndSwapInt32. 111 // 112 //go:nosplit 113 func (i *Int32) CompareAndSwap(oldVal, newVal int32) bool { 114 return atomic.CompareAndSwapInt32(&i.value, oldVal, newVal) 115 } 116 117 //go:nosplit 118 func (i *Int32) ptr() *int32 { 119 return &i.value 120 } 121 122 // Uint32 is an atomic uint32. 123 // 124 // Don't add fields to this struct. It is important that it remain the same 125 // size as its builtin analogue. 126 // 127 // See aligned_unsafe.go in this directory for justification. 128 // 129 // +stateify savable 130 type Uint32 struct { 131 _ sync.NoCopy 132 value uint32 133 } 134 135 // FromUint32 returns an Uint32 initialized to value v. 136 // 137 //go:nosplit 138 func FromUint32(v uint32) Uint32 { 139 return Uint32{value: v} 140 } 141 142 // Load is analogous to atomic.LoadUint32. 143 // 144 //go:nosplit 145 func (u *Uint32) Load() uint32 { 146 return atomic.LoadUint32(&u.value) 147 } 148 149 // RacyLoad is analogous to reading an atomic value without using 150 // synchronization. 151 // 152 // It may be helpful to document why a racy operation is permitted. 153 // 154 //go:nosplit 155 func (u *Uint32) RacyLoad() uint32 { 156 return u.value 157 } 158 159 // Store is analogous to atomic.StoreUint32. 160 // 161 //go:nosplit 162 func (u *Uint32) Store(v uint32) { 163 atomic.StoreUint32(&u.value, v) 164 } 165 166 // RacyStore is analogous to setting an atomic value without using 167 // synchronization. 168 // 169 // It may be helpful to document why a racy operation is permitted. 170 // 171 //go:nosplit 172 func (u *Uint32) RacyStore(v uint32) { 173 u.value = v 174 } 175 176 // Add is analogous to atomic.AddUint32. 177 // 178 //go:nosplit 179 func (u *Uint32) Add(v uint32) uint32 { 180 return atomic.AddUint32(&u.value, v) 181 } 182 183 // RacyAdd is analogous to adding to an atomic value without using 184 // synchronization. 185 // 186 // It may be helpful to document why a racy operation is permitted. 187 // 188 //go:nosplit 189 func (u *Uint32) RacyAdd(v uint32) uint32 { 190 u.value += v 191 return u.value 192 } 193 194 // Swap is analogous to atomic.SwapUint32. 195 // 196 //go:nosplit 197 func (u *Uint32) Swap(v uint32) uint32 { 198 return atomic.SwapUint32(&u.value, v) 199 } 200 201 // CompareAndSwap is analogous to atomic.CompareAndSwapUint32. 202 // 203 //go:nosplit 204 func (u *Uint32) CompareAndSwap(oldVal, newVal uint32) bool { 205 return atomic.CompareAndSwapUint32(&u.value, oldVal, newVal) 206 } 207 208 //go:nosplit 209 func (u *Uint32) ptr() *uint32 { 210 return &u.value 211 } 212 213 // Bool is an atomic Boolean. 214 // 215 // It is implemented by a Uint32, with value 0 indicating false, and 1 216 // indicating true. 217 // 218 // +stateify savable 219 type Bool struct { 220 Uint32 221 } 222 223 // b32 returns a uint32 0 or 1 representing b. 224 func b32(b bool) uint32 { 225 if b { 226 return 1 227 } 228 return 0 229 } 230 231 // FromBool returns a Bool initialized to value val. 232 // 233 //go:nosplit 234 func FromBool(val bool) Bool { 235 return Bool{ 236 Uint32: FromUint32(b32(val)), 237 } 238 } 239 240 // Load is analogous to atomic.LoadBool, if such a thing existed. 241 // 242 //go:nosplit 243 func (b *Bool) Load() bool { 244 return b.Uint32.Load() != 0 245 } 246 247 // RacyLoad is analogous to reading an atomic value without using 248 // synchronization. 249 // 250 // It may be helpful to document why a racy operation is permitted. 251 // 252 //go:nosplit 253 func (b *Bool) RacyLoad() bool { 254 return b.Uint32.RacyLoad() != 0 255 } 256 257 // Store is analogous to atomic.StoreBool, if such a thing existed. 258 // 259 //go:nosplit 260 func (b *Bool) Store(val bool) { 261 b.Uint32.Store(b32(val)) 262 } 263 264 // RacyStore is analogous to setting an atomic value without using 265 // synchronization. 266 // 267 // It may be helpful to document why a racy operation is permitted. 268 // 269 //go:nosplit 270 func (b *Bool) RacyStore(val bool) { 271 b.Uint32.RacyStore(b32(val)) 272 } 273 274 // Swap is analogous to atomic.SwapBool, if such a thing existed. 275 // 276 //go:nosplit 277 func (b *Bool) Swap(val bool) bool { 278 return b.Uint32.Swap(b32(val)) != 0 279 } 280 281 // CompareAndSwap is analogous to atomic.CompareAndSwapBool, if such a thing 282 // existed. 283 // 284 //go:nosplit 285 func (b *Bool) CompareAndSwap(oldVal, newVal bool) bool { 286 return b.Uint32.CompareAndSwap(b32(oldVal), b32(newVal)) 287 } 288 289 // LINT.ThenChange(32b_64bit.go)