Blocking a task indefinitely in the RTS

Phyx lonetiger at gmail.com
Mon Jan 7 22:09:18 UTC 2019


Hi Phil,

Thanks for the reply, however that just gives me a forced deadlock removal
as before.

new bound thread (1)
cap 0: schedule()
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (blocked on an MVar)
        thread    1 @ 0000000003205388 is blocked on an MVar @
00000000032040c8 (TSO_DIRTY)
deadlocked, forcing major GC...
all threads:
threads on capability 0:
other threads:
        thread    1 @ 0000000003205388 is blocked on an MVar @
00000000032040c8 (TSO_DIRTY)
cap 0: starting GC

I don't believe any solution involving MVars will work for the non-threaded
RTS. Though I'd love to be wrong here...

Regards,
Tamar

On Sun, Jan 6, 2019 at 9:38 PM Phil Ruffwind <rf at rufflewind.com> wrote:

> What if you wrap the MVar in a foreign closure?
>
>     import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)
>     import Control.Exception (bracket)
>     import Foreign.Ptr (FunPtr, freeHaskellFunPtr)
>
>     foreign import ccall "wrapper" wrapAwaken :: IO () -> IO (FunPtr (IO
> ()))
>
>     main = do
>       mvar <- newEmptyMVar
>       bracket (wrapAwaken (putMVar mvar ())) freeHaskellFunPtr $ \ awaken
> -> do
>         -- giveToExternalCode awaken
>         takeMVar mvar
>
> On Sun, Jan 6, 2019, at 10:37, Phyx wrote:
> > Hi All,
> >
> > 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.
> >
> > Cheers,
> > Tamar
> > _______________________________________________
> > ghc-devs mailing list
> > ghc-devs at haskell.org
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-devs/attachments/20190107/cc532d42/attachment.html>


More information about the ghc-devs mailing list