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