{-# LINE 1 "libraries\base\.\System\CPUTime.hsc" #-}
{-# LANGUAGE Trustworthy #-}
{-# LINE 2 "libraries\base\.\System\CPUTime.hsc" #-}
{-# LANGUAGE CPP, NondecreasingIndentation, ForeignFunctionInterface, CApiFFI #-}

-----------------------------------------------------------------------------
-- |
-- 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.
--
-----------------------------------------------------------------------------


{-# LINE 19 "libraries\base\.\System\CPUTime.hsc" #-}

{-# LINE 20 "libraries\base\.\System\CPUTime.hsc" #-}

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

import Prelude

import Data.Ratio


{-# LINE 34 "libraries\base\.\System\CPUTime.hsc" #-}


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


{-# LINE 40 "libraries\base\.\System\CPUTime.hsc" #-}
import Foreign.Safe
import Foreign.C

{-# LINE 45 "libraries\base\.\System\CPUTime.hsc" #-}

-- For _SC_CLK_TCK

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

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

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

-- For struct rusage

{-# LINE 57 "libraries\base\.\System\CPUTime.hsc" #-}

-- For FILETIME etc. on Windows

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

{-# LINE 61 "libraries\base\.\System\CPUTime.hsc" #-}

{-# LINE 62 "libraries\base\.\System\CPUTime.hsc" #-}

-- for CLK_TCK

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

{-# LINE 66 "libraries\base\.\System\CPUTime.hsc" #-}

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

-- for struct tms

{-# LINE 72 "libraries\base\.\System\CPUTime.hsc" #-}


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

#ifdef mingw32_HOST_OS
# if defined(i386_HOST_ARCH)
#  define WINDOWS_CCONV stdcall
# elif defined(x86_64_HOST_ARCH)
#  define WINDOWS_CCONV ccall
# else
#  error Unknown mingw32 arch
# endif
#else
#endif


{-# LINE 92 "libraries\base\.\System\CPUTime.hsc" #-}


{-# LINE 94 "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 144 "libraries\base\.\System\CPUTime.hsc" #-}
     -- NOTE: GetProcessTimes() is only supported on NT-based OSes.
     -- The counts reported by GetProcessTimes() are in 100-ns (10^-7) units.
    allocaBytes (8) $ \ p_creationTime -> do
{-# LINE 147 "libraries\base\.\System\CPUTime.hsc" #-}
    allocaBytes (8) $ \ p_exitTime -> do
{-# LINE 148 "libraries\base\.\System\CPUTime.hsc" #-}
    allocaBytes (8) $ \ p_kernelTime -> do
{-# LINE 149 "libraries\base\.\System\CPUTime.hsc" #-}
    allocaBytes (8) $ \ p_userTime -> do
{-# LINE 150 "libraries\base\.\System\CPUTime.hsc" #-}
    pid <- getCurrentProcess
    ok <- getProcessTimes pid p_creationTime p_exitTime p_kernelTime p_userTime
    if toBool ok then do
      ut <- ft2psecs p_userTime
      kt <- ft2psecs p_kernelTime
      return (ut + kt)
     else return 0
  where 
        ft2psecs :: Ptr FILETIME -> IO Integer
        ft2psecs ft = do
          high <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) ft :: IO Word32
{-# LINE 161 "libraries\base\.\System\CPUTime.hsc" #-}
          low  <- ((\hsc_ptr -> peekByteOff hsc_ptr 0))  ft :: IO Word32
{-# LINE 162 "libraries\base\.\System\CPUTime.hsc" #-}
            -- Convert 100-ns units to picosecs (10^-12) 
            -- => multiply by 10^5.
          return (((fromIntegral high) * (2^(32::Int)) + (fromIntegral low)) * 100000)

    -- ToDo: pin down elapsed times to just the OS thread(s) that
    -- are evaluating/managing Haskell code.

type FILETIME = ()
type HANDLE = ()
-- need proper Haskell names (initial lower-case character)
foreign import WINDOWS_CCONV unsafe "GetCurrentProcess" getCurrentProcess :: IO (Ptr HANDLE)
foreign import WINDOWS_CCONV unsafe "GetProcessTimes" getProcessTimes :: Ptr HANDLE -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> Ptr FILETIME -> IO CInt


{-# LINE 176 "libraries\base\.\System\CPUTime.hsc" #-}

{-# LINE 177 "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 183 "libraries\base\.\System\CPUTime.hsc" #-}
cpuTimePrecision :: Integer
cpuTimePrecision = round ((1000000000000::Integer) % fromIntegral (clockTicks))

{-# LINE 186 "libraries\base\.\System\CPUTime.hsc" #-}


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

{-# LINE 191 "libraries\base\.\System\CPUTime.hsc" #-}
    (1000)
{-# LINE 192 "libraries\base\.\System\CPUTime.hsc" #-}

{-# LINE 196 "libraries\base\.\System\CPUTime.hsc" #-}

{-# LINE 197 "libraries\base\.\System\CPUTime.hsc" #-}