{-# LANGUAGE ForeignFunctionInterface #-}
--------------------------------------------------------------------
-- |
-- Module    :  System.IO.Posix.MMap.Internal
-- Copyright :  (c) Galois, Inc. 2007
-- License   :  BSD3
--
-- Maintainer:  Don Stewart <dons@galois.com>
-- Stability :  provisional
-- Portability: non-portable -- posix only
--
-- Low level mmap access.
--
module System.IO.Posix.MMap.Internal (

    -- * Converting an mmapped pointer to a 'ByteString'
    unsafePackMMapPtr,      -- :: Ptr Word8 -> CSize -> IO ByteString

    -- * Low level bindings
    c_mmap,                 -- :: CSize -> CInt -> IO (Ptr Word8)
    c_munmap                -- :: Ptr Word8 -> CSize -> IO CInt

  ) where

import System.IO
import qualified System.IO as IO
import Foreign.C.Types
import Foreign.Ptr
import qualified Foreign.Concurrent as FC

import Control.Monad
import Data.Word
import Data.ByteString.Internal
-- import Data.ByteString

-- | Create a bytestring from a memory mapped Ptr.
-- A finalizer will be associated with the resource, that will call
-- munmap when the storage manager detects that the resource is no longer
-- in use.
unsafePackMMapPtr :: Ptr Word8 -> CSize -> IO ByteString
unsafePackMMapPtr :: Ptr Word8 -> CSize -> IO ByteString
unsafePackMMapPtr p :: Ptr Word8
p s :: CSize
s = do
    ForeignPtr Word8
fp <- Ptr Word8 -> IO () -> IO (ForeignPtr Word8)
forall a. Ptr a -> IO () -> IO (ForeignPtr a)
FC.newForeignPtr Ptr Word8
p (IO () -> IO (ForeignPtr Word8)) -> IO () -> IO (ForeignPtr Word8)
forall a b. (a -> b) -> a -> b
$ do
                 CInt
v <- Ptr Word8 -> CSize -> IO CInt
c_munmap Ptr Word8
p CSize
s
                 Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
v CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== -1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Handle -> String -> IO ()
IO.hPutStrLn Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
                         "System.IO.Posix.MMap: warning, failed to unmap "
                          String -> String -> String
forall a. [a] -> [a] -> [a]
++ CSize -> String
forall a. Show a => a -> String
show CSize
s String -> String -> String
forall a. [a] -> [a] -> [a]
++" bytes at "String -> String -> String
forall a. [a] -> [a] -> [a]
++Ptr Word8 -> String
forall a. Show a => a -> String
show Ptr Word8
p
    ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr Word8 -> Int -> Int -> ByteString
fromForeignPtr ForeignPtr Word8
fp 0 (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
s))
{-# INLINE unsafePackMMapPtr #-}

foreign import ccall unsafe "hs_bytestring_mmap.h hs_bytestring_mmap"
    c_mmap   :: CSize -> CInt -> IO (Ptr Word8)

foreign import ccall unsafe "hs_bytestring_mmap.h munmap"
    c_munmap :: Ptr Word8 -> CSize -> IO CInt