Skip to content

Commit 68c1146

Browse files
committed
Initial implementation
1 parent 1084b2b commit 68c1146

File tree

8 files changed

+135
-7
lines changed

8 files changed

+135
-7
lines changed

Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,9 @@ uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
33
authors = ["Takafumi Arakaki <[email protected]> and contributors"]
44
version = "0.1.0-DEV"
55

6+
[deps]
7+
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
8+
UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f"
9+
610
[compat]
711
julia = "1.6"

src/UnsafeAtomicsLLVM.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ baremodule UnsafeAtomicsLLVM
22

33
module Internal
44

5-
using ..UnsafeAtomicsLLVM: UnsafeAtomicsLLVM
5+
using Core: LLVMPtr
6+
using LLVM
7+
using UnsafeAtomics: UnsafeAtomics, Ordering
68

79
include("internal.jl")
810

src/internal.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# TODO: move this to UnsafeAtomics
2+
julia_ordering_name(::UnsafeAtomics.Internal.LLVMOrdering{name}) where {name} = name
3+
julia_ordering_name(::typeof(UnsafeAtomics.acquire_release)) = :acquire_release
4+
julia_ordering_name(::typeof(UnsafeAtomics.sequentially_consistent)) =
5+
:sequentially_consistent
6+
7+
@inline UnsafeAtomics.load(ptr::LLVMPtr, order::Ordering) =
8+
LLVM.Interop.atomic_pointerref(ptr, Val{julia_ordering_name(order)}())
9+
10+
@inline function UnsafeAtomics.store!(ptr::LLVMPtr, x, order::Ordering)
11+
LLVM.Interop.atomic_pointerset(ptr, x, Val{julia_ordering_name(order)}())
12+
return
13+
end
14+
15+
mapop(op::OP) where {OP} = op
16+
mapop(::typeof(UnsafeAtomics.right)) = LLVM.Interop.right
17+
18+
@inline UnsafeAtomics.modify!(ptr::LLVMPtr, op::OP, x, order::Ordering) where {OP} =
19+
LLVM.Interop.atomic_pointermodify(ptr, mapop(op), x, Val{julia_ordering_name(order)}())
20+
21+
@inline UnsafeAtomics.cas!(
22+
ptr::LLVMPtr,
23+
expected,
24+
desired,
25+
success_order::Ordering,
26+
failure_order::Ordering,
27+
) = LLVM.Interop.atomic_pointerreplace(
28+
ptr,
29+
expected,
30+
desired,
31+
Val{julia_ordering_name(success_order)}(),
32+
Val{julia_ordering_name(failure_order)}(),
33+
)

test/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
[deps]
22
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
3+
TestFunctionRunner = "792026f5-ac9a-4a19-adcb-47b0ce2deb5d"
4+
5+
[compat]
6+
TestFunctionRunner = "0.1"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name = "UnsafeAtomicsLLVMTests"
2+
uuid = "f81c5320-9584-4f93-9445-2842f5246c7e"
3+
authors = ["Takafumi Arakaki <[email protected]> and contributors"]
4+
version = "0.1.0-DEV"
5+
6+
[deps]
7+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
8+
UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f"
9+
UnsafeAtomicsLLVM = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
10+
11+
[compat]
12+
julia = "1.6"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module UnsafeAtomicsLLVMTests
2+
3+
include("test_core.jl")
4+
5+
end # module UnsafeAtomicsLLVMTests
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
module TestCore
2+
3+
import UnsafeAtomicsLLVM
4+
5+
using UnsafeAtomics: UnsafeAtomics, acquire, release, acq_rel
6+
using UnsafeAtomics.Internal: OP_RMW_TABLE, inttypes
7+
using Test
8+
9+
llvmptr(xs::Array, i) = reinterpret(Core.LLVMPtr{eltype(xs),0}, pointer(xs, i))
10+
11+
function test_default_ordering()
12+
@testset for T in inttypes
13+
check_default_ordering(T)
14+
end
15+
end
16+
17+
function check_default_ordering(T::Type)
18+
xs = T[rand(T), rand(T)]
19+
x1 = rand(T)
20+
x2 = rand(T)
21+
@debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))"
22+
23+
ptr = llvmptr(xs, 1)
24+
GC.@preserve xs begin
25+
@test UnsafeAtomics.load(ptr) === xs[1]
26+
UnsafeAtomics.store!(ptr, x1)
27+
@test xs[1] === x1
28+
desired = (old = x1, success = true)
29+
@test UnsafeAtomics.cas!(ptr, x1, x2) === (old = x1, success = true)
30+
@test xs[1] === x2
31+
@testset for (op, name) in OP_RMW_TABLE
32+
xs[1] = x1
33+
@test UnsafeAtomics.modify!(ptr, op, x2) === (x1 => op(x1, x2))
34+
@test xs[1] === op(x1, x2)
35+
36+
rmw = getfield(UnsafeAtomics, Symbol(name, :!))
37+
xs[1] = x1
38+
@test rmw(ptr, x2) === x1
39+
@test xs[1] === op(x1, x2)
40+
end
41+
end
42+
end
43+
44+
function test_explicit_ordering(T::Type = UInt)
45+
xs = T[rand(T), rand(T)]
46+
x1 = rand(T)
47+
x2 = rand(T)
48+
@debug "xs=$(repr(xs)) x1=$(repr(x1)) x2=$(repr(x2))"
49+
50+
ptr = llvmptr(xs, 1)
51+
GC.@preserve xs begin
52+
53+
@test UnsafeAtomics.load(ptr, acquire) === xs[1]
54+
UnsafeAtomics.store!(ptr, x1, release)
55+
@test xs[1] === x1
56+
desired = (old = x1, success = true)
57+
@test UnsafeAtomics.cas!(ptr, x1, x2, acq_rel, acquire) === desired
58+
@test xs[1] === x2
59+
@testset for (op, name) in OP_RMW_TABLE
60+
xs[1] = x1
61+
@test UnsafeAtomics.modify!(ptr, op, x2, acq_rel) === (x1 => op(x1, x2))
62+
@test xs[1] === op(x1, x2)
63+
64+
rmw = getfield(UnsafeAtomics, Symbol(name, :!))
65+
xs[1] = x1
66+
@test rmw(ptr, x2, acquire) === x1
67+
@test xs[1] === op(x1, x2)
68+
end
69+
end
70+
end
71+
72+
end # module

test/runtests.jl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
1-
using UnsafeAtomicsLLVM
2-
using Test
3-
4-
@testset "UnsafeAtomicsLLVM.jl" begin
5-
# Write your tests here.
6-
end
1+
using TestFunctionRunner
2+
TestFunctionRunner.@run

0 commit comments

Comments
 (0)