{-# LANGUAGE ForeignFunctionInterface #-} -- | -- Module : System.Posix.LoadAvg -- There are two basic ways you can get load average on a modern Linux system. -- First is @getloadavg (3)@ system call. The second is @\/proc\/loadavg@ file. -- This module provides means of getting the information from both sources. -- @\/proc\/loadavg@ provides some additional information but we ignore that. module System.Posix.LoadAvg ( LoadAvg(..), parseLoadAvg, getLoadAvg, getLoadAvgSafe, getLoadAvgProc ) where import Foreign import Data.Maybe data LoadAvg = LoadAvg { sample_1 :: !Double -- ^ sample for last 1 minute , sample_5 :: !Double -- ^ sample for last 5 minutes , sample_15 :: !Double -- ^ sample for last 15 minutes } deriving (Read,Show,Eq,Ord) foreign import ccall "getloadavg" getloadavg_C :: Ptr Double -> Int -> IO Int -- | Discards error checking from getLoadAvgSafe. Will raise IO exception on error. getLoadAvg :: IO LoadAvg getLoadAvg = (fromMaybe (error "getLoadAvg: an error occured")) `fmap` getLoadAvgSafe -- | Calls @getloadavg (3)@ to get system load average. -- Provides error checking, and the result may be Nothing in case of error. -- If there is not enough data the samples will be copied from more recent samples. getLoadAvgSafe :: IO (Maybe LoadAvg) getLoadAvgSafe = allocaArray 3 $ \arr -> do res <- getloadavg_C arr 3 case res of -- Kind of hacky, I know 3 -> do [a,b,c] <- peekArray 3 arr return . Just $ LoadAvg a b c 2 -> do [a,b] <- peekArray 2 arr return . Just $ LoadAvg a b b 1 -> do [a] <- peekArray 1 arr return . Just $ LoadAvg a a a -- Instead of matching with _ perhaps whe should check that we got '-1' here _ -> return Nothing -- | Tries to read @\/proc\/loadavg@ and parse it's output with 'parseLoadAvg'. Either may fail with IO exception. getLoadAvgProc :: IO LoadAvg getLoadAvgProc = parseLoadAvg `fmap` readFile "/proc/loadavg" -- | Tries to parse the output of @\/proc\/loadavg@. If anything goes wrong an arbitrary exception will be raised. parseLoadAvg :: String -> LoadAvg parseLoadAvg input = let (a:b:c:_) = map read $ words input in LoadAvg a b c