aligned_64bit.go raw

   1  // Copyright 2021 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  // Int64 is an atomic int64 that is guaranteed to be 64-bit
  27  // aligned, even on 32-bit systems. On most architectures, it's just a regular
  28  // int64.
  29  //
  30  // The default value is zero.
  31  //
  32  // Don't add fields to this struct. It is important that it remain the same
  33  // size as its builtin analogue.
  34  //
  35  // See aligned_32bit_unsafe.go in this directory for justification.
  36  //
  37  // +stateify savable
  38  type Int64 struct {
  39  	_     sync.NoCopy
  40  	value int64
  41  }
  42  
  43  // FromInt64 returns an Int64 initialized to value v.
  44  //
  45  //go:nosplit
  46  func FromInt64(v int64) Int64 {
  47  	return Int64{value: v}
  48  }
  49  
  50  // Load is analogous to atomic.LoadInt64.
  51  //
  52  //go:nosplit
  53  func (i *Int64) Load() int64 {
  54  	return atomic.LoadInt64(&i.value)
  55  }
  56  
  57  // RacyLoad is analogous to reading an atomic value without using
  58  // synchronization.
  59  //
  60  // It may be helpful to document why a racy operation is permitted.
  61  //
  62  //go:nosplit
  63  func (i *Int64) RacyLoad() int64 {
  64  	return i.value
  65  }
  66  
  67  // Store is analogous to atomic.StoreInt64.
  68  //
  69  //go:nosplit
  70  func (i *Int64) Store(v int64) {
  71  	atomic.StoreInt64(&i.value, v)
  72  }
  73  
  74  // RacyStore is analogous to setting an atomic value without using
  75  // synchronization.
  76  //
  77  // It may be helpful to document why a racy operation is permitted.
  78  //
  79  //go:nosplit
  80  func (i *Int64) RacyStore(v int64) {
  81  	i.value = v
  82  }
  83  
  84  // Add is analogous to atomic.AddInt64.
  85  //
  86  //go:nosplit
  87  func (i *Int64) Add(v int64) int64 {
  88  	return atomic.AddInt64(&i.value, v)
  89  }
  90  
  91  // RacyAdd is analogous to adding to an atomic value without using
  92  // synchronization.
  93  //
  94  // It may be helpful to document why a racy operation is permitted.
  95  //
  96  //go:nosplit
  97  func (i *Int64) RacyAdd(v int64) int64 {
  98  	i.value += v
  99  	return i.value
 100  }
 101  
 102  // Swap is analogous to atomic.SwapInt64.
 103  //
 104  //go:nosplit
 105  func (i *Int64) Swap(v int64) int64 {
 106  	return atomic.SwapInt64(&i.value, v)
 107  }
 108  
 109  // CompareAndSwap is analogous to atomic.CompareAndSwapInt64.
 110  //
 111  //go:nosplit
 112  func (i *Int64) CompareAndSwap(oldVal, newVal int64) bool {
 113  	return atomic.CompareAndSwapInt64(&i.value, oldVal, newVal)
 114  }
 115  
 116  //go:nosplit
 117  func (i *Int64) ptr() *int64 {
 118  	return &i.value
 119  }
 120  
 121  // Uint64 is an atomic uint64 that is guaranteed to be 64-bit
 122  // aligned, even on 32-bit systems. On most architectures, it's just a regular
 123  // uint64.
 124  //
 125  // Don't add fields to this struct. It is important that it remain the same
 126  // size as its builtin analogue.
 127  //
 128  // See aligned_unsafe.go in this directory for justification.
 129  //
 130  // +stateify savable
 131  type Uint64 struct {
 132  	_     sync.NoCopy
 133  	value uint64
 134  }
 135  
 136  // FromUint64 returns an Uint64 initialized to value v.
 137  //
 138  //go:nosplit
 139  func FromUint64(v uint64) Uint64 {
 140  	return Uint64{value: v}
 141  }
 142  
 143  // Load is analogous to atomic.LoadUint64.
 144  //
 145  //go:nosplit
 146  func (u *Uint64) Load() uint64 {
 147  	return atomic.LoadUint64(&u.value)
 148  }
 149  
 150  // RacyLoad is analogous to reading an atomic value without using
 151  // synchronization.
 152  //
 153  // It may be helpful to document why a racy operation is permitted.
 154  //
 155  //go:nosplit
 156  func (u *Uint64) RacyLoad() uint64 {
 157  	return u.value
 158  }
 159  
 160  // Store is analogous to atomic.StoreUint64.
 161  //
 162  //go:nosplit
 163  func (u *Uint64) Store(v uint64) {
 164  	atomic.StoreUint64(&u.value, v)
 165  }
 166  
 167  // RacyStore is analogous to setting an atomic value without using
 168  // synchronization.
 169  //
 170  // It may be helpful to document why a racy operation is permitted.
 171  //
 172  //go:nosplit
 173  func (u *Uint64) RacyStore(v uint64) {
 174  	u.value = v
 175  }
 176  
 177  // Add is analogous to atomic.AddUint64.
 178  //
 179  //go:nosplit
 180  func (u *Uint64) Add(v uint64) uint64 {
 181  	return atomic.AddUint64(&u.value, v)
 182  }
 183  
 184  // RacyAdd is analogous to adding to an atomic value without using
 185  // synchronization.
 186  //
 187  // It may be helpful to document why a racy operation is permitted.
 188  //
 189  //go:nosplit
 190  func (u *Uint64) RacyAdd(v uint64) uint64 {
 191  	u.value += v
 192  	return u.value
 193  }
 194  
 195  // Swap is analogous to atomic.SwapUint64.
 196  //
 197  //go:nosplit
 198  func (u *Uint64) Swap(v uint64) uint64 {
 199  	return atomic.SwapUint64(&u.value, v)
 200  }
 201  
 202  // CompareAndSwap is analogous to atomic.CompareAndSwapUint64.
 203  //
 204  //go:nosplit
 205  func (u *Uint64) CompareAndSwap(oldVal, newVal uint64) bool {
 206  	return atomic.CompareAndSwapUint64(&u.value, oldVal, newVal)
 207  }
 208  
 209  //go:nosplit
 210  func (u *Uint64) ptr() *uint64 {
 211  	return &u.value
 212  }
 213