@@ -91,13 +91,29 @@ render_arg(io, arg::Base.RefValue{T}) where {T} = print(io, "Ref{", T, "}")
91
91
92
92
93
93
# # 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
-
97
94
# note that this is generally only safe with functions that do not call back into Julia.
98
95
# when callbacks occur, the code should ensure the GC is not running by wrapping the code
99
96
# in the `@gcunsafe` macro
100
97
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
101
117
function ccall_macro_lower (func, rettype, types, args, nreq)
102
118
# instead of re-using ccall or Expr(:foreigncall) to perform argument conversion,
103
119
# 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.
152
168
macro gcsafe_ccall (expr)
153
169
return ccall_macro_lower (Base. ccall_macro_parse (expr)... )
154
170
end
171
+ end # HAS_CCALL_GCSAFE
0 commit comments