{-# LINE 1 "libraries/base/./System/CPUTime.hsc" #-}
-----------------------------------------------------------------------------
{-# LINE 2 "libraries/base/./System/CPUTime.hsc" #-}
-- |
-- Module      :  System.CPUTime
-- Copyright   :  (c) The University of Glasgow 2001
-- License     :  BSD-style (see the file libraries/base/LICENSE)
-- 
-- Maintainer  :  libraries@haskell.org
-- Stability   :  provisional
-- Portability :  portable
--
-- The standard CPUTime library.
--
-----------------------------------------------------------------------------

module System.CPUTime 
        (
         getCPUTime,       -- :: IO Integer
         cpuTimePrecision  -- :: Integer
        ) where

import Prelude

import Data.Ratio


{-# LINE 28 "libraries/base/./System/CPUTime.hsc" #-}


{-# LINE 32 "libraries/base/./System/CPUTime.hsc" #-}


{-# LINE 34 "libraries/base/./System/CPUTime.hsc" #-}
import Foreign
import Foreign.C


{-# LINE 38 "libraries/base/./System/CPUTime.hsc" #-}

-- For _SC_CLK_TCK

{-# LINE 41 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 42 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 43 "libraries/base/./System/CPUTime.hsc" #-}

-- For struct rusage

{-# LINE 46 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 47 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 48 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 49 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 50 "libraries/base/./System/CPUTime.hsc" #-}

-- For FILETIME etc. on Windows

{-# LINE 55 "libraries/base/./System/CPUTime.hsc" #-}

-- for CLK_TCK

{-# LINE 58 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 59 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 60 "libraries/base/./System/CPUTime.hsc" #-}

-- for struct tms

{-# LINE 63 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 64 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 65 "libraries/base/./System/CPUTime.hsc" #-}


{-# LINE 67 "libraries/base/./System/CPUTime.hsc" #-}


{-# LINE 69 "libraries/base/./System/CPUTime.hsc" #-}
realToInteger :: Real a => a -> Integer
realToInteger ct = round (realToFrac ct :: Double)
  -- CTime, CClock, CUShort etc are in Real but not Fractional, 
  -- so we must convert to Double before we can round it

{-# LINE 74 "libraries/base/./System/CPUTime.hsc" #-}


{-# LINE 76 "libraries/base/./System/CPUTime.hsc" #-}
-- -----------------------------------------------------------------------------
-- |Computation 'getCPUTime' returns the number of picoseconds CPU time
-- used by the current program.  The precision of this result is
-- implementation-dependent.

getCPUTime :: IO Integer
getCPUTime = do


{-# LINE 85 "libraries/base/./System/CPUTime.hsc" #-}
-- getrusage() is right royal pain to deal with when targetting multiple
-- versions of Solaris, since some versions supply it in libc (2.3 and 2.5),
-- while 2.4 has got it in libucb (I wouldn't be too surprised if it was back
-- again in libucb in 2.6..)
--
-- Avoid the problem by resorting to times() instead.
--

{-# LINE 93 "libraries/base/./System/CPUTime.hsc" #-}
    allocaBytes (144) $ \ p_rusage -> do
{-# LINE 94 "libraries/base/./System/CPUTime.hsc" #-}
    throwErrnoIfMinus1_ "getrusage" $ getrusage (0) p_rusage
{-# LINE 95 "libraries/base/./System/CPUTime.hsc" #-}

    let ru_utime = ((\hsc_ptr -> hsc_ptr `plusPtr` 0)) p_rusage
{-# LINE 97 "libraries/base/./System/CPUTime.hsc" #-}
    let ru_stime = ((\hsc_ptr -> hsc_ptr `plusPtr` 16)) p_rusage
{-# LINE 98 "libraries/base/./System/CPUTime.hsc" #-}
    u_sec  <- ((\hsc_ptr -> peekByteOff hsc_ptr 0))  ru_utime :: IO CTime
{-# LINE 99 "libraries/base/./System/CPUTime.hsc" #-}
    u_usec <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) ru_utime :: IO CTime
{-# LINE 100 "libraries/base/./System/CPUTime.hsc" #-}
    s_sec  <- ((\hsc_ptr -> peekByteOff hsc_ptr 0))  ru_stime :: IO CTime
{-# LINE 101 "libraries/base/./System/CPUTime.hsc" #-}
    s_usec <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) ru_stime :: IO CTime
{-# LINE 102 "libraries/base/./System/CPUTime.hsc" #-}
    return ((realToInteger u_sec * 1000000 + realToInteger u_usec + 
             realToInteger s_sec * 1000000 + realToInteger s_usec) 
                * 1000000)

type CRUsage = ()
foreign import ccall unsafe getrusage :: CInt -> Ptr CRUsage -> IO CInt

{-# LINE 126 "libraries/base/./System/CPUTime.hsc" #-}


{-# LINE 160 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 161 "libraries/base/./System/CPUTime.hsc" #-}

-- |The 'cpuTimePrecision' constant is the smallest measurable difference
-- in CPU time that the implementation can record, and is given as an
-- integral number of picoseconds.


{-# LINE 167 "libraries/base/./System/CPUTime.hsc" #-}
cpuTimePrecision :: Integer
cpuTimePrecision = round ((1000000000000::Integer) % fromIntegral (clockTicks))

{-# LINE 170 "libraries/base/./System/CPUTime.hsc" #-}


{-# LINE 172 "libraries/base/./System/CPUTime.hsc" #-}
clockTicks :: Int
clockTicks =

{-# LINE 177 "libraries/base/./System/CPUTime.hsc" #-}
    unsafePerformIO (sysconf (2) >>= return . fromIntegral)
{-# LINE 178 "libraries/base/./System/CPUTime.hsc" #-}
foreign import ccall unsafe sysconf :: CInt -> IO CLong

{-# LINE 180 "libraries/base/./System/CPUTime.hsc" #-}

{-# LINE 181 "libraries/base/./System/CPUTime.hsc" #-}