Skip to content
This repository was archived by the owner on May 27, 2021. It is now read-only.

Commit 951a1d1

Browse files
Umashankar Sivakumarmaleadt
Umashankar Sivakumar
authored andcommitted
Making at-atomic robust (#467)
1 parent d98e60e commit 951a1d1

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

src/device/cuda/atomics.jl

+8-6
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ const inplace_ops = Dict(
299299
:(⊻=) => :()
300300
)
301301

302+
struct AtomicError <: Exception
303+
msg::AbstractString
304+
end
305+
302306
"""
303307
@atomic a[I] = op(a[I], val)
304308
@atomic a[I] ...= val
@@ -319,24 +323,22 @@ macro atomic(ex)
319323
if ex.head == :(=)
320324
ref = ex.args[1]
321325
rhs = ex.args[2]
322-
rhs.head == :call || error("right-hand side of an @atomic assignment should be a call")
326+
Meta.isexpr(rhs, :call) || throw(AtomicError("right-hand side of an @atomic assignment should be a call"))
323327
op = rhs.args[1]
324328
if rhs.args[2] != ref
325-
error("non-inplace @atomic assignment should reference the same array elements")
329+
throw(AtomicError("right-hand side of a non-inplace @atomic assignment should reference the left-hand side"))
326330
end
327331
val = rhs.args[3]
328332
elseif haskey(inplace_ops, ex.head)
329333
op = inplace_ops[ex.head]
330334
ref = ex.args[1]
331335
val = ex.args[2]
332336
else
333-
error("unknown @atomic expression")
337+
throw(AtomicError("unknown @atomic expression"))
334338
end
335339

336340
# decode array expression
337-
if ref.head != :ref
338-
error("@atomic should be applied to an array reference expression")
339-
end
341+
Meta.isexpr(ref, :ref) || throw(AtomicError("@atomic should be applied to an array reference expression"))
340342
array = ref.args[1]
341343
indices = Expr(:tuple, ref.args[2:end]...)
342344

test/device/cuda.jl

+23
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,29 @@ end
11001100
end
11011101
end
11021102

1103+
@testset "macro" begin
1104+
using CUDAnative: AtomicError
1105+
1106+
@test_throws_macro AtomicError("right-hand side of an @atomic assignment should be a call") @macroexpand begin
1107+
@atomic a[1] = 1
1108+
end
1109+
@test_throws_macro AtomicError("right-hand side of an @atomic assignment should be a call") @macroexpand begin
1110+
@atomic a[1] = b ? 1 : 2
1111+
end
1112+
1113+
@test_throws_macro AtomicError("right-hand side of a non-inplace @atomic assignment should reference the left-hand side") @macroexpand begin
1114+
@atomic a[1] = a[2] + 1
1115+
end
1116+
1117+
@test_throws_macro AtomicError("unknown @atomic expression") @macroexpand begin
1118+
@atomic wat(a[1])
1119+
end
1120+
1121+
@test_throws_macro AtomicError("@atomic should be applied to an array reference expression") @macroexpand begin
1122+
@atomic a = a + 1
1123+
end
1124+
end
1125+
11031126
end
11041127

11051128
############################################################################################

test/util.jl

+14
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,20 @@ macro test_throws_message(f, typ, ex...)
1717
end
1818
end
1919

20+
# @test_throw, peeking into the load error for testing macro errors
21+
macro test_throws_macro(ty, ex)
22+
return quote
23+
Test.@test_throws $(esc(ty)) try
24+
$(esc(ex))
25+
catch err
26+
@test err isa LoadError
27+
@test err.file === $(string(__source__.file))
28+
@test err.line === $(__source__.line + 1)
29+
rethrow(err.error)
30+
end
31+
end
32+
end
33+
2034
# NOTE: based on test/pkg.jl::capture_stdout, but doesn't discard exceptions
2135
macro grab_output(ex)
2236
quote

0 commit comments

Comments
 (0)