Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,10 @@ function GPUArrays.derive(::Type{T}, a::oneArray, dims::Dims{N}, offset::Int) wh
Base.elsize(a) == 0 || error("Cannot derive a singleton array from non-singleton inputs")
end
offset = a.offset + offset * sizeof(T)
oneArray{T,N}(a.data, dims; a.maxsize, offset)
# The derived array constructor copies `a.data`, but merely loading that field does not
# keep `a` alive. Without this preserve, `a` may be finalized between the field load and
# the DataRef copy, causing its finalizer to mark the reference as freed.
GC.@preserve a oneArray{T,N}(a.data, dims; a.maxsize, offset)
end


Expand Down
35 changes: 35 additions & 0 deletions test/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,41 @@ end
@test Array(xs) == [0,1,0]
end

@testset "derived array lifetime" begin
parent = oneArray{UInt8}(undef, 1)

# Construct through an ephemeral derived array, whose finalizer shares the same
# reference-counted allocation with the returned view.
function ephemeral_derived_view(parent)
intermediate = @view parent[:]
@view intermediate[:]
end

derived = ephemeral_derived_view(parent)
@test derived isa oneArray{UInt8}

# Exercise finalization while deriving. Without preserving the immediate parent in
# GPUArrays.derive, its finalizer can mark the DataRef as freed before it is copied.
if Threads.nthreads() > 1
stop_gc = Threads.Atomic{Bool}(false)
gc_task = Threads.@spawn while !stop_gc[]
GC.gc(false)
yield()
end
try
Threads.@threads for _ in 1:min(Threads.nthreads(), 4)
for _ in 1:100
a = ephemeral_derived_view(parent)
oneAPI.unsafe_free!(a)
end
end
finally
stop_gc[] = true
wait(gc_task)
end
end
end

@testset "reinterpret of view with non-aligned offset" begin
# reinterpreting a view to a larger element type where the byte offset
# is not a multiple of the new element size
Expand Down
Loading