github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/atomicbitops/aligned_64bit.go (about)

     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  	"github.com/sagernet/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  }