riot
riot copied to clipboard
Support spawning blocking Riot processes
In many cases we want to execute some work that does not play well with Riot's scheduling, that wouldn't play well with work-stealing, that needs to use libraries that don't play well with Riot's IO, or that simply need to aggressively busy-wait to meet certain real-time deadlines (like rendering a frame within 16ms).
For those use-cases, spawn
, spawn_pinned
, and process_flag (Priority High)
are not suitable solutions since they all expect the process to not starve the scheduler, to be friendly to work-stealing, and to use Riot's IO layer.
Instead, we'd like to implement spawn_blocking fn
which will create a new process, like any other process, but allocate an entire OS thread to execute it.
The signature of this function would be identical to spawn
:
val spanw_blocking : (unit -> unit) -> Pid.t
Implementation Notes
To do this, we'd start by adding the signature to the riot.mli
file, and working backwards from there until we reach the imports.ml
module where spawn
and spawn_pinned
are defined. This function should probably call into a function like Pool.spawn_blocking
that will do the work of setting up a new scheduler just for this process, and updating the list of domains in the global pool
variable.
Then we'd want the pool
type inside the scheduler.ml
module to be extended to include a list of Domains that have been spawned for these blocking processes:
type pool = {
(* ... *)
blocking_processes: unit Domain.t list Atomic.t;
}
It is important that we make this list atomic to make sure that multiple processes spawning new blocking processes from different scheduling threads do not override the domain handlers.
The final set of changes could look a little bit like this, but this list is not a set of requirements and other implementations are welcome:
- new
spawn_blocking
function with its signature and documentation on Riot.mli - new
Pool.spawn_blocking
function that uses a newBlocking_scheduler
in a new Domain - new
blocking_processes
attribute on thepool
type to keep track of new domains - new
Blocking_scheduler
that wraps aScheduler
and adds logic for removing the domains from theblocking_processes
domain list
Hope this helps!
Do you have any ideas what might make a good small test I can add or an example of it working correctly to test its behaviour in the repo?
Hmm, off the top of my head we could spin up a blocking process to run some function (eg. count up to max int in a hot loop), and set up a receive (with timeout) on the main process so we terminate the test when the blocking process sends the max int value back in.
I don't think its a particularly good test, but at least it'd exercise that we can have a blocking process running work, and regular processes doing work at the same time.