Last active
November 20, 2019 17:37
-
-
Save dillondaudert/be7b2e2943f37dacc75f315cd89590a0 to your computer and use it in GitHub Desktop.
Atomic{Ptr}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# atomic operations for pointers. for test development purposes | |
import Base.Sys: WORD_SIZE | |
using Core.Intrinsics: llvmcall | |
using Base.Threads: llvmtypes, AtomicTypes | |
mutable struct MyAtomic{V<:Ptr} | |
value::V | |
end | |
@eval atomic_xchg!(x::MyAtomic{Ptr{V}}, v::Ptr{V}) where V = llvmcall($""" | |
%ptr = inttoptr i$WORD_SIZE %0 to i$WORD_SIZE* | |
%rv = atomicrmw xchg i$WORD_SIZE* %ptr, i$WORD_SIZE %1 acq_rel | |
ret i$WORD_SIZE %rv | |
""", Ptr{V}, Tuple{Ptr{Ptr{V}}, Ptr{V}}, convert(Ptr{Ptr{V}}, pointer_from_objref(x)), v) | |
@eval atomic_cas!(x::MyAtomic{Ptr{V}}, cmp::Ptr{V}, new::Ptr{V}) where V = llvmcall($""" | |
%ptr = inttoptr i$WORD_SIZE %0 to i$WORD_SIZE* | |
%rs = cmpxchg i$WORD_SIZE* %ptr, i$WORD_SIZE %1, i$WORD_SIZE %2 acq_rel acquire | |
%rv = extractvalue { i$WORD_SIZE, i1 } %rs, 0 | |
ret i$WORD_SIZE %rv | |
""", Ptr{V}, Tuple{Ptr{Ptr{V}}, Ptr{V}, Ptr{V}}, convert(Ptr{Ptr{V}}, pointer_from_objref(x)), cmp, new) | |
A = [1, 2, 3] | |
ptr1 = pointer(A, 1) | |
ptr2 = pointer(A, 2) | |
ptr3 = pointer(A, 3) | |
my_atomic = MyAtomic{Ptr{Int}}(ptr1) | |
@assert atomic_xchg!(my_atomic, ptr2) === ptr1 | |
@assert my_atomic.value === ptr2 | |
# atomic_cas! | |
@assert atomic_cas!(my_atomic, ptr3, ptr3) === ptr2 | |
@assert my_atomic.value === ptr2 # no swap | |
@assert atomic_cas!(my_atomic, ptr2, ptr3) === ptr2 | |
@assert my_atomic.value === ptr3 # yes swap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Base.Sys: WORD_SIZE | |
using Core.Intrinsics: llvmcall | |
using Base.Threads: llvmtypes, atomictypes | |
""" | |
getelementptr(p::Ptr{T}, index::Integer) | |
Returns the address in memory at `index`. This calls the LLVM op `getelementptr` to | |
perform pointer arithmetic. | |
""" | |
function getelementptr end | |
getelementptr(p::Ptr, index::Integer) = getelementptr(p, (index % UInt) % UInt) | |
for typ in atomictypes | |
lt = llvmtypes[typ] | |
@eval getelementptr(p::Ptr{$typ}, index::UInt) = oftype(p, llvmcall($""" | |
%ptr = inttoptr i$WORD_SIZE %0 to $lt* | |
%idx = getelementptr $lt, $lt* %ptr, i$WORD_SIZE %1 | |
%rv = ptrtoint $lt* %idx to i$WORD_SIZE | |
ret i$WORD_SIZE %rv | |
""", UInt, Tuple{Ptr{$typ}, UInt}, p, index)) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment