Skip to content

Commit 8b2ccff

Browse files
authored
Expose syncscope parameter for atomic add/sub (#14)
1 parent 6e57e10 commit 8b2ccff

File tree

5 files changed

+79
-14
lines changed

5 files changed

+79
-14
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ jobs:
1313
strategy:
1414
matrix:
1515
julia-version:
16-
- '1'
17-
- '1.6'
16+
- '1.10'
1817
- 'nightly'
1918
fail-fast: false
2019
name: Test Julia ${{ matrix.julia-version }}
@@ -36,8 +35,7 @@ jobs:
3635
strategy:
3736
matrix:
3837
julia-version:
39-
- '1'
40-
- '1.6'
38+
- '1.10'
4139
- 'nightly'
4240
fail-fast: false
4341
steps:

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
name = "UnsafeAtomicsLLVM"
22
uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
33
authors = ["Takafumi Arakaki <[email protected]> and contributors"]
4-
version = "0.1.5"
4+
version = "0.2.0"
55

66
[deps]
77
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
88
UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f"
99

1010
[compat]
11-
LLVM = "6, 7, 8"
11+
LLVM = "8.1"
1212
UnsafeAtomics = "0.2"
13-
julia = "1.6"
13+
julia = "1.10"

src/atomics.jl

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,15 @@ const binoptable = [
248248
(:umin, min, LLVM.API.LLVMAtomicRMWBinOpUMin),
249249
(:fadd, +, LLVM.API.LLVMAtomicRMWBinOpFAdd),
250250
(:fsub, -, LLVM.API.LLVMAtomicRMWBinOpFSub),
251+
(:fmax, max, LLVM.API.LLVMAtomicRMWBinOpFMax),
252+
(:fmin, min, LLVM.API.LLVMAtomicRMWBinOpFMin),
251253
]
252-
if VERSION v"1.10-"
253-
push!(binoptable, (:fmax, max, LLVM.API.LLVMAtomicRMWBinOpFMax))
254-
push!(binoptable, (:fmin, min, LLVM.API.LLVMAtomicRMWBinOpFMin))
255-
end
256254

257255
const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...}
258256

257+
# LLVM API accepts string literal as a syncscope argument.
258+
@inline syncscope_to_string(::Type{Val{S}}) where {S} = string(S)
259+
259260
@generated function llvm_atomic_op(
260261
binop::AtomicRMWBinOpVal,
261262
ptr::LLVMPtr{T,A},
@@ -293,6 +294,40 @@ const AtomicRMWBinOpVal = Union{(Val{binop} for (_, _, binop) in binoptable)...}
293294
end
294295
end
295296

297+
@generated function llvm_atomic_op(
298+
binop::AtomicRMWBinOpVal,
299+
ptr::LLVMPtr{T,A},
300+
val::T,
301+
order::LLVMOrderingVal,
302+
syncscope::Val{S},
303+
) where {T,A,S}
304+
@dispose ctx = Context() begin
305+
T_val = convert(LLVMType, T)
306+
T_ptr = convert(LLVMType, ptr)
307+
308+
T_typed_ptr = LLVM.PointerType(T_val, A)
309+
llvm_f, _ = create_function(T_val, [T_ptr, T_val])
310+
311+
@dispose builder = IRBuilder() begin
312+
entry = BasicBlock(llvm_f, "entry")
313+
position!(builder, entry)
314+
315+
typed_ptr = bitcast!(builder, parameters(llvm_f)[1], T_typed_ptr)
316+
rv = atomic_rmw!(
317+
builder,
318+
_valueof(binop()),
319+
typed_ptr,
320+
parameters(llvm_f)[2],
321+
_valueof(order()),
322+
syncscope_to_string(syncscope),
323+
)
324+
325+
ret!(builder, rv)
326+
end
327+
call_function(llvm_f, T, Tuple{LLVMPtr{T,A},T}, :ptr, :val)
328+
end
329+
end
330+
296331
@inline function atomic_pointermodify(pointer, op::OP, x, order::Symbol) where {OP}
297332
@dynamic_order(order) do order
298333
atomic_pointermodify(pointer, op, x, order)
@@ -359,8 +394,18 @@ for (opname, op, llvmop) in binoptable
359394
::$(typeof(op)),
360395
x::$T,
361396
order::AtomicOrdering,
362-
)
363-
old = llvm_atomic_op($(Val(llvmop)), ptr, x, llvm_from_julia_ordering(order))
397+
syncscope::Val{S} = Val{:system}(),
398+
) where {S}
399+
old =
400+
syncscope isa Val{:system} ?
401+
llvm_atomic_op($(Val(llvmop)), ptr, x, llvm_from_julia_ordering(order)) :
402+
llvm_atomic_op(
403+
$(Val(llvmop)),
404+
ptr,
405+
x,
406+
llvm_from_julia_ordering(order),
407+
syncscope,
408+
)
364409
return old => $op(old, x)
365410
end
366411
end

src/internal.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ mapop(::typeof(UnsafeAtomics.right)) = right
2020
@inline UnsafeAtomics.modify!(ptr::LLVMPtr, op::OP, x, order::Ordering) where {OP} =
2121
atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}())
2222

23+
@inline UnsafeAtomics.modify!(
24+
ptr::LLVMPtr,
25+
op::OP,
26+
x,
27+
order::Ordering,
28+
syncscope::Val{S} = Val(:system),
29+
) where {OP<:Union{typeof(+),typeof(-)},S} =
30+
atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}(), syncscope)
31+
2332
@inline UnsafeAtomics.cas!(
2433
ptr::LLVMPtr,
2534
expected,

test/runtests.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import UnsafeAtomicsLLVM
22

3-
using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel
3+
using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel, seq_cst
44
using UnsafeAtomics.Internal: OP_RMW_TABLE, inttypes
55
using Test
66

@@ -57,6 +57,19 @@ function test_explicit_ordering(T::Type = UInt)
5757
xs[1] = x1
5858
@test rmw(ptr, x2, acquire) === x1
5959
@test xs[1] === op(x1, x2)
60+
61+
# Test syncscopes.
62+
if (op == +) || (op == -)
63+
xs[1] = x1
64+
@test UnsafeAtomics.modify!(ptr, op, x2, seq_cst, Val(:system)) ===
65+
(x1 => op(x1, x2))
66+
@test xs[1] === op(x1, x2)
67+
68+
xs[1] = x1
69+
@test UnsafeAtomics.modify!(ptr, op, x2, seq_cst, Val(:singlethread)) ===
70+
(x1 => op(x1, x2))
71+
@test xs[1] === op(x1, x2)
72+
end
6073
end
6174
end
6275
end

0 commit comments

Comments
 (0)