Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use support for gc_safe=true in Base if available #6

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
36 changes: 22 additions & 14 deletions src/ccalls.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,31 @@ render_arg(io, arg::Base.RefValue{T}) where {T} = print(io, "Ref{", T, "}")


## version of ccall that calls jl_gc_safe_enter|leave around the inner ccall

# TODO: replace with JuliaLang/julia#49933 once merged

# note that this is generally only safe with functions that do not call back into Julia.
# when callbacks occur, the code should ensure the GC is not running by wrapping the code
# in the `@gcunsafe` macro

const HAS_CCALL_GCSAFE = VERSION >= v"1.13.0-DEV.70"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait for JuliaLang/julia#57408 to be merged to add that compat/version bound to this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const HAS_CCALL_GCSAFE = VERSION >= v"1.13.0-DEV.70"
const HAS_CCALL_GCSAFE = VERSION >= v"1.13.0-DEV.70" || v"1.12-DEV.2029" <= VERSION < v"1.13-"


"""
@gcsafe_ccall ...

Call a foreign function just like `@ccall`, but marking it safe for the GC to run. This is
useful for functions that may block, so that the GC isn't blocked from running, but may also
be required to prevent deadlocks (see JuliaGPU/CUDA.jl#2261).

Note that this is generally only safe with non-Julia C functions that do not call back into
Julia. When using callbacks, the code should make sure to transition back into GC-unsafe
mode using the `@gcunsafe` macro.
"""
macro gcsafe_ccall end

if HAS_CCALL_GCSAFE
macro gcsafe_ccall(exprs)
exprs = pushfirst(exprs, :(gc_safe = true))
return Base.ccall_macro_lower((:ccall), Base.ccall_macro_parse(exprs)...)
end
else
function ccall_macro_lower(func, rettype, types, args, nreq)
# instead of re-using ccall or Expr(:foreigncall) to perform argument conversion,
# we need to do so ourselves in order to insert a jl_gc_safe_enter|leave
Expand Down Expand Up @@ -138,17 +156,7 @@ function ccall_macro_lower(func, rettype, types, args, nreq)
end
end

"""
@gcsafe_ccall ...

Call a foreign function just like `@ccall`, but marking it safe for the GC to run. This is
useful for functions that may block, so that the GC isn't blocked from running, but may also
be required to prevent deadlocks (see JuliaGPU/CUDA.jl#2261).

Note that this is generally only safe with non-Julia C functions that do not call back into
Julia. When using callbacks, the code should make sure to transition back into GC-unsafe
mode using the `@gcunsafe` macro.
"""
macro gcsafe_ccall(expr)
return ccall_macro_lower(Base.ccall_macro_parse(expr)...)
end
end # HAS_CCALL_GCSAFE
Loading