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