1
2
3
4
5
6
7 package atomic
8
9 import (
10 "internal/cpu"
11 "unsafe"
12 )
13
14 const (
15 offsetARMHasV7Atomics = unsafe.Offsetof(cpu.ARM.HasV7Atomics)
16 )
17
18
19
20
21
22
23
24 type spinlock struct {
25 v uint32
26 }
27
28
29 func (l *spinlock) lock() {
30 for {
31 if Cas(&l.v, 0, 1) {
32 return
33 }
34 }
35 }
36
37
38 func (l *spinlock) unlock() {
39 Store(&l.v, 0)
40 }
41
42 var locktab [57]struct {
43 l spinlock
44 pad [cpu.CacheLinePadSize - unsafe.Sizeof(spinlock{})]byte
45 }
46
47 func addrLock(addr *uint64) *spinlock {
48 return &locktab[(uintptr(unsafe.Pointer(addr))>>3)%uintptr(len(locktab))].l
49 }
50
51
52
53
54 func Xadd(val *uint32, delta int32) uint32 {
55 for {
56 oval := *val
57 nval := oval + uint32(delta)
58 if Cas(val, oval, nval) {
59 return nval
60 }
61 }
62 }
63
64
65 func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
66
67
68 func Xchg(addr *uint32, v uint32) uint32 {
69 for {
70 old := *addr
71 if Cas(addr, old, v) {
72 return old
73 }
74 }
75 }
76
77
78 func Xchg8(addr *uint8, v uint8) uint8
79
80
81 func goXchg8(addr *uint8, v uint8) uint8 {
82
83 addr32 := (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(addr)) &^ 3))
84 shift := (uintptr(unsafe.Pointer(addr)) & 3) * 8
85 word := uint32(v) << shift
86 mask := uint32(0xFF) << shift
87
88 for {
89 old := *addr32
90
91 if Cas(addr32, old, (old&^mask)|word) {
92
93 return uint8((old & mask) >> shift)
94 }
95 }
96 }
97
98
99 func Xchguintptr(addr *uintptr, v uintptr) uintptr {
100 return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
101 }
102
103
104 func StorepNoWB(addr unsafe.Pointer, v unsafe.Pointer)
105
106
107 func Store(addr *uint32, v uint32)
108
109
110 func StoreRel(addr *uint32, v uint32)
111
112
113 func StoreReluintptr(addr *uintptr, v uintptr)
114
115
116 func goCas64(addr *uint64, old, new uint64) bool {
117 if uintptr(unsafe.Pointer(addr))&7 != 0 {
118 *(*int)(nil) = 0
119 }
120 _ = *addr
121 var ok bool
122 addrLock(addr).lock()
123 if *addr == old {
124 *addr = new
125 ok = true
126 }
127 addrLock(addr).unlock()
128 return ok
129 }
130
131
132 func goXadd64(addr *uint64, delta int64) uint64 {
133 if uintptr(unsafe.Pointer(addr))&7 != 0 {
134 *(*int)(nil) = 0
135 }
136 _ = *addr
137 var r uint64
138 addrLock(addr).lock()
139 r = *addr + uint64(delta)
140 *addr = r
141 addrLock(addr).unlock()
142 return r
143 }
144
145
146 func goXchg64(addr *uint64, v uint64) uint64 {
147 if uintptr(unsafe.Pointer(addr))&7 != 0 {
148 *(*int)(nil) = 0
149 }
150 _ = *addr
151 var r uint64
152 addrLock(addr).lock()
153 r = *addr
154 *addr = v
155 addrLock(addr).unlock()
156 return r
157 }
158
159
160 func goLoad64(addr *uint64) uint64 {
161 if uintptr(unsafe.Pointer(addr))&7 != 0 {
162 *(*int)(nil) = 0
163 }
164 _ = *addr
165 var r uint64
166 addrLock(addr).lock()
167 r = *addr
168 addrLock(addr).unlock()
169 return r
170 }
171
172
173 func goStore64(addr *uint64, v uint64) {
174 if uintptr(unsafe.Pointer(addr))&7 != 0 {
175 *(*int)(nil) = 0
176 }
177 _ = *addr
178 addrLock(addr).lock()
179 *addr = v
180 addrLock(addr).unlock()
181 }
182
183
184 func Or8(addr *uint8, v uint8)
185
186
187 func goOr8(addr *uint8, v uint8) {
188
189 addr32 := (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(addr)) &^ 3))
190 word := uint32(v) << ((uintptr(unsafe.Pointer(addr)) & 3) * 8)
191 for {
192 old := *addr32
193 if Cas(addr32, old, old|word) {
194 return
195 }
196 }
197 }
198
199
200 func And8(addr *uint8, v uint8)
201
202
203 func goAnd8(addr *uint8, v uint8) {
204
205 addr32 := (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(addr)) &^ 3))
206 word := uint32(v) << ((uintptr(unsafe.Pointer(addr)) & 3) * 8)
207 mask := uint32(0xFF) << ((uintptr(unsafe.Pointer(addr)) & 3) * 8)
208 word |= ^mask
209 for {
210 old := *addr32
211 if Cas(addr32, old, old&word) {
212 return
213 }
214 }
215 }
216
217
218 func Or(addr *uint32, v uint32) {
219 for {
220 old := *addr
221 if Cas(addr, old, old|v) {
222 return
223 }
224 }
225 }
226
227
228 func And(addr *uint32, v uint32) {
229 for {
230 old := *addr
231 if Cas(addr, old, old&v) {
232 return
233 }
234 }
235 }
236
237
238 func armcas(ptr *uint32, old, new uint32) bool
239
240
241 func Load(addr *uint32) uint32
242
243
244 func Loadp(addr unsafe.Pointer) unsafe.Pointer
245
246
247 func Load8(addr *uint8) uint8
248
249
250 func LoadAcq(addr *uint32) uint32
251
252
253 func LoadAcquintptr(ptr *uintptr) uintptr
254
255
256 func Cas64(addr *uint64, old, new uint64) bool
257
258
259 func CasRel(addr *uint32, old, new uint32) bool
260
261
262 func Xadd64(addr *uint64, delta int64) uint64
263
264
265 func Xchg64(addr *uint64, v uint64) uint64
266
267
268 func Load64(addr *uint64) uint64
269
270
271 func Store8(addr *uint8, v uint8)
272
273
274 func Store64(addr *uint64, v uint64)
275
View as plain text