Re: RTS's (old?) invariant regarding OS blocking

2016-03-03 Thread Dan Aloni
On Thu, Mar 03, 2016 at 09:52:07AM +, Sergei Trofimovich wrote:
> On Wed, 2 Mar 2016 16:38:56 +0200
> Dan Aloni  wrote:
> 
> > Hi,
> > 
> > While trying to gain insights into the RTS, I've noticed the following in
> > the Wiki page [1] on the topic of the scheduler:
> > 
> > Invariant: a task that holds a capability is not blocked in the 
> > operating system.
> > 
> > This makes some parts of the system simpler - for example, we can use 
> > spin locks that spin indefinitely, because we can ensure that the spin lock 
> > is only held by a currently executing CPU, and will therefore be released 
> > in a finite (and short) amount of time.
> > 
> > Does it still apply to modern day GHC, or was it addressed by [2]?
> 
> It still does apply. Foreign calls are by default 'safe' and executed
> after Capability is released to a separate OS thread.
> Capability release is needed as foreign calls can reenter haskell RTS.

Thanks for the elborate example - however my concerns extend beyond
the safe vs. unsafe FFI. I was concerned about the spin lock, and about
hard host kernel scheduling assumptions thereof.

I looked into the GHC code now, and the locks in Capability.c on Linux
seem to translate to pthread_mutex_lock(), which is a futex. This is
a relief. Does the wiki need updating?

--
Dan Aloni
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Re: RTS's (old?) invariant regarding OS blocking

2016-03-03 Thread Sergei Trofimovich
On Wed, 2 Mar 2016 16:38:56 +0200
Dan Aloni  wrote:

> Hi,
> 
> While trying to gain insights into the RTS, I've noticed the following in
> the Wiki page [1] on the topic of the scheduler:
> 
> Invariant: a task that holds a capability is not blocked in the operating 
> system.
> 
> This makes some parts of the system simpler - for example, we can use 
> spin locks that spin indefinitely, because we can ensure that the spin lock 
> is only held by a currently executing CPU, and will therefore be released in 
> a finite (and short) amount of time.
> 
> Does it still apply to modern day GHC, or was it addressed by [2]?

It still does apply. Foreign calls are by default 'safe' and executed
after Capability is released to a separate OS thread.
Capability release is needed as foreign calls can reenter haskell RTS.

You can break that invariant and observe the negative effect.
For example 'unsafe' foreign call to a blocking function stops
all haskell threads happened to be queued on that Capability.

Illustration of adverse effect. [1] runs 2 threads:
- main thread issues 'safe' and 'unsafe' FFI sleeps
- auxiliary thread prints a message on screen every second.

'unsafe_sleep' blocks unrelated haskell thread for 5 seconds
while 'safe_sleep' doesn't.

We disable SIGVTALARM to not interfere with sleep() system call
and use threaded RTS as non-threaded RTS uses SIGVTALARM
for thread switching as well.

$ ghc --make a.hs -o ./a -rtsopts -threaded && ./a +RTS -V0 -N1
[1 of 1] Compiling Main ( a.hs, a.o )
Linking ./a ...

"start unsafe sleep"
"thread: enter"
"done unsafe sleep"
"entering safe sleep"
"*** thread: tick"
"*** thread: tick"
"*** thread: tick"
"*** thread: tick"
"done safe sleep"
"*** thread: tick"
"*** thread: tick"
"*** thread: tick"
"*** thread: tick"
"*** thread: tick"
"*** thread: tick"
"thread: exit"

-- [1]: example program a.hs:
import Control.Concurrent
import Control.Monad
import Foreign.C

foreign import ccall safe "unistd.h sleep"
safe_sleep :: CInt -> IO CInt
foreign import ccall unsafe "unistd.h sleep"
unsafe_sleep :: CInt -> IO CInt

-- sleep for n * 100ms
s :: Int -> IO ()
s slices = threadDelay $ slices * 10^6

main = do
t1_lock <- newEmptyMVar
t1 <- forkIO $ do
print "thread: enter"
replicateM_ 10 $ do
s 1
print "*** thread: tick"
print "thread: exit"
putMVar t1_lock ()

yield -- switch to the ticker

print "start unsafe sleep"
unsafe_sleep 5
print "done unsafe sleep"

print "entering safe sleep"
safe_sleep 5
print "done safe sleep"

takeMVar t1_lock

-- 

  Sergei


signature.asc
Description: PGP signature
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


RTS's (old?) invariant regarding OS blocking

2016-03-02 Thread Dan Aloni
Hi,

While trying to gain insights into the RTS, I've noticed the following in
the Wiki page [1] on the topic of the scheduler:

Invariant: a task that holds a capability is not blocked in the operating 
system.

This makes some parts of the system simpler - for example, we can use spin 
locks that spin indefinitely, because we can ensure that the spin lock is only 
held by a currently executing CPU, and will therefore be released in a finite 
(and short) amount of time.

Does it still apply to modern day GHC, or was it addressed by [2]?

[1] https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Scheduler#Capabilities
[2] https://ghc.haskell.org/trac/ghc/ticket/3553

--
Dan Aloni
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs