32b_64bit.go raw

   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  	"gvisor.dev/gvisor/pkg/sync"
  24  )
  25  
  26  // Note that this file is *identical* to 32b_32bit.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_32bit.go)
 290