C embedding interface called from multiple threads

I’ve spent a few days playing with embedding Julia into C++ signal processing code. My aim is to be able to quickly write prototype code in Julia that is then executed in a real-time audio host.

The problem that I have now encountered is that the real-time audio rendering callback runs in a different thread than the other setup code. So after I have initialized everything that I require for interfacing with the julia code and have disabled garbage collection, I receive the actual real-time thread callback that I’m relaying to julia, which crashes with an access violation in jl_enter_handler.

It turns out that julia tries to access information from the thread local storage. With the audio real-time thread unknown to julia, it does not find an associate local storage and the walks right into accessing uninitialised memory.

Unfortunately, I cannot move my initialisation code to the real-time thread, so I’m not sure how I can proceed. Is there any way to inform julia of the existence of the other thread so that it can allocate the TLS properly? Are there any other options that would allow me to call julia functions from this thread?

Some time ago, I had toyed some code to solve that. Maybe it can be useful to you: https://gist.github.com/cdsousa/473463e9b4e4f57c5b598e6966ca6a21

Also, it may be possible that the parallel task runtime WIP WIP: parallel task runtime by kpamnany · Pull Request #22631 · JuliaLang/julia · GitHub will help with making Julia embedding interface available from multiple threads. But about that, I’m not sure.

Thank you very much for your response. Unfortunately using a single worker thread to dispatch Julia calls is not an option for me, or at least it would be an option that I would like to avoid if possible.

I would like to stay in the context of the audio thread which runs with real-time priority (which I cannot set for my worker thread, if I used one, because I don’t have the necessary privileges) and blocking the audio thread while I wait for the worker wouldn’t be good because the audio thread might lose the attention of the scheduler. And a spinning lock is probably wasting a lot of CPU time.

I’ll have a look at the parallel task runtime you have referred to. And I will inspect the Julia sources and try to find a way to handle TLS manually, if possible.

Thanks!
Andreas

1 Like

Maybe you already knew this, but you can call uv_async_send from any thread in C and receive it via AsyncCondition in Julia: Calling C and Fortran Code · The Julia Language This handles audio thread-to-Julia part but you would still need to code up Julia-to-audio thread communication. It probably become similar to @cdsousa’s solution in the end but I thought I’d mention uv_async_send anyway.

I don’t think that PR changes anything for non-Julia threads, there is however issue #17573 that is relevant here I think.

@atell_soundtheory - did you ever come up with a solution? Did you try @cdsousa’s suggestion? I’m attempting to use Julia for a LV2 plugin, and I’m coming up against a similar issue.

Thanks,
Oliver

Just wanted to chime in to say that I did manage to embed Julia into a VST plugin.
My solution to the thread problem was to create a dedicated Julia thread.
I initialize Julia in the thread, then it runs a loop waiting for event notifications and checking if it has got any requests to eval Julia code or produce output samples by running a specific Julia function that it has previously compiled.

The real time thread has to send a notification to the Julia thread to do its processing, and wait for it to finish before taking the samples from the buffer. It took some fiddling, but it seems to work pretty well.

However, there is another problem because if you try to initialize Julia more than once in the same process, it crashes. So you can only load the VST once. It was more than a year ago that I worked on this. Maybe the crashing problem might has been fixed since then, I don’t know.

Fortunately, Julia has addressed a number of issues that prevented me from using a multithreaded c-interface with the Julia runtime. Julia now supports foreign threads that can be registered with the runtime so that they crash when calling the runtime. This removes the biggest obstacle for use in a real-time plugin environment. I have not yet found the time to revisit the plugin code, but I’m pretty confident it would work now.

Thanks, might come in handy some time!

Hopefully Julia supports foreign threads so they do not crash.