@@ -91,13 +91,29 @@ render_arg(io, arg::Base.RefValue{T}) where {T} = print(io, "Ref{", T, "}")
9191
9292
9393# # version of ccall that calls jl_gc_safe_enter|leave around the inner ccall
94-
95- # TODO : replace with JuliaLang/julia#49933 once merged
96-
9794# note that this is generally only safe with functions that do not call back into Julia.
9895# when callbacks occur, the code should ensure the GC is not running by wrapping the code
9996# in the `@gcunsafe` macro
10097
98+ const HAS_CCALL_GCSAFE = VERSION >= v " 1.13.0-DEV.70"
99+
100+ if HAS_CCALL_GCSAFE
101+ """
102+ @gcsafe_ccall ...
103+
104+ Call a foreign function just like `@ccall`, but marking it safe for the GC to run. This is
105+ useful for functions that may block, so that the GC isn't blocked from running, but may also
106+ be required to prevent deadlocks (see JuliaGPU/CUDA.jl#2261).
107+
108+ Note that this is generally only safe with non-Julia C functions that do not call back into
109+ Julia. When using callbacks, the code should make sure to transition back into GC-unsafe
110+ mode using the `@gcunsafe` macro.
111+ """
112+ macro gcsafe_ccall (exprs)
113+ exprs = pushfirst (exprs, :(gc_safe = true ))
114+ return Base. ccall_macro_lower ((:ccall ), Base. ccall_macro_parse (exprs)... )
115+ end
116+ else
101117function ccall_macro_lower (func, rettype, types, args, nreq)
102118 # instead of re-using ccall or Expr(:foreigncall) to perform argument conversion,
103119 # we need to do so ourselves in order to insert a jl_gc_safe_enter|leave
@@ -152,3 +168,4 @@ mode using the `@gcunsafe` macro.
152168macro gcsafe_ccall (expr)
153169 return ccall_macro_lower (Base. ccall_macro_parse (expr)... )
154170end
171+ end # HAS_CCALL_GCSAFE
0 commit comments