@async calls to C API yields?

But then I don’t think you can do the IO while calling yield? I suppose all the IO has to go through the event loop in order to do them concurrently (non-blockingly).

IIUC, if you need to do IO without touching libuv’s IO interface, then you have to do it in a different thread. To ping Julia to come back to the C function in the main thread, you call uv_async_send(cond.handle) from the IO thread once the IO is finished, where this cond is created with Base.AsyncCondition. You can call Julia code wait(cond) in the thread that initialized Julia. During this wait(cond), Julia can run other tasks and block until uv_async_send. (Not sure if this is the only solution. It’s just what I know.)