File: Mmap.hsc

package info (click to toggle)
haskell-hashable 1.2.1.0-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 196 kB
  • ctags: 39
  • sloc: haskell: 975; ansic: 456; makefile: 3
file content (73 lines) | stat: -rw-r--r-- 2,416 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{-# LANGUAGE ForeignFunctionInterface #-}

module Regress.Mmap (regressions) where

#include <sys/mman.h>

import Control.Exception (bracket, evaluate)
import Control.Monad (forM_)
import Data.Bits ((.|.))
import Data.ByteString.Internal (ByteString(..))
import Data.Hashable (hash)
import Foreign.C.Error (throwErrnoIf, throwErrnoIfMinus1, throwErrnoIfMinus1_)
import Foreign.C.Types (CInt(..), CSize(..))
import Foreign.Ptr (Ptr, intPtrToPtr, nullPtr, plusPtr)
import GHC.ForeignPtr (newForeignPtr_)
import System.Posix.Types (COff(..))
import Test.Framework (Test)
import Test.Framework.Providers.HUnit (testCase)
import qualified Data.ByteString as B

withMapping :: (Ptr a -> Int -> IO ()) -> IO ()
withMapping go = do
  pageSize <- fromIntegral `fmap` getPageSize
  let mappingSize = pageSize * 2
  bracket (mmap
           nullPtr
           mappingSize
           ((#const PROT_READ) .|. (#const PROT_WRITE))
           ((#const MAP_ANON) .|. (#const MAP_PRIVATE))
           (-1)
           0)
           (flip munmap mappingSize) $ \mappingPtr -> do
    go mappingPtr (fromIntegral pageSize)
    mprotect (mappingPtr `plusPtr` fromIntegral pageSize)
             pageSize (#const PROT_NONE)

hashNearPageBoundary :: IO ()
hashNearPageBoundary =
  withMapping $ \ptr pageSize -> do
    let initialSize = 16
    fp <- newForeignPtr_ (ptr `plusPtr` (pageSize - initialSize))
    let bs0 = PS fp 0 initialSize
    forM_ (B.tails bs0) $ \bs -> do
      evaluate (hash bs)

regressions :: [Test]
regressions = [
   testCase "hashNearPageBoundary" hashNearPageBoundary
 ]

mmap :: Ptr a -> CSize -> CInt -> CInt -> CInt -> COff -> IO (Ptr a)
mmap addr len prot flags fd offset =
    throwErrnoIf (== intPtrToPtr (#const MAP_FAILED)) "mmap" $
    c_mmap addr len prot flags fd offset

munmap :: Ptr a -> CSize -> IO CInt
munmap addr len = throwErrnoIfMinus1 "munmap" $ c_munmap addr len

mprotect :: Ptr a -> CSize -> CInt -> IO ()
mprotect addr len prot =
    throwErrnoIfMinus1_ "mprotect" $ c_mprotect addr len prot

foreign import ccall unsafe "sys/mman.h mmap"
    c_mmap :: Ptr a -> CSize -> CInt -> CInt -> CInt -> COff -> IO (Ptr a)

foreign import ccall unsafe "sys/mman.h munmap"
    c_munmap :: Ptr a -> CSize -> IO CInt

foreign import ccall unsafe "sys/mman.h mprotect"
    c_mprotect :: Ptr a -> CSize -> CInt -> IO CInt

foreign import ccall unsafe "unistd.h getpagesize"
    getPageSize :: IO CInt