Why do remaining HECs busy-wait during unsafe-FFI calls?
Herbert Valerio Riedel
hvr at gnu.org
Mon May 6 13:29:29 CEST 2013
Hello,
Recently, I stumbled over E.Z.Yang's "Safety first: FFI and
threading"[1] post and then while experimenting with unsafe-imported FFI
functions I've noticed a somewhat surprising behaviour:
Consider the following contrived program:
--8<---------------cut here---------------start------------->8---
import Foreign.C
import Control.Concurrent
import Control.Monad
import Data.Time.Clock.POSIX (getPOSIXTime)
foreign import ccall unsafe "unistd.h sleep" c_sleep_unsafe :: CUInt -> IO CUInt
main :: IO ()
main = do
putStrLnTime "main started"
_ <- forkIO (sleepLoop 10 >> putStrLnTime "sleepLoop finished")
yield
putStrLnTime "after forkIO"
threadDelay (11*1000*1000) -- 11 seconds
putStrLnTime "end of main"
where
putStrLnTime s = do
t <- getPOSIXTime
putStrLn $ init (show t) ++ "\t" ++ s
sleepLoop n = do
n' <- c_sleep_unsafe n
unless (n' == 0) $ do
putStrLnTime "c_sleep_unsafe got interrupted"
sleepLoop n'
--8<---------------cut here---------------end--------------->8---
When compiled with GHC-7.6.3/linux/amd64 with "-O2 -threaded" and
executed with "+RTS -N4", the following output is emitted:
1367838802.137419 main started
1367838812.137727 after forkIO
1367838812.137783 sleepLoop finished
1367838823.148733 end of main
which shows that the forkIO of the unsafe ccall effectively blocks the
main thread;
Moreover, when looking at the process table, I saw that 3 threads were
occupying 100% CPU time each for 10 seconds until the 'after forkIO' was
emitted.
So what is happening here exactly, why do the 3 remaining HECs busy-wait
during that FFI call instead of continuing the execution of the main
thread?
Do *all* foreign unsafe ccalls (even short ones) cause N-1 HECs to spend
time in some kind of busy looping?
[1]: http://blog.ezyang.com/2010/07/safety-first-ffi-and-threading/
Cheers,
hvr
More information about the Glasgow-haskell-users
mailing list