{-# OPTIONS_GHC -optc-DSUPPORT_RUSAGE #-}
{-# LINE 1 "Gauge/Source/RUsage.hsc" #-}
-- |
-- Module      : Gauge.Source.RUsage
-- Copyright   : (c) 2017 Vincent Hanquez
--
-- A bindings to POSIX getrusage()
--

{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
module Gauge.Source.RUsage
    ( Who
    , pattern Self
    , pattern Children
    , RUsage(..)
    , TimeVal(..)
    , get
    , with
    , supported
    ) where


{-# LINE 23 "Gauge/Source/RUsage.hsc" #-}


{-# LINE 25 "Gauge/Source/RUsage.hsc" #-}


{-# LINE 27 "Gauge/Source/RUsage.hsc" #-}

import Control.Applicative
import Foreign.C.Error (throwErrnoIfMinus1_)
import Foreign.Storable
import Foreign.Ptr
import Foreign.Marshal.Alloc





{-# LINE 40 "Gauge/Source/RUsage.hsc" #-}

import Gauge.Time (MicroSeconds(..))
import Foreign.C.Types
import Data.Word
import Prelude -- Silence redundant import warnings

{- struct rusage :
struct timeval ru_utime; /* user CPU time used */
struct timeval ru_stime; /* system CPU time used */
long   ru_maxrss;        /* maximum resident set size */
long   ru_ixrss;         /* integral shared memory size */
long   ru_idrss;         /* integral unshared data size */
long   ru_isrss;         /* integral unshared stack size */
long   ru_minflt;        /* page reclaims (soft page faults) */
long   ru_majflt;        /* page faults (hard page faults) */
long   ru_nswap;         /* swaps */
long   ru_inblock;       /* block input operations */
long   ru_oublock;       /* block output operations */
long   ru_msgsnd;        /* IPC messages sent */
long   ru_msgrcv;        /* IPC messages received */
long   ru_nsignals;      /* signals received */
long   ru_nvcsw;         /* voluntary context switches */
long   ru_nivcsw;        /* involuntary context switches */
-}

data RUsage = RUsage
    { userCpuTime               :: {-# UNPACK #-} !TimeVal
    , systemCpuTime             :: {-# UNPACK #-} !TimeVal
    , maxResidentSetSize        :: {-# UNPACK #-} !Word64
    , iSharedMemorySize         :: {-# UNPACK #-} !Word64
    , iUnsharedDataSize         :: {-# UNPACK #-} !Word64
    , iUnsharedStackSize        :: {-# UNPACK #-} !Word64
    , minorFault                :: {-# UNPACK #-} !Word64
    , majorFault                :: {-# UNPACK #-} !Word64
    , nSwap                     :: {-# UNPACK #-} !Word64
    , inBlock                   :: {-# UNPACK #-} !Word64
    , outBlock                  :: {-# UNPACK #-} !Word64
    , msgSend                   :: {-# UNPACK #-} !Word64
    , msgRecv                   :: {-# UNPACK #-} !Word64
    , nSignals                  :: {-# UNPACK #-} !Word64
    , nVoluntaryContextSwitch   :: {-# UNPACK #-} !Word64
    , nInvoluntaryContextSwitch :: {-# UNPACK #-} !Word64
    } deriving (Show, Eq)

newtype TimeVal = TimeVal MicroSeconds
    deriving (Show,Eq)


{-# LINE 88 "Gauge/Source/RUsage.hsc" #-}

instance Storable RUsage where
    alignment _ = 8
    sizeOf _ = sizeRUsage
    peek p = RUsage <$> ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p
{-# LINE 93 "Gauge/Source/RUsage.hsc" #-}
                    <*> ((\hsc_ptr -> peekByteOff hsc_ptr 16)) p
{-# LINE 94 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 32)) p) )
{-# LINE 95 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 40)) p) )
{-# LINE 96 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 48)) p) )
{-# LINE 97 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 56)) p) )
{-# LINE 98 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 64)) p) )
{-# LINE 99 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 72)) p) )
{-# LINE 100 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 80)) p) )
{-# LINE 101 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 88)) p) )
{-# LINE 102 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 96)) p) )
{-# LINE 103 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 104)) p) )
{-# LINE 104 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 112)) p) )
{-# LINE 105 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 120)) p) )
{-# LINE 106 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 128)) p) )
{-# LINE 107 "Gauge/Source/RUsage.hsc" #-}
                    <*> (clongToW64 <$> ( ((\hsc_ptr -> peekByteOff hsc_ptr 136)) p) )
{-# LINE 108 "Gauge/Source/RUsage.hsc" #-}
      where

    poke p (RUsage utime stime maxrss ixrss idrss isrss minflt majflt nswap
            inblock oublock msgsnd msgrcv nsignals nvcsw nivcsw) = do
        ((\hsc_ptr -> pokeByteOff hsc_ptr 0))    p utime
{-# LINE 113 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 16))    p stime
{-# LINE 114 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 32))   p (w64ToCLong maxrss)
{-# LINE 115 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 40))    p (w64ToCLong ixrss)
{-# LINE 116 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 48))    p (w64ToCLong idrss)
{-# LINE 117 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 56))    p (w64ToCLong isrss)
{-# LINE 118 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 64))   p (w64ToCLong minflt)
{-# LINE 119 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 72))   p (w64ToCLong majflt)
{-# LINE 120 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 80))    p (w64ToCLong nswap)
{-# LINE 121 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 88))  p (w64ToCLong inblock)
{-# LINE 122 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 96))  p (w64ToCLong oublock)
{-# LINE 123 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 104))   p (w64ToCLong msgsnd)
{-# LINE 124 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 112))   p (w64ToCLong msgrcv)
{-# LINE 125 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 120)) p (w64ToCLong nsignals)
{-# LINE 126 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 128))    p (w64ToCLong nvcsw)
{-# LINE 127 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 136))   p (w64ToCLong nivcsw)
{-# LINE 128 "Gauge/Source/RUsage.hsc" #-}

instance Storable TimeVal where
    alignment _ = 8
    sizeOf _ = 16
{-# LINE 132 "Gauge/Source/RUsage.hsc" #-}
    peek p = toTimeVal <$> ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p
{-# LINE 133 "Gauge/Source/RUsage.hsc" #-}
                       <*> ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p
{-# LINE 134 "Gauge/Source/RUsage.hsc" #-}
      where toTimeVal !s !us = TimeVal $! MicroSeconds $! (clongToW64 s * secondsToMicroScale) + clongToW64 us
    poke p (TimeVal (MicroSeconds cus)) = do
        ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) p (w64ToCLong s)
{-# LINE 137 "Gauge/Source/RUsage.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) p (w64ToCLong us)
{-# LINE 138 "Gauge/Source/RUsage.hsc" #-}
      where (s, us) = cus `divMod` secondsToMicroScale

secondsToMicroScale :: Word64
secondsToMicroScale = 1000000

w64ToCLong :: Word64 -> CLong
w64ToCLong = fromIntegral

clongToW64 :: CLong -> Word64
clongToW64 = fromIntegral

sizeRUsage :: Int
sizeRUsage = 144
{-# LINE 151 "Gauge/Source/RUsage.hsc" #-}


{-# LINE 153 "Gauge/Source/RUsage.hsc" #-}
pattern Self :: Who

{-# LINE 155 "Gauge/Source/RUsage.hsc" #-}
pattern Self = (0) :: Who
{-# LINE 156 "Gauge/Source/RUsage.hsc" #-}


{-# LINE 158 "Gauge/Source/RUsage.hsc" #-}
pattern Children :: Who

{-# LINE 160 "Gauge/Source/RUsage.hsc" #-}
pattern Children = (-1) :: Who
{-# LINE 161 "Gauge/Source/RUsage.hsc" #-}

type Who = CInt

-- | Gather RUsage
get :: Who -> IO RUsage
get who = alloca $ \ptr -> do
    throwErrnoIfMinus1_ "getrusage" (binding_getrusage who ptr)
    peek ptr

-- | call a function `f` gathering RUSage before and after the call.
with :: Who -> IO a -> IO (a, RUsage, RUsage)
with who f = allocaBytes (sizeRUsage * 2) $ \ptr -> do
    let ptr2 = ptr `plusPtr` sizeRUsage
    throwErrnoIfMinus1_ "getrusage" (binding_getrusage who ptr)
    a <- f
    throwErrnoIfMinus1_ "getrusage" (binding_getrusage who ptr2)
    (,,) <$> pure a <*> peek ptr <*> peek ptr2

-- binding for: int getrusage(int who, struct rusage *usage);
foreign import ccall unsafe "getrusage"
    binding_getrusage :: Who -> Ptr RUsage -> IO CInt

-- | On operating system not supporting getrusage this will be False, otherwise True.
supported :: Bool
supported = True


{-# LINE 215 "Gauge/Source/RUsage.hsc" #-}