I am currently developping a Kotlin library to embed Julia in the JVM, with the goal to support multithreading with jl_adopt_thread()
. The main issue is that when using some frameworks, there may not be a way to be in control of which JVM thread would want to use Julia.
If Julia is used through JVM worker threads, then you would want to make sure that after the work is done, the adopted JVM thread does not prevent the GC from running: good management of the thread’s gc_state
is required.
What I came up with is the following code (simplified):
fun runUsingJulia(func: () -> Unit) {
var wasThreadAdopted = false
if (!isThreadAdopted()) {
jl_adopt_thread()
wasThreadAdopted = true
}
val oldState = jl_gc_unsafe_enter()
try {
func()
} finally {
jl_gc_unsafe_leave(oldState)
if (wasThreadAdopted) {
jl_gc_safe_enter()
}
}
}
Then runUsingJulia(someFunction)
would:
- Adopt the current thread if needed
- Mark the current thread as running Julia code (GC unsafe)
- Run
someFunction
- Mark the current thread as GC safe (
jl_gc_safe_enter
is needed asjl_adopt_thread
marks the thread as GC unsafe by default, and therefore must be called once)
However, this is not robust, as jl_gc_unsafe_enter
will segfault if the GC is running.
The first lines of jl_adopt_thread
show how to deal with a similar edge-case, but:
jl_gc_running
is not exported: it is not possible to know if it is safe to calljl_gc_unsafe_enter
beforehandjl_gc_disable_counter
is not exported: there is no way to prevent the GC from starting before we calljl_gc_unsafe_enter
(writes should also be atomic, which is not possible within the JVM)jl_safepoint_wait_gc
would be a good way to wait for the GC to finish (plus dealing with another edge-case where the thread is marked as GC unsafe and the GC is currently waiting for it), but it is not exported
Therefore I cannot use those from Kotlin to prevent jl_gc_unsafe_enter
to segfault.
Is there any way to adopt threads for temporary work with Julia without preventing GC and edge-cases?
I should mention that I managed to make this work reliably in Windows, where jl_gc_running
and jl_safepoint_wait_gc
are accessble for some reason. Obviously, supporting all platforms would be better.