[commit: base] : Lock stripe the callback table in the IO managers. (5f8a3fc)

Johan Tibell johan.tibell at gmail.com
Tue Feb 12 07:50:35 CET 2013


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

On branch  : 

http://hackage.haskell.org/trac/ghc/changeset/5f8a3fc24c374f162e8bd03baa2a5d252bb990c6

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

commit 5f8a3fc24c374f162e8bd03baa2a5d252bb990c6
Author: Andreas Voellmy <andreas.voellmy at gmail.com>
Date:   Thu Dec 20 14:54:00 2012 -0500

    Lock stripe the callback table in the IO managers.

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

 GHC/Event/Manager.hs |   32 +++++++++++++++++++++-----------
 1 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/GHC/Event/Manager.hs b/GHC/Event/Manager.hs
index 726d77e..80bdcc9 100644
--- a/GHC/Event/Manager.hs
+++ b/GHC/Event/Manager.hs
@@ -50,16 +50,17 @@ module GHC.Event.Manager
 
 import Control.Concurrent.MVar (MVar, modifyMVar, newMVar, readMVar)
 import Control.Exception (finally)
-import Control.Monad ((=<<), forM_, liftM, sequence_, when)
+import Control.Monad ((=<<), forM_, liftM, sequence_, when, replicateM)
 import Data.IORef (IORef, atomicModifyIORef, mkWeakIORef, newIORef, readIORef,
                    writeIORef)
 import Data.Maybe (Maybe(..))
 import Data.Monoid (mappend, mconcat, mempty)
+import GHC.Arr (Array, (!), listArray)
 import GHC.Base
 import GHC.Conc.Signal (runHandlers)
 import GHC.List (filter)
 import GHC.Num (Num(..))
-import GHC.Real ((/), fromIntegral )
+import GHC.Real ((/), fromIntegral, mod)
 import GHC.Show (Show(..))
 import GHC.Event.Control
 import GHC.Event.Internal (Backend, Event, evtClose, evtRead, evtWrite,
@@ -107,14 +108,22 @@ data State = Created
 -- | The event manager state.
 data EventManager = EventManager
     { emBackend      :: !Backend
-    , emFds          :: {-# UNPACK #-} !(MVar (IM.IntMap [FdData]))
+    , emFds          :: {-# UNPACK #-} !(Array Int (MVar (IM.IntMap [FdData])))
     , emState        :: {-# UNPACK #-} !(IORef State)
     , emUniqueSource :: {-# UNPACK #-} !UniqueSource
     , emControl      :: {-# UNPACK #-} !Control
     }
 
+callbackArraySize :: Int
+callbackArraySize = 32
+
+hashFd :: Fd -> Int
+hashFd fd = fromIntegral fd `mod` callbackArraySize
+{-# INLINE hashFd #-}
+
 callbackTableVar :: EventManager -> Fd -> MVar (IM.IntMap [FdData])
-callbackTableVar mgr _ = emFds mgr
+callbackTableVar mgr fd = emFds mgr ! hashFd fd
+{-# INLINE callbackTableVar #-}
 ------------------------------------------------------------------------
 -- Creation
 
@@ -143,7 +152,8 @@ new = newWith =<< newDefaultBackend
 
 newWith :: Backend -> IO EventManager
 newWith be = do
-  iofds <- newMVar IM.empty
+  iofds <- fmap (listArray (0, callbackArraySize-1)) $
+           replicateM callbackArraySize (newMVar IM.empty)
   ctrl <- newControl False
   state <- newIORef Created
   us <- newSource
@@ -214,9 +224,9 @@ step mgr at EventManager{..} = do
 -- event manager ought to be woken.
 registerFd_ :: EventManager -> IOCallback -> Fd -> Event
             -> IO (FdKey, Bool)
-registerFd_ EventManager{..} cb fd evs = do
+registerFd_ mgr@(EventManager{..}) cb fd evs = do
   u <- newUnique emUniqueSource
-  modifyMVar emFds $ \oldMap -> do
+  modifyMVar (callbackTableVar mgr fd) $ \oldMap -> do
     let fd'  = fromIntegral fd
         reg  = FdKey fd u
         !fdd = FdData reg evs cb
@@ -257,8 +267,8 @@ pairEvents prev m fd = let l = eventsOf prev
 -- event manager thread.  The return value indicates whether the event
 -- manager ought to be woken.
 unregisterFd_ :: EventManager -> FdKey -> IO Bool
-unregisterFd_ EventManager{..} (FdKey fd u) =
-  modifyMVar emFds $ \oldMap -> do
+unregisterFd_ mgr@(EventManager{..}) (FdKey fd u) =
+  modifyMVar (callbackTableVar mgr fd) $ \oldMap -> do
     let dropReg cbs = case filter ((/= u) . keyUnique . fdKey) cbs of
                           []   -> Nothing
                           cbs' -> Just cbs'
@@ -280,7 +290,7 @@ unregisterFd mgr reg = do
 -- | Close a file descriptor in a race-safe way.
 closeFd :: EventManager -> (Fd -> IO ()) -> Fd -> IO ()
 closeFd mgr close fd = do
-  fds <- modifyMVar (emFds mgr) $ \oldMap -> do
+  fds <- modifyMVar (callbackTableVar mgr fd) $ \oldMap -> do
     close fd
     case IM.delete (fromIntegral fd) oldMap of
       (Nothing,  _)       -> return (oldMap, [])
@@ -307,7 +317,7 @@ closeFd_ mgr oldMap fd = do
 -- | Call the callbacks corresponding to the given file descriptor.
 onFdEvent :: EventManager -> Fd -> Event -> IO ()
 onFdEvent mgr fd evs = do
-  fds <- readMVar (emFds mgr)
+  fds <- readMVar (callbackTableVar mgr fd)
   case IM.lookup (fromIntegral fd) fds of
       Just cbs -> forM_ cbs $ \(FdData reg ev cb) ->
                     when (evs `I.eventIs` ev) $ cb reg evs





More information about the ghc-commits mailing list