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