[commit: base] master: Separated the IO manager into a timer manager and a file IO manager. (d1461b2)

Johan Tibell johan.tibell at gmail.com
Tue Feb 12 07:49:51 CET 2013


Repository : ssh://darcs.haskell.org//srv/darcs/packages/base

On branch  : master

http://hackage.haskell.org/trac/ghc/changeset/d1461b2a8772392b258c2f532b25ce5d08186281

>---------------------------------------------------------------

commit d1461b2a8772392b258c2f532b25ce5d08186281
Author: Andreas Voellmy <andreas.voellmy at gmail.com>
Date:   Thu Dec 20 00:41:00 2012 -0500

    Separated the IO manager into a timer manager and a file IO manager.
    
    This is a preliminary patch; ultimately the single file IO manager will be replaced by per-capability managers.

>---------------------------------------------------------------

 GHC/Event.hs        |    3 +-
 GHC/Event/Thread.hs |   64 ++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/GHC/Event.hs b/GHC/Event.hs
index 257412f..0510409 100644
--- a/GHC/Event.hs
+++ b/GHC/Event.hs
@@ -14,6 +14,7 @@ module GHC.Event
 
       -- * Creation
     , getSystemEventManager
+    , getSystemTimerManager
 
       -- * Registering interest in I/O events
     , Event
@@ -36,5 +37,5 @@ module GHC.Event
     ) where
 
 import GHC.Event.Manager
-import GHC.Event.Thread (getSystemEventManager)
+import GHC.Event.Thread (getSystemEventManager, getSystemTimerManager)
 
diff --git a/GHC/Event/Thread.hs b/GHC/Event/Thread.hs
index e685108..3cdbdd3 100644
--- a/GHC/Event/Thread.hs
+++ b/GHC/Event/Thread.hs
@@ -3,6 +3,7 @@
 
 module GHC.Event.Thread
     ( getSystemEventManager
+    , getSystemTimerManager
     , ensureIOManagerIsRunning
     , threadWaitRead
     , threadWaitWrite
@@ -13,6 +14,7 @@ module GHC.Event.Thread
     , registerDelay
     ) where
 
+import Control.Exception (finally)
 import Data.IORef (IORef, newIORef, readIORef, writeIORef)
 import Data.Maybe (Maybe(..))
 import Foreign.C.Error (eBADF, errnoToIOError)
@@ -39,7 +41,7 @@ import System.Posix.Types (Fd)
 -- run /earlier/ than specified.
 threadDelay :: Int -> IO ()
 threadDelay usecs = mask_ $ do
-  mgr <- getSystemEventManager
+  mgr <- getSystemTimerManager
   m <- newEmptyMVar
   reg <- registerTimeout mgr usecs (putMVar m ())
   takeMVar m `onException` M.unregisterTimeout mgr reg
@@ -50,7 +52,7 @@ threadDelay usecs = mask_ $ do
 registerDelay :: Int -> IO (TVar Bool)
 registerDelay usecs = do
   t <- atomically $ newTVar False
-  mgr <- getSystemEventManager
+  mgr <- getSystemTimerManager
   _ <- registerTimeout mgr usecs . atomically $ writeTVar t True
   return t
 
@@ -164,16 +166,40 @@ ioManager = unsafePerformIO $ do
    m <- newMVar Nothing
    sharedCAF m getOrSetSystemEventThreadIOManagerThreadStore
 
+getSystemTimerManager :: IO EventManager
+getSystemTimerManager = do 
+  Just mgr <- readIORef timerManager
+  return mgr
+
+foreign import ccall unsafe "getOrSetSystemTimerThreadEventManagerStore"
+    getOrSetSystemTimerThreadEventManagerStore :: Ptr a -> IO (Ptr a)
+
+timerManager :: IORef (Maybe EventManager)
+timerManager = unsafePerformIO $ do
+    em <- newIORef Nothing
+    sharedCAF em getOrSetSystemTimerThreadEventManagerStore
+{-# NOINLINE timerManager #-}
+
+foreign import ccall unsafe "getOrSetSystemTimerThreadIOManagerThreadStore"
+    getOrSetSystemTimerThreadIOManagerThreadStore :: Ptr a -> IO (Ptr a)
+
+{-# NOINLINE timerManagerThreadVar #-}
+timerManagerThreadVar :: MVar (Maybe ThreadId)
+timerManagerThreadVar = unsafePerformIO $ do
+   m <- newMVar Nothing
+   sharedCAF m getOrSetSystemTimerThreadIOManagerThreadStore
+
 ensureIOManagerIsRunning :: IO ()
 ensureIOManagerIsRunning
   | not threaded = return ()
   | otherwise = do
       startIOManagerThread
+      startTimerManagerThread
 
 startIOManagerThread :: IO ()
 startIOManagerThread = modifyMVar_ ioManager $ \old -> do
   let create = do
-        !mgr <- new True
+        !mgr <- new False
         writeIORef eventManager $ Just mgr
         !t <- forkIO $ loop mgr
         labelThread t "IOManager"
@@ -197,4 +223,36 @@ startIOManagerThread = modifyMVar_ ioManager $ \old -> do
           create
         _other         -> return st
 
+startTimerManagerThread :: IO ()
+startTimerManagerThread = modifyMVar_ timerManagerThreadVar $ \old -> do
+  let shutdownEM = do
+        mem <- readIORef eventManager
+        case mem of
+          Nothing -> return ()
+          Just em -> M.shutdown em
+  let create = do
+        !mgr <- new True
+        writeIORef timerManager $ Just mgr
+        !t <- forkIO $ loop mgr `finally` shutdownEM
+        labelThread t "TimerManager"
+        return $ Just t
+  case old of
+    Nothing            -> create
+    st@(Just t) -> do
+      s <- threadStatus t
+      case s of
+        ThreadFinished -> create
+        ThreadDied     -> do 
+          -- Sanity check: if the thread has died, there is a chance
+          -- that event manager is still alive. This could happend during
+          -- the fork, for example. In this case we should clean up
+          -- open pipes and everything else related to the event manager.
+          -- See #4449
+          mem <- readIORef timerManager
+          _ <- case mem of
+                 Nothing -> return ()
+                 Just em -> M.cleanup em
+          create
+        _other         -> return st
+
 foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool





More information about the ghc-commits mailing list