Allow for :foreigncall to transition to GC safe automatically#49933
Allow for :foreigncall to transition to GC safe automatically#49933
Conversation
|
Since we already have the trampoline stuff, what about adding a safepoint into every call into the julia runtime? Similar to the safepoint in JIT function calls? |
|
How would this affect packages that use CxxWrap or jlrs to provide access to C++ and Rust libraries, which call back into into Julia from foreign functions? |
All in Julia itself? Perhaps. All in all Julia packages? Definitely not! That would be a breaking change. |
Can you point at a for-instance @fingolfin? |
|
The not common but existing case is for julia code to call c code that calls julia runtime functions. |
|
@kpamnany any package using a JLL linking against I am not saying this is an impossible change, but only if there is a well thought out migration strategy that is coordinated with all stakeholders. But just saying "it probably won't affect that many packages, let's just do it", without a full analysis and without involving the community, repeats the "main" debacle. Let's not go there. Overall, I prefer "code that is not as fast as it could be but is correct" over "code that is perhaps a bit faster, or not, but will occasionally crash or produce garbage... A more viable alternative would be an opt-in solution -- but then of course many packages will miss this opportunity. A pity, but it wouldn't leave us worse than we are right now, new packages could benefit from it. (If we had something like Rust editions, then for "new" packages this could become the default, I guess...?) |
aca69d9 to
47a08bb
Compare
47a08bb to
6fcef7c
Compare
Now is: The safepoint emission at that point needs to be cleaner. @vtjnash that's probably closer to what it needs to be? |
|
Note for when this lands: we should redo JuliaLang/MbedTLS.jl#265. |
This allows the GC to run while potentially blocking in a CUDA library. To make this safe, callbacks into Julia should again transition to GC-unsafe mode. It should be reimplemented when JuliaLang/julia#49933 lands. Co-authored-by: Tim Besard <tim.besard@gmail.com>
6fcef7c to
e007905
Compare
|
@gbaraldi I rebased this and confirmed that: @eval function put(msg)
cmsg = Base.cconvert(Cstring, msg)
ptr = Base.unsafe_convert(Cstring, cmsg)
$(Expr(:foreigncall, QuoteNode(:puts), Cint, Core.svec(Cstring), 0, true, QuoteNode(:ccall), :ptr, :cmsg))
end |
|
This is missing some safepoints no? STATIC_INLINE int8_t jl_gc_state_set(jl_ptls_t ptls, int8_t state,
int8_t old_state)
{
assert(old_state != JL_GC_PARALLEL_COLLECTOR_THREAD);
assert(old_state != JL_GC_CONCURRENT_COLLECTOR_THREAD);
jl_atomic_store_release(&ptls->gc_state, state);
if (state == JL_GC_STATE_UNSAFE || old_state == JL_GC_STATE_UNSAFE)
jl_gc_safepoint_(ptls);
return old_state;
} |
|
I only posted an excerpt: |
|
And yeah I was gonna say, the conditionality of the safepoint is probably a bit dumb, even in gc_state_set |
|
@gbaraldi I would prefer |
0ea64c0 to
699a949
Compare
72ed182 to
e1a8b94
Compare
ce14078 to
41ef0c4
Compare
2ebb73e to
557119f
Compare
|
llvmpasses and windows tests are failing |
Co-authored-by: Gabriel Baraldi <baraldigabriel@gmail.com>
9c70ad2 to
8b252f8
Compare
| New language features | ||
| --------------------- | ||
|
|
||
| * The `@ccall` macro can now take a `gc_safe` argument, that if set to true allows the runtime to run garbage collection concurrently to the `ccall` |
There was a problem hiding this comment.
Should probably have been in HISTORY since you want it backported
This has been bouncing around as a idea for a while. One of the challenges around time-to-safepoint has been Julia code that is calling libraries. Since foreign code will not include safepoints we see increased latency when one thread is running a foreign-call and another wants to trigger GC. The open design question here is: - Do we expose this as an option the user must "opt-in", e.g. by using a keyword arg to `@ccall` or a specific calling-convetion. - Or do we turn this on for all ccall, except for Julia runtime calls. There is relativly little code outside the Julia runtime that needs to be "GC unsafe", exception are programs that directly use the Julia C-API. Incidentially `jl_adopt_thread` and `@cfunction`/`@ccallable` do the right thing and transition to "GC unsafe", regardless of what state the thread currently is in. I still need to figure out how to reliably detect Julia runtime calls, but I think we can switch all other calls to "GC safe". We should also consider optimizations that mark large regions of code without Julia runtime interactions as "GC safe" in particular numeric for-loops. Closes #57057 --------- Co-authored-by: Gabriel Baraldi <baraldigabriel@gmail.com> (cherry picked from commit 85458a0)
Backported PRs: - [x] #57346 <!-- lowering: Only try to define the method once --> - [x] #57341 <!-- bpart: When backdating replace the entire bpart chain --> - [x] #57381 <!-- staticdata: Set min validation world to require world --> - [x] #57357 <!-- Only implicitly `using` Base, not Core --> - [x] #57383 <!-- staticdata: Fix typo in recursive edge revalidation --> - [x] #57385 <!-- bpart: Move kind enum into its intended place --> - [x] #57275 <!-- Compiler: fix unsoundness of getfield_tfunc on Tuple Types --> - [x] #57378 <!-- print admonition for auto-import only once per module --> - [x] #57392 <!-- [LateLowerGCFrame] fix PlaceGCFrameReset for returns_twice --> - [x] #57388 <!-- Bump JuliaSyntax to v1.0.2 --> - [x] #57266 <!-- 🤖 [master] Bump the Statistics stdlib from d49c2bf to 77bd570 --> - [x] #57395 <!-- lowering: fix has_fcall computation --> - [x] #57204 <!-- Clarify mathematical definition of `gcd` --> - [x] #56794 <!-- Make `Pairs` public --> - [x] #57407 <!-- staticdata: corrected implementation of jl_collect_new_roots --> - [x] #57405 <!-- bpart: Also partition the export flag --> - [x] #57420 <!-- Compiler: Fix check for IRShow definedness --> - [x] #55875 <!-- fix `(-Inf)^-1` inconsistency --> - [x] #57317 <!-- internals: add _defaultctor function for defining ctors --> - [x] #57406 <!-- bpart: Ignore guard bindings for ambiguity purposes --> - [x] #49933 <!-- Allow for :foreigncall to transition to GC safe automatically -->
…ang#49933) This has been bouncing around as a idea for a while. One of the challenges around time-to-safepoint has been Julia code that is calling libraries. Since foreign code will not include safepoints we see increased latency when one thread is running a foreign-call and another wants to trigger GC. The open design question here is: - Do we expose this as an option the user must "opt-in", e.g. by using a keyword arg to `@ccall` or a specific calling-convetion. - Or do we turn this on for all ccall, except for Julia runtime calls. There is relativly little code outside the Julia runtime that needs to be "GC unsafe", exception are programs that directly use the Julia C-API. Incidentially `jl_adopt_thread` and `@cfunction`/`@ccallable` do the right thing and transition to "GC unsafe", regardless of what state the thread currently is in. I still need to figure out how to reliably detect Julia runtime calls, but I think we can switch all other calls to "GC safe". We should also consider optimizations that mark large regions of code without Julia runtime interactions as "GC safe" in particular numeric for-loops. Closes JuliaLang#57057 --------- Co-authored-by: Gabriel Baraldi <baraldigabriel@gmail.com>
|
Applying the new option breaks |
This has been bouncing around as a idea for a while.
One of the challenges around time-to-safepoint has been Julia code
that is calling libraries.
Since foreign code will not include safepoints we see increased latency
when one thread is running a foreign-call and another wants to trigger GC.
The open design question here is:
keyword arg to
@ccallor a specific calling-convetion.There is relativly little code outside the Julia runtime that needs to be "GC unsafe",
exception are programs that directly use the Julia C-API. Incidentially
jl_adopt_threadand
@cfunction/@ccallabledo the right thing and transition to "GC unsafe", regardlessof what state the thread currently is in.
I still need to figure out how to reliably detect Julia runtime calls, but I think we can
switch all other calls to "GC safe". We should also consider optimizations that mark large
regions of code without Julia runtime interactions as "GC safe" in particular numeric
for-loops.
Closes #57057