github.com/noisysockets/netstack@v0.6.0/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/noisysockets/netstack/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)