4
4
@inline UnsafeAtomics. modify! (ptr, op, x) = UnsafeAtomics. modify! (ptr, op, x, seq_cst)
5
5
@inline UnsafeAtomics. fence () = UnsafeAtomics. fence (seq_cst)
6
6
7
+ @inline UnsafeAtomics. load (x, ord) = UnsafeAtomics. load (x, ord, none)
8
+ @inline UnsafeAtomics. store! (x, v, ord) = UnsafeAtomics. store! (x, v, ord, none)
9
+ @inline UnsafeAtomics. cas! (x, cmp, new, ord) = UnsafeAtomics. cas! (x, cmp, new, ord, ord, none)
10
+ @inline UnsafeAtomics. modify! (ptr, op, x, ord) = UnsafeAtomics. modify! (ptr, op, x, ord, none)
11
+ @inline UnsafeAtomics. fence (ord) = UnsafeAtomics. fence (ord, none)
12
+
7
13
# ! format: off
8
14
# https://github.com/JuliaLang/julia/blob/v1.6.3/base/atomics.jl#L23-L30
9
15
if Sys. ARCH == :i686 || startswith (string (Sys. ARCH), " arm" ) ||
@@ -45,8 +51,9 @@ const OP_RMW_TABLE = [
45
51
for (op, rmwop) in OP_RMW_TABLE
46
52
fn = Symbol (rmwop, " !" )
47
53
@eval @inline UnsafeAtomics.$ fn (x, v) = UnsafeAtomics.$ fn (x, v, seq_cst)
48
- @eval @inline UnsafeAtomics.$ fn (ptr, x, ord) =
49
- first (UnsafeAtomics. modify! (ptr, $ op, x, ord))
54
+ @eval @inline UnsafeAtomics.$ fn (x, v, ord) = UnsafeAtomics.$ fn (x, v, ord, none)
55
+ @eval @inline UnsafeAtomics.$ fn (ptr, x, ord, scope) =
56
+ first (UnsafeAtomics. modify! (ptr, $ op, x, ord, scope))
50
57
end
51
58
52
59
const ATOMIC_INTRINSICS = isdefined (Core. Intrinsics, :atomic_pointerref )
@@ -67,47 +74,51 @@ for typ in (inttypes..., floattypes...)
67
74
for ord in orderings
68
75
ord in (release, acq_rel) && continue
69
76
70
- if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE
71
- @eval function UnsafeAtomics. load (x:: Ptr{$typ} , :: $ (typeof (ord)))
72
- return Core. Intrinsics. atomic_pointerref (x, base_ordering ($ ord))
73
- end
74
- else
75
- @eval function UnsafeAtomics. load (x:: Ptr{$typ} , :: $ (typeof (ord)))
76
- return llvmcall (
77
- $ ("""
78
- %ptr = inttoptr i$WORD_SIZE %0 to $lt *
79
- %rv = load atomic $rt %ptr $ord , align $(sizeof (typ))
80
- ret $lt %rv
81
- """ ),
82
- $ typ,
83
- Tuple{Ptr{$ typ}},
84
- x,
85
- )
77
+ for sync in syncscopes
78
+ if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE && sync == none
79
+ @eval function UnsafeAtomics. load (x:: Ptr{$typ} , :: $ (typeof (ord)), :: $ (typeof (sync)))
80
+ return Core. Intrinsics. atomic_pointerref (x, base_ordering ($ ord))
81
+ end
82
+ else
83
+ @eval function UnsafeAtomics. load (x:: Ptr{$typ} , :: $ (typeof (ord)), :: $ (typeof (sync)))
84
+ return llvmcall (
85
+ $ ("""
86
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
87
+ %rv = load atomic $rt %ptr $ord , align $(sizeof (typ))
88
+ ret $lt %rv
89
+ """ ),
90
+ $ typ,
91
+ Tuple{Ptr{$ typ}},
92
+ x,
93
+ )
94
+ end
86
95
end
87
96
end
88
97
end
89
98
90
99
for ord in orderings
91
100
ord in (acquire, acq_rel) && continue
92
-
93
- if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE
94
- @eval function UnsafeAtomics. store! (x:: Ptr{$typ} , v:: $typ , :: $ (typeof (ord)))
95
- Core. Intrinsics. atomic_pointerset (x, v, base_ordering ($ ord))
96
- return nothing
97
- end
98
- else
99
- @eval function UnsafeAtomics. store! (x:: Ptr{$typ} , v:: $typ , :: $ (typeof (ord)))
100
- return llvmcall (
101
- $ ("""
102
- %ptr = inttoptr i$WORD_SIZE %0 to $lt *
103
- store atomic $lt %1, $lt * %ptr $ord , align $(sizeof (typ))
104
- ret void
105
- """ ),
106
- Cvoid,
107
- Tuple{Ptr{$ typ},$ typ},
108
- x,
109
- v,
110
- )
101
+
102
+ for sync in syncscopes
103
+ if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE && sync == none
104
+ @eval function UnsafeAtomics. store! (x:: Ptr{$typ} , v:: $typ , :: $ (typeof (ord)), :: $ (typeof (sync)))
105
+ Core. Intrinsics. atomic_pointerset (x, v, base_ordering ($ ord))
106
+ return nothing
107
+ end
108
+ else
109
+ @eval function UnsafeAtomics. store! (x:: Ptr{$typ} , v:: $typ , :: $ (typeof (ord)), :: $ (typeof (sync)))
110
+ return llvmcall (
111
+ $ ("""
112
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
113
+ store atomic $lt %1, $lt * %ptr $ord , align $(sizeof (typ))
114
+ ret void
115
+ """ ),
116
+ Cvoid,
117
+ Tuple{Ptr{$ typ},$ typ},
118
+ x,
119
+ v,
120
+ )
121
+ end
111
122
end
112
123
end
113
124
end
@@ -117,54 +128,58 @@ for typ in (inttypes..., floattypes...)
117
128
118
129
typ <: AbstractFloat && break
119
130
120
- if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE
121
- @eval function UnsafeAtomics. cas! (
122
- x:: Ptr{$typ} ,
123
- cmp:: $typ ,
124
- new:: $typ ,
125
- :: $ (typeof (success_ordering)),
126
- :: $ (typeof (failure_ordering)),
127
- )
128
- return Core. Intrinsics. atomic_pointerreplace (
129
- x,
130
- cmp,
131
- new,
132
- base_ordering ($ success_ordering),
133
- base_ordering ($ failure_ordering)
131
+ for sync in syncscopes
132
+ if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE && sync == none
133
+ @eval function UnsafeAtomics. cas! (
134
+ x:: Ptr{$typ} ,
135
+ cmp:: $typ ,
136
+ new:: $typ ,
137
+ :: $ (typeof (success_ordering)),
138
+ :: $ (typeof (failure_ordering)),
139
+ :: $ (typeof (sync)),
134
140
)
135
- end
136
- else
137
- @eval function UnsafeAtomics. cas! (
138
- x:: Ptr{$typ} ,
139
- cmp:: $typ ,
140
- new:: $typ ,
141
- :: $ (typeof (success_ordering)),
142
- :: $ (typeof (failure_ordering)),
143
- )
144
- success = Ref {Int8} ()
145
- GC. @preserve success begin
146
- old = llvmcall (
147
- $ (
148
- """
149
- %ptr = inttoptr i$WORD_SIZE %0 to $lt *
150
- %rs = cmpxchg $lt * %ptr, $lt %1, $lt %2 $success_ordering $failure_ordering
151
- %rv = extractvalue { $lt , i1 } %rs, 0
152
- %s1 = extractvalue { $lt , i1 } %rs, 1
153
- %s8 = zext i1 %s1 to i8
154
- %sptr = inttoptr i$WORD_SIZE %3 to i8*
155
- store i8 %s8, i8* %sptr
156
- ret $lt %rv
157
- """
158
- ),
159
- $ typ,
160
- Tuple{Ptr{$ typ},$ typ,$ typ,Ptr{Int8}},
141
+ return Core. Intrinsics. atomic_pointerreplace (
161
142
x,
162
143
cmp,
163
144
new,
164
- Ptr {Int8} (pointer_from_objref (success)),
145
+ base_ordering ($ success_ordering),
146
+ base_ordering ($ failure_ordering)
165
147
)
166
148
end
167
- return (old = old, success = ! iszero (success[]))
149
+ else
150
+ @eval function UnsafeAtomics. cas! (
151
+ x:: Ptr{$typ} ,
152
+ cmp:: $typ ,
153
+ new:: $typ ,
154
+ :: $ (typeof (success_ordering)),
155
+ :: $ (typeof (failure_ordering)),
156
+ :: $ (typeof (sync)),
157
+ )
158
+ success = Ref {Int8} ()
159
+ GC. @preserve success begin
160
+ old = llvmcall (
161
+ $ (
162
+ """
163
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
164
+ %rs = cmpxchg $lt * %ptr, $lt %1, $lt %2 $success_ordering $failure_ordering
165
+ %rv = extractvalue { $lt , i1 } %rs, 0
166
+ %s1 = extractvalue { $lt , i1 } %rs, 1
167
+ %s8 = zext i1 %s1 to i8
168
+ %sptr = inttoptr i$WORD_SIZE %3 to i8*
169
+ store i8 %s8, i8* %sptr
170
+ ret $lt %rv
171
+ """
172
+ ),
173
+ $ typ,
174
+ Tuple{Ptr{$ typ},$ typ,$ typ,Ptr{Int8}},
175
+ x,
176
+ cmp,
177
+ new,
178
+ Ptr {Int8} (pointer_from_objref (success)),
179
+ )
180
+ end
181
+ return (old = old, success = ! iszero (success[]))
182
+ end
168
183
end
169
184
end
170
185
end
@@ -186,60 +201,81 @@ for typ in (inttypes..., floattypes...)
186
201
end
187
202
end
188
203
for ord in orderings
189
- # Enable this code iff https://github.com/JuliaLang/julia/pull/45122 get's merged
190
- if false && ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE
191
- @eval function UnsafeAtomics. modify! (
204
+ for sync in syncscopes
205
+ # Enable this code iff https://github.com/JuliaLang/julia/pull/45122 get's merged
206
+ if false && ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE && sync == none
207
+ @eval function UnsafeAtomics. modify! (
208
+ x:: Ptr{$typ} ,
209
+ op:: typeof ($ op),
210
+ v:: $typ ,
211
+ :: $ (typeof (ord)),
212
+ :: $ (typeof (sync)),
213
+ )
214
+ return Core. Intrinsics. atomic_pointermodify (x, op, v, base_ordering ($ ord))
215
+ end
216
+ else
217
+ @eval function UnsafeAtomics. modify! (
192
218
x:: Ptr{$typ} ,
193
- op :: typeof ($ op),
219
+ :: typeof ($ op),
194
220
v:: $typ ,
195
221
:: $ (typeof (ord)),
222
+ :: $ (typeof (sync)),
196
223
)
197
- return Core. Intrinsics. atomic_pointermodify (x, op, v, base_ordering ($ ord))
198
- end
199
- else
200
- @eval function UnsafeAtomics. modify! (
201
- x:: Ptr{$typ} ,
202
- :: typeof ($ op),
203
- v:: $typ ,
204
- :: $ (typeof (ord)),
205
- )
206
- old = llvmcall (
207
- $ ("""
208
- %ptr = inttoptr i$WORD_SIZE %0 to $lt *
209
- %rv = atomicrmw $rmw $lt * %ptr, $lt %1 $ord
210
- ret $lt %rv
211
- """ ),
212
- $ typ,
213
- Tuple{Ptr{$ typ},$ typ},
214
- x,
215
- v,
216
- )
217
- return old => $ op (old, v)
224
+ old = llvmcall (
225
+ $ ("""
226
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
227
+ %rv = atomicrmw $rmw $lt * %ptr, $lt %1 $ord
228
+ ret $lt %rv
229
+ """ ),
230
+ $ typ,
231
+ Tuple{Ptr{$ typ},$ typ},
232
+ x,
233
+ v,
234
+ )
235
+ return old => $ op (old, v)
236
+ end
218
237
end
219
238
end
220
239
end
221
240
end
222
241
end
223
242
224
- # Core.Intrinsics.atomic_fence was introduced in 1.10
225
- function UnsafeAtomics. fence (ord:: Ordering )
226
- Core. Intrinsics. atomic_fence (base_ordering (ord))
227
- return nothing
228
- end
229
- if Sys. ARCH == :x86_64
230
- # FIXME : Disable this once on LLVM 19
231
- # This is unfortunatly required for good-performance on AMD
232
- # https://github.com/llvm/llvm-project/pull/106555
233
- function UnsafeAtomics. fence (:: typeof (seq_cst))
234
- Base. llvmcall (
235
- (raw """
236
- define void @fence() #0 {
237
- entry:
238
- tail call void asm sideeffect "lock orq $$0 , (%rsp)", ""(); should this have ~{memory}
239
- ret void
240
- }
241
- attributes #0 = { alwaysinline }
242
- """ , " fence" ), Nothing, Tuple{})
243
+ for sync in syncscopes
244
+ if sync == none
245
+ # Core.Intrinsics.atomic_fence was introduced in 1.10
246
+ @eval function UnsafeAtomics. fence (ord:: Ordering , :: $ (typeof (sync)))
247
+ Core. Intrinsics. atomic_fence (base_ordering (ord))
248
+ return nothing
249
+ end
250
+ if Sys. ARCH == :x86_64
251
+ # FIXME : Disable this once on LLVM 19
252
+ # This is unfortunatly required for good-performance on AMD
253
+ # https://github.com/llvm/llvm-project/pull/106555
254
+ @eval function UnsafeAtomics. fence (:: typeof (seq_cst), :: $ (typeof (sync)))
255
+ Base. llvmcall (
256
+ (raw """
257
+ define void @fence() #0 {
258
+ entry:
259
+ tail call void asm sideeffect "lock orq $$0 , (%rsp)", ""(); should this have ~{memory}
260
+ ret void
261
+ }
262
+ attributes #0 = { alwaysinline }
263
+ """ , " fence" ), Nothing, Tuple{})
264
+ end
265
+ end
266
+ else
267
+ for ord in orderings
268
+ @eval function UnsafeAtomics. fence (:: $ (typeof (ord)), :: $ (typeof (sync)))
269
+ return llvmcall (
270
+ $ ("""
271
+ fence $sync $ord
272
+ ret void
273
+ """ ),
274
+ Cvoid,
275
+ Tuple{},
276
+ )
277
+ end
278
+ end
243
279
end
244
280
end
245
281
0 commit comments