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 }