----------------------------------------------------------------------------- -- | -- Module : cpuperf.hs -- Copyright : (c) Don Stewart 2007 -- License : BSD3-style (see LICENSE) -- -- Maintainer : dons@cse.unsw.edu.au -- Stability : stable -- Portability : GHC only: mtl -- ----------------------------------------------------------------------------- -- -- Toggle the cpu speed on an openbsd machine. -- -- Tries to be very robust and clean with errors, and separates -- privledged from non-privledged shell commands on the type level -- -- $ cpuperf -- cpu: 100 -> 0 -- -- $ cpuperf -- cpu: 0 -> 100 -- import Shell import Text.Printf main = shell $ do (old,new) <- modify "hw.setperf" toggle clock <- get "hw.cpuspeed" io $ do printf "cpu: %d -> %d\n" old new printf "clock: %f Ghz\n" (fromIntegral clock / 1000 :: Double) toggle v = if v == 100 then 0 else 100 -- --------------------------------------------------------------------- -- -- A State-monad like interface to the sysctl values -- -- -- Read a sysctl value from the shell -- get :: String -> Shell Integer get s = readM . parse =<< run ("sysctl " ++ s) where parse = tail . dropWhile (/= '=') . init -- -- Set a sysctl value. Runs in the Priv monad, and requires root privledges. -- Will prompt for a password. -- set :: String -> Integer -> Priv () set s v = do runPriv $ printf "sysctl -w %s=%s" s (show v) return () -- -- Modify a particular sysctl value, using a function applied to the -- current value, yielding a new value. Both the old and new values are -- returned. -- modify :: String -> (Integer -> Integer) -> Shell (Integer, Integer) modify s f = do v <- get s let u = f v priv (set s u) -- root return (v,u)