{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude #-}
module GHC.Internal.Conc.Signal
        ( Signal
        , HandlerFun
        , setHandler
        , runHandlers
        , runHandlersPtr
        ) where
import GHC.Internal.Control.Concurrent.MVar (MVar, newMVar, withMVar)
import GHC.Internal.Data.Dynamic (Dynamic)
import GHC.Internal.Foreign.C.Types (CInt)
import GHC.Internal.Foreign.ForeignPtr (ForeignPtr, newForeignPtr)
import GHC.Internal.Foreign.StablePtr (castPtrToStablePtr, castStablePtrToPtr,
                          deRefStablePtr, freeStablePtr, newStablePtr)
import GHC.Internal.Foreign.Ptr (Ptr, castPtr)
import GHC.Internal.Foreign.Marshal.Alloc (finalizerFree)
import GHC.Internal.Arr (inRange)
import GHC.Internal.Base
import GHC.Internal.Conc.Sync (forkIO)
import GHC.Internal.IO (mask_, unsafePerformIO)
import GHC.Internal.IOArray (IOArray, boundsIOArray, newIOArray,
                    unsafeReadIOArray, unsafeWriteIOArray)
import GHC.Internal.Real (fromIntegral)
import GHC.Internal.Word (Word8)
type Signal = CInt
maxSig :: Int
maxSig :: Int
maxSig = Int
64
type HandlerFun = ForeignPtr Word8 -> IO ()
signal_handlers :: MVar (IOArray Int (Maybe (HandlerFun,Dynamic)))
signal_handlers :: MVar (IOArray Int (Maybe (HandlerFun, Dynamic)))
signal_handlers = IO (MVar (IOArray Int (Maybe (HandlerFun, Dynamic))))
-> MVar (IOArray Int (Maybe (HandlerFun, Dynamic)))
forall a. IO a -> a
unsafePerformIO (IO (MVar (IOArray Int (Maybe (HandlerFun, Dynamic))))
 -> MVar (IOArray Int (Maybe (HandlerFun, Dynamic))))
-> IO (MVar (IOArray Int (Maybe (HandlerFun, Dynamic))))
-> MVar (IOArray Int (Maybe (HandlerFun, Dynamic)))
forall a b. (a -> b) -> a -> b
$ do
  arr <- (Int, Int)
-> Maybe (HandlerFun, Dynamic)
-> IO (IOArray Int (Maybe (HandlerFun, Dynamic)))
forall i e. Ix i => (i, i) -> e -> IO (IOArray i e)
newIOArray (Int
0, Int
maxSig) Maybe (HandlerFun, Dynamic)
forall a. Maybe a
Nothing
  m <- newMVar arr
  sharedCAF m getOrSetGHCConcSignalSignalHandlerStore
{-# NOINLINE signal_handlers #-}
foreign import ccall unsafe "getOrSetGHCConcSignalSignalHandlerStore"
  getOrSetGHCConcSignalSignalHandlerStore :: Ptr a -> IO (Ptr a)
setHandler :: Signal -> Maybe (HandlerFun, Dynamic)
           -> IO (Maybe (HandlerFun, Dynamic))
setHandler :: Signal
-> Maybe (HandlerFun, Dynamic) -> IO (Maybe (HandlerFun, Dynamic))
setHandler Signal
sig Maybe (HandlerFun, Dynamic)
handler = do
  let int :: Int
int = Signal -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Signal
sig
  MVar (IOArray Int (Maybe (HandlerFun, Dynamic)))
-> (IOArray Int (Maybe (HandlerFun, Dynamic))
    -> IO (Maybe (HandlerFun, Dynamic)))
-> IO (Maybe (HandlerFun, Dynamic))
forall a b. MVar a -> (a -> IO b) -> IO b
withMVar MVar (IOArray Int (Maybe (HandlerFun, Dynamic)))
signal_handlers ((IOArray Int (Maybe (HandlerFun, Dynamic))
  -> IO (Maybe (HandlerFun, Dynamic)))
 -> IO (Maybe (HandlerFun, Dynamic)))
-> (IOArray Int (Maybe (HandlerFun, Dynamic))
    -> IO (Maybe (HandlerFun, Dynamic)))
-> IO (Maybe (HandlerFun, Dynamic))
forall a b. (a -> b) -> a -> b
$ \IOArray Int (Maybe (HandlerFun, Dynamic))
arr ->
    if Bool -> Bool
not ((Int, Int) -> Int -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (IOArray Int (Maybe (HandlerFun, Dynamic)) -> (Int, Int)
forall i e. IOArray i e -> (i, i)
boundsIOArray IOArray Int (Maybe (HandlerFun, Dynamic))
arr) Int
int)
      then [Char] -> IO (Maybe (HandlerFun, Dynamic))
forall a. [Char] -> a
errorWithoutStackTrace [Char]
"GHC.Internal.Conc.setHandler: signal out of range"
      else do old <- IOArray Int (Maybe (HandlerFun, Dynamic))
-> Int -> IO (Maybe (HandlerFun, Dynamic))
forall i e. IOArray i e -> Int -> IO e
unsafeReadIOArray IOArray Int (Maybe (HandlerFun, Dynamic))
arr Int
int
              unsafeWriteIOArray arr int handler
              return old
runHandlers :: ForeignPtr Word8 -> Signal -> IO ()
runHandlers :: ForeignPtr Word8 -> Signal -> IO ()
runHandlers ForeignPtr Word8
p_info Signal
sig = do
  let int :: Int
int = Signal -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Signal
sig
  MVar (IOArray Int (Maybe (HandlerFun, Dynamic)))
-> (IOArray Int (Maybe (HandlerFun, Dynamic)) -> IO ()) -> IO ()
forall a b. MVar a -> (a -> IO b) -> IO b
withMVar MVar (IOArray Int (Maybe (HandlerFun, Dynamic)))
signal_handlers ((IOArray Int (Maybe (HandlerFun, Dynamic)) -> IO ()) -> IO ())
-> (IOArray Int (Maybe (HandlerFun, Dynamic)) -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \IOArray Int (Maybe (HandlerFun, Dynamic))
arr ->
    if Bool -> Bool
not ((Int, Int) -> Int -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (IOArray Int (Maybe (HandlerFun, Dynamic)) -> (Int, Int)
forall i e. IOArray i e -> (i, i)
boundsIOArray IOArray Int (Maybe (HandlerFun, Dynamic))
arr) Int
int)
      then () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      else do handler <- IOArray Int (Maybe (HandlerFun, Dynamic))
-> Int -> IO (Maybe (HandlerFun, Dynamic))
forall i e. IOArray i e -> Int -> IO e
unsafeReadIOArray IOArray Int (Maybe (HandlerFun, Dynamic))
arr Int
int
              case handler of
                Maybe (HandlerFun, Dynamic)
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                Just (HandlerFun
f,Dynamic
_)  -> do _ <- IO () -> IO ThreadId
forkIO (HandlerFun
f ForeignPtr Word8
p_info)
                                  return ()
runHandlersPtr :: Ptr Word8 -> Signal -> IO ()
runHandlersPtr :: Ptr Word8 -> Signal -> IO ()
runHandlersPtr Ptr Word8
p Signal
s = do
  fp <- FinalizerPtr Word8 -> Ptr Word8 -> IO (ForeignPtr Word8)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr Word8
forall a. FinalizerPtr a
finalizerFree Ptr Word8
p
  runHandlers fp s
sharedCAF :: a -> (Ptr a -> IO (Ptr a)) -> IO a
sharedCAF :: forall a. a -> (Ptr a -> IO (Ptr a)) -> IO a
sharedCAF a
a Ptr a -> IO (Ptr a)
get_or_set =
  IO a -> IO a
forall a. IO a -> IO a
mask_ (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
    stable_ref <- a -> IO (StablePtr a)
forall a. a -> IO (StablePtr a)
newStablePtr a
a
    let ref = Ptr () -> Ptr b
forall a b. Ptr a -> Ptr b
castPtr (StablePtr a -> Ptr ()
forall a. StablePtr a -> Ptr ()
castStablePtrToPtr StablePtr a
stable_ref)
    ref2 <- get_or_set ref
    if ref == ref2
      then return a
      else do freeStablePtr stable_ref
              deRefStablePtr (castPtrToStablePtr (castPtr ref2))