...
Source file src/runtime/internal/atomic/atomic_arm.go
1
2
3
4
5
6
7 package atomic
8
9 import (
10 "internal/cpu"
11 "unsafe"
12 )
13
14
15
16
17
18 type spinlock struct {
19 v uint32
20 }
21
22
23 func (l *spinlock) lock() {
24 for {
25 if Cas(&l.v, 0, 1) {
26 return
27 }
28 }
29 }
30
31
32 func (l *spinlock) unlock() {
33 Store(&l.v, 0)
34 }
35
36 var locktab [57]struct {
37 l spinlock
38 pad [cpu.CacheLinePadSize - unsafe.Sizeof(spinlock{})]byte
39 }
40
41 func addrLock(addr *uint64) *spinlock {
42 return &locktab[(uintptr(unsafe.Pointer(addr))>>3)%uintptr(len(locktab))].l
43 }
44
45
46
47 func Xadd(val *uint32, delta int32) uint32 {
48 for {
49 oval := *val
50 nval := oval + uint32(delta)
51 if Cas(val, oval, nval) {
52 return nval
53 }
54 }
55 }
56
57
58 func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
59
60
61 func Xchg(addr *uint32, v uint32) uint32 {
62 for {
63 old := *addr
64 if Cas(addr, old, v) {
65 return old
66 }
67 }
68 }
69
70
71 func Xchguintptr(addr *uintptr, v uintptr) uintptr {
72 return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
73 }
74
75
76 func StorepNoWB(addr unsafe.Pointer, v unsafe.Pointer)
77
78
79 func Store(addr *uint32, v uint32)
80
81
82 func StoreRel(addr *uint32, v uint32)
83
84
85 func goCas64(addr *uint64, old, new uint64) bool {
86 if uintptr(unsafe.Pointer(addr))&7 != 0 {
87 *(*int)(nil) = 0
88 }
89 _ = *addr
90 var ok bool
91 addrLock(addr).lock()
92 if *addr == old {
93 *addr = new
94 ok = true
95 }
96 addrLock(addr).unlock()
97 return ok
98 }
99
100
101 func goXadd64(addr *uint64, delta int64) uint64 {
102 if uintptr(unsafe.Pointer(addr))&7 != 0 {
103 *(*int)(nil) = 0
104 }
105 _ = *addr
106 var r uint64
107 addrLock(addr).lock()
108 r = *addr + uint64(delta)
109 *addr = r
110 addrLock(addr).unlock()
111 return r
112 }
113
114
115 func goXchg64(addr *uint64, v uint64) uint64 {
116 if uintptr(unsafe.Pointer(addr))&7 != 0 {
117 *(*int)(nil) = 0
118 }
119 _ = *addr
120 var r uint64
121 addrLock(addr).lock()
122 r = *addr
123 *addr = v
124 addrLock(addr).unlock()
125 return r
126 }
127
128
129 func goLoad64(addr *uint64) uint64 {
130 if uintptr(unsafe.Pointer(addr))&7 != 0 {
131 *(*int)(nil) = 0
132 }
133 _ = *addr
134 var r uint64
135 addrLock(addr).lock()
136 r = *addr
137 addrLock(addr).unlock()
138 return r
139 }
140
141
142 func goStore64(addr *uint64, v uint64) {
143 if uintptr(unsafe.Pointer(addr))&7 != 0 {
144 *(*int)(nil) = 0
145 }
146 _ = *addr
147 addrLock(addr).lock()
148 *addr = v
149 addrLock(addr).unlock()
150 }
151
152
153 func Or8(addr *uint8, v uint8) {
154
155 uaddr := uintptr(unsafe.Pointer(addr))
156 addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
157 word := uint32(v) << ((uaddr & 3) * 8)
158 for {
159 old := *addr32
160 if Cas(addr32, old, old|word) {
161 return
162 }
163 }
164 }
165
166
167 func And8(addr *uint8, v uint8) {
168
169 uaddr := uintptr(unsafe.Pointer(addr))
170 addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
171 word := uint32(v) << ((uaddr & 3) * 8)
172 mask := uint32(0xFF) << ((uaddr & 3) * 8)
173 word |= ^mask
174 for {
175 old := *addr32
176 if Cas(addr32, old, old&word) {
177 return
178 }
179 }
180 }
181
182
183 func armcas(ptr *uint32, old, new uint32) bool
184
185
186 func Load(addr *uint32) uint32
187
188
189 func Loadp(addr unsafe.Pointer) unsafe.Pointer
190
191
192 func Load8(addr *uint8) uint8
193
194
195 func LoadAcq(addr *uint32) uint32
196
197
198 func Cas64(addr *uint64, old, new uint64) bool
199
200
201 func CasRel(addr *uint32, old, new uint32) bool
202
203
204 func Xadd64(addr *uint64, delta int64) uint64
205
206
207 func Xchg64(addr *uint64, v uint64) uint64
208
209
210 func Load64(addr *uint64) uint64
211
212
213 func Store64(addr *uint64, v uint64)
214
View as plain text