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 Xchguintptr(addr *uintptr, v uintptr) uintptr {
82 return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
83 }
84
85
86 func StorepNoWB(addr unsafe.Pointer, v unsafe.Pointer)
87
88
89 func Store(addr *uint32, v uint32)
90
91
92 func StoreRel(addr *uint32, v uint32)
93
94
95 func StoreReluintptr(addr *uintptr, v uintptr)
96
97
98 func goCas64(addr *uint64, old, new uint64) bool {
99 if uintptr(unsafe.Pointer(addr))&7 != 0 {
100 *(*int)(nil) = 0
101 }
102 _ = *addr
103 var ok bool
104 addrLock(addr).lock()
105 if *addr == old {
106 *addr = new
107 ok = true
108 }
109 addrLock(addr).unlock()
110 return ok
111 }
112
113
114 func goXadd64(addr *uint64, delta int64) uint64 {
115 if uintptr(unsafe.Pointer(addr))&7 != 0 {
116 *(*int)(nil) = 0
117 }
118 _ = *addr
119 var r uint64
120 addrLock(addr).lock()
121 r = *addr + uint64(delta)
122 *addr = r
123 addrLock(addr).unlock()
124 return r
125 }
126
127
128 func goXchg64(addr *uint64, v uint64) uint64 {
129 if uintptr(unsafe.Pointer(addr))&7 != 0 {
130 *(*int)(nil) = 0
131 }
132 _ = *addr
133 var r uint64
134 addrLock(addr).lock()
135 r = *addr
136 *addr = v
137 addrLock(addr).unlock()
138 return r
139 }
140
141
142 func goLoad64(addr *uint64) uint64 {
143 if uintptr(unsafe.Pointer(addr))&7 != 0 {
144 *(*int)(nil) = 0
145 }
146 _ = *addr
147 var r uint64
148 addrLock(addr).lock()
149 r = *addr
150 addrLock(addr).unlock()
151 return r
152 }
153
154
155 func goStore64(addr *uint64, v uint64) {
156 if uintptr(unsafe.Pointer(addr))&7 != 0 {
157 *(*int)(nil) = 0
158 }
159 _ = *addr
160 addrLock(addr).lock()
161 *addr = v
162 addrLock(addr).unlock()
163 }
164
165
166 func Or8(addr *uint8, v uint8)
167
168
169 func goOr8(addr *uint8, v uint8) {
170
171 addr32 := (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(addr)) &^ 3))
172 word := uint32(v) << ((uintptr(unsafe.Pointer(addr)) & 3) * 8)
173 for {
174 old := *addr32
175 if Cas(addr32, old, old|word) {
176 return
177 }
178 }
179 }
180
181
182 func And8(addr *uint8, v uint8)
183
184
185 func goAnd8(addr *uint8, v uint8) {
186
187 addr32 := (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(addr)) &^ 3))
188 word := uint32(v) << ((uintptr(unsafe.Pointer(addr)) & 3) * 8)
189 mask := uint32(0xFF) << ((uintptr(unsafe.Pointer(addr)) & 3) * 8)
190 word |= ^mask
191 for {
192 old := *addr32
193 if Cas(addr32, old, old&word) {
194 return
195 }
196 }
197 }
198
199
200 func Or(addr *uint32, v uint32) {
201 for {
202 old := *addr
203 if Cas(addr, old, old|v) {
204 return
205 }
206 }
207 }
208
209
210 func And(addr *uint32, v uint32) {
211 for {
212 old := *addr
213 if Cas(addr, old, old&v) {
214 return
215 }
216 }
217 }
218
219
220 func armcas(ptr *uint32, old, new uint32) bool
221
222
223 func Load(addr *uint32) uint32
224
225
226 func Loadp(addr unsafe.Pointer) unsafe.Pointer
227
228
229 func Load8(addr *uint8) uint8
230
231
232 func LoadAcq(addr *uint32) uint32
233
234
235 func LoadAcquintptr(ptr *uintptr) uintptr
236
237
238 func Cas64(addr *uint64, old, new uint64) bool
239
240
241 func CasRel(addr *uint32, old, new uint32) bool
242
243
244 func Xadd64(addr *uint64, delta int64) uint64
245
246
247 func Xchg64(addr *uint64, v uint64) uint64
248
249
250 func Load64(addr *uint64) uint64
251
252
253 func Store8(addr *uint8, v uint8)
254
255
256 func Store64(addr *uint64, v uint64)
257
View as plain text