Blocking a task indefinitely in the RTS
lonetiger at gmail.com
Sun Jan 6 18:37:17 UTC 2019
I'm looking for a way to block a task indefinitely until it is woken up by
an external event in both the threaded and non-threaded RTS and returns a
value that was stored/passed. MVar works great for the threaded RTS, but
for the non-threaded there's a bunch of deadlock detection in the scheduler
that would forcibly free the lock and resume the task with an opaque
exception. This means that MVar and anything derived from it is not usable.
STMs are more expensive but also have the same deadlock code. So again no
go. The reason it looks like a deadlock to the RTS is that the "Wake-up"
call in the non-threaded rts will come from C code running inside the RTS.
The RTS essentially just sees all tasks blocked on it's main capability and
(usually rightly so) assumes a deadlock occurred.
You have other states like BlockedOnForeign etc but those are not usable as
a primitive. Previous iterations of I/O managers have each invented
primitives for this such as asyncRead#, but they are not general and can't
be re-used, and requires a different solution for threaded and non-threaded.
I have started making a new primitive IOPort for this, based on the MVar
code, but this is not trivial... (currently I'm getting a segfault
*somewhere* in the primitive's cmm code). The reason is that the semantics
are decidedly different from what MVars guarantee. I should also mention
that this is meant to be internal to base (i.e no exported).
So before I continue down this path and some painful debugging..., does
anyone know of a way to block a task, unblock it later and pass a value
back? It does not need to support anything complicated such as multiple
take/put requests etc.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the ghc-devs