Thoughts on async RTS API?

Cheng Shao cheng.shao at tweag.io
Wed Dec 15 02:06:34 UTC 2021


Hi devs,

To invoke Haskell computation in C, we need to call one of rts_eval*
functions, which enters the scheduler loop, and returns only when the
specified Haskell thread is finished or killed. We'd like to enhance
the scheduler and add async variants of the rts_eval* functions, which
take C callbacks to consume the Haskell thread result, kick off the
scheduler loop, and the loop is allowed to exit when the Haskell
thread is blocked. Sync variants of RTS API will continue to work with
unchanged behavior.

The main intended use case is async foreign calls for the WebAssembly
target. When an async foreign call is made, the Haskell thread will
block on an MVar to be fulfilled with the call result. But the
scheduler will eventually fail to find work due to empty run queue and
exit with error! We need a way to gracefully exit the scheduler, so
the RTS API caller can process the async foreign call, fulfill that
MVar and resume Haskell computation later.

Question I: does the idea of adding async RTS API sound acceptable by
GHC HQ? To be honest, it's not impossible to workaround lack of async
RTS API: reuse the awaitEvent() logic in non-threaded RTS, pretend
each async foreign call reads from a file descriptor and can be
handled by the POSIX select() function in awaitEvent(). But it'd
surely be nice to avoid such hacks and do things the principled way.

Question II: how to modify the scheduler loop to implement this
feature? Straightforward answer seems to be: check some RTS API
non-blocking flag, if present, allow early exit due to empty run
queue.

Thanks a lot for reading this, I appreciate any suggestions or
questions :)

Best regards,
Cheng


More information about the ghc-devs mailing list