packages feed

cpuid 0.2.1.2 → 0.2.1.3

raw patch · 7 files changed

+134/−93 lines, 7 filesnew-component:exe:cpuid-testnew-uploaderPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- System.Cpuid: data BytesPerSector
- System.Cpuid: data Entries
- System.Cpuid: data LineSize
- System.Cpuid: data MuOps
- System.Cpuid: data Ways
+ System.Cpuid: newtype BytesPerSector
+ System.Cpuid: newtype Entries
+ System.Cpuid: newtype LineSize
+ System.Cpuid: newtype MuOps
+ System.Cpuid: newtype Ways

Files

README view
@@ -27,8 +27,12 @@ to compile your program.  The "tests" directory contains a small test program for the module and-demonstrates its usage.  There is also a C version for this test-program, to test the overheads of Haskell's FFI.+demonstrates its usage. You may compile this program by installing with++  cabal install -fbuildExamples cpuid++There is also a C version for this test program, to test the overheads+of Haskell's FFI.  Happy Haskell hacking,   Martin
System/Cpuid.hs view
@@ -19,23 +19,22 @@ -- -- > module Main(main) where -- > --- > import Text.Printf+-- > import Text.Printf (printf, ) -- > import System.Cpuid -- >  -- > main :: IO ()--- > main =--- >     do (a, b, c, d) <- cpuid 0--- >        printf "basic CPUID usage: EAX=0: %8x %8x %8x %8x\n\n" a b c d--- >        vs <- vendorString--- >        printf "Vendor string: %s\n\n" vs--- >        vs <- brandString--- >        printf "Brand string: %s\n\n" vs--- >        printf "Cache information:\n"--- >        infos <- cacheInfo--- >        mapM_ (\ v -> putStrLn $ "  " ++ show v) infos--- >        putStrLn ""--- >        ProcessorInfo{piFamily = fam, piModel = mod, piStepping = step, piType = typ} <- processorInfo--- >        printf "processor info: family: %d, model: %d, stepping: %d, processor type: %d\n" fam mod step typ+-- > main = do+-- >    (a, b, c, d) <- cpuid 0+-- >    _ <- printf "basic CPUID usage: EAX=0: %8x %8x %8x %8x\n\n" a b c d+-- >    _ <- printf "Vendor string: %s\n\n" =<< vendorString+-- >    _ <- printf "Brand string: %s\n\n" =<< brandString+-- >    putStrLn "Cache information:"+-- >    putStrLn . unlines .+-- >       map (\ v -> "  " ++ show v) =<< cacheInfo+-- >    p <- processorInfo+-- >    _ <- printf "processor info: family: %d, model: %d, stepping: %d, processor type: %d\n"+-- >       (piFamily p) (piModel p) (piStepping p) (piType p)+-- >    return () -------------------------------------------------------------------------- module System.Cpuid     (-- * Data types@@ -56,74 +55,66 @@      brandString,      cacheInfo) where -import Foreign-import Foreign.C.String+import Foreign.Marshal.Array (allocaArray, peekArray, advancePtr, )+import Foreign.C.String (peekCStringLen, )+import Foreign.Storable (pokeElemOff, peekElemOff, )+import Foreign.Ptr (Ptr, castPtr, )+import Data.Bits ((.&.), shiftR, complement, )+import Data.Word (Word8, Word32, ) -foreign import ccall unsafe "cpuid" _cpuid :: Word32 -> Ptr Word32 -> Ptr Word32 -> Ptr Word32 -> Ptr Word32 -> IO ()+foreign import ccall unsafe "cpuid_array" _cpuid :: Word32 -> Ptr Word32 -> IO ()  -- | Execute the @cpuid@ instructions with the given argument -- in the EAX register.  Return the values of the registers -- EAX, EBX, ECX and EDX in that order. cpuid :: Word32 -> IO (Word32, Word32, Word32, Word32)-cpuid val =-    alloca (\ a -> -    alloca (\ b -> -    alloca (\ c -> -    alloca (\ d -> do _cpuid val a b c d-                      aa <- peek a-                      bb <- peek b-                      cc <- peek c-                      dd <- peek d-                      return (aa, bb, cc, dd)))))+cpuid op =+    allocaArray 4 $ \ arr -> do+        _cpuid op arr+        [a,b,c,d] <- peekArray 4 arr+        return (a, b, c, d) +-- | Run @cpuid@ but check before that the used operation is actually supported+cpuidMaybe :: Word32 -> IO (Maybe (Word32, Word32, Word32, Word32))+cpuidMaybe op = do+   (high, _, _, _) <- cpuid 0+   if op>high+     then return Nothing+     else fmap Just $ cpuid op+ -- | Execute the @cpuid@ instruction and return the vendor -- string reported by that instruction. vendorString :: IO String vendorString =-    do (_, b, c, d) <- cpuid 0-       allocaBytes 20 (\ str -> do let str' :: Ptr Word32-                                       str' = castPtr str -                                   poke str' b-                                   poke (str' `plusPtr` 4) d-                                   poke (str' `plusPtr` 8) c-                                   peekCStringLen (str, 12))+    allocaArray 4 $ \ arr -> do+        _cpuid 0 arr+        c <- peekElemOff arr 2+        d <- peekElemOff arr 3+        pokeElemOff arr 2 d+        pokeElemOff arr 3 c+        peekCStringLen (castPtr (advancePtr arr 1), 3*4)  -- | Execute the @cpuid@ instruction and return the brand string -- (processor name and maximum frequency) reported by that -- instruction. brandString :: IO String brandString =-    do allocaBytes 80-         (\ str -> -              do let str' :: Ptr Word32-                     str' = castPtr str -                 (a1, b1, c1, d1) <- cpuid 0x80000002-                 poke str' a1-                 poke (str' `plusPtr` 4) b1-                 poke (str' `plusPtr` 8) c1-                 poke (str' `plusPtr` 12) d1-                 (a2, b2, c2, d2) <- cpuid 0x80000003-                 poke (str' `plusPtr` 16) a2-                 poke (str' `plusPtr` 20) b2-                 poke (str' `plusPtr` 24) c2-                 poke (str' `plusPtr` 28) d2-                 (a3, b3, c3, d3) <- cpuid 0x80000004-                 poke (str' `plusPtr` 32) a3-                 poke (str' `plusPtr` 36) b3-                 poke (str' `plusPtr` 40) c3-                 poke (str' `plusPtr` 44) d3-                 peekCStringLen (str, 16 * 3))+    allocaArray (3*4) $ \ arr -> do+        _cpuid 0x80000002 arr+        _cpuid 0x80000003 (advancePtr arr 4)+        _cpuid 0x80000004 (advancePtr arr 8)+        peekCStringLen (castPtr arr, 3*4*4)  -- | Number of entries in a TLB.-data Entries = Entries Int+newtype Entries = Entries Int                      deriving (Show)  -- | Associativity in a set-associative cache.-data Ways = Ways Int+newtype Ways = Ways Int                      deriving (Show)  -- | MuOps in a processors trace cache.-data MuOps = MuOps Int+newtype MuOps = MuOps Int                      deriving (Show)  -- | Page size. Some entries can have alternative page sizes,@@ -139,11 +130,11 @@                  deriving (Show)  -- | Line size in a cache.-data LineSize = LineSize Int+newtype LineSize = LineSize Int                      deriving (Show) --- | Bytes per sector in a cache.  -data BytesPerSector = BytesPerSector Int+-- | Bytes per sector in a cache.+newtype BytesPerSector = BytesPerSector Int                      deriving (Show)  -- | Cache associativity.  For some entries, this is not specified in@@ -170,8 +161,13 @@ -- the @cpuid@ instruction.  The list is not ordered. cacheInfo :: IO [CacheInfo] cacheInfo =-    do (a, b, c, d) <- cpuid 2-       collectCacheDescriptors (fromIntegral ((a .&. 0xff) - 1)) [] (a .&. complement 0xff) b c d+    do m <- cpuidMaybe 2+       case m of+          Nothing -> return []+          Just (a, b, c, d) ->+             collectCacheDescriptors+                (fromIntegral ((a .&. 0xff) - 1)) []+                (a .&. complement 0xff) b c d  -- | Call the @cpuid@ instruction as often as needed and merge the values. collectCacheDescriptors :: Int -> [CacheInfo] -> Word32 -> Word32 -> Word32 -> Word32 -> IO [CacheInfo]
+ cbits/cpuid-pdc.c view
@@ -0,0 +1,7 @@+#include <stdint.h>++void+cpuid_array(uint32_t op, uint32_t reg[4])+{+  asm("cpuid": "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) : "a" (op));+}
+ cbits/cpuid-pic.c view
@@ -0,0 +1,15 @@+// http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inlin+#include <stdint.h>++void+cpuid_array(uint32_t op, uint32_t reg[4])+{+  asm volatile(+    "pushl %%ebx      \n" /* save %ebx */+    "cpuid            \n"+    "movl %%ebx, %1   \n" /* save what cpuid just put in %ebx */+    "popl %%ebx       \n" /* restore the old %ebx */+    : "=a"(reg[0]), "=r"(reg[1]), "=c"(reg[2]), "=d"(reg[3])+    : "a"(op)+    : "cc");+}
cbits/cpuid.c view
@@ -1,12 +1,16 @@-/* #include "cpuid.h" */+#ifdef __PIC__+#include "cpuid-pic.c"+#else+#include "cpuid-pdc.c"+#endif  void-cpuid(int in, int * aa, int * bb, int * cc, int * dd)+cpuid(uint32_t op, uint32_t * a, uint32_t * b, uint32_t * c, uint32_t * d) {-  int a, b, c, d;-  asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));-  *aa = a;-  *bb = b;-  *cc = c;-  *dd = d;+  uint32_t reg[4];+  cpuid_array(op, reg);+  *a = reg[0];+  *b = reg[1];+  *c = reg[2];+  *d = reg[3]; }
cpuid.cabal view
@@ -1,10 +1,9 @@-Cabal-version:      >=1.2 Name:               cpuid-Version:            0.2.1.2+Version:            0.2.1.3 License:            GPL License-file:       COPYING Author:             Martin Grabmueller <martin@grabmueller.de>-Maintainer:         martin@grabmueller.de+Maintainer:         martin@grabmueller.de, cpuid@henning-thielemann.de Homepage:           http://code.haskell.org/cpuid Category:           Foreign binding Synopsis:           Binding for the cpuid machine instruction on x86 compatible@@ -16,14 +15,31 @@         machines. Stability:          Experimental Build-type:         Simple+Cabal-version:      >=1.2 -Extra-source-files: README-                    tests/TestCpuid.hs+Extra-source-files:+  README+  cbits/cpuid-pic.c+  cbits/cpuid-pdc.c +Flag buildExamples+  Description: Build example executables+  Default: False+ Library+  If !arch(i386)+    Buildable: False   Build-depends:      base >= 4 && < 5   Exposed-Modules:    System.Cpuid   Extensions:         ForeignFunctionInterface-  C-sources:	    cbits/cpuid.c+  C-sources:	      cbits/cpuid.c   Include-dirs:       cbits   Install-includes:   cpuid.h+  GHC-Options:        -Wall++Executable cpuid-test+  If !(flag(buildExamples) && arch(i386))+    Buildable: False+  Main-Is:            tests/TestCpuid.hs+  C-sources:	      cbits/cpuid.c+  GHC-Options:        -Wall
tests/TestCpuid.hs view
@@ -1,20 +1,19 @@+-- This program is contained in the Cpuid documentation. module Main(main) where -import Text.Printf+import Text.Printf (printf, ) import System.Cpuid  main :: IO ()-main =-    do (a, b, c, d) <- cpuid 0-       printf "basic CPUID usage: EAX=0: %8x %8x %8x %8x\n\n" a b c d-       vs <- vendorString-       printf "Vendor string: %s\n\n" vs-       vs <- brandString-       printf "Brand string: %s\n\n" vs-       printf "Cache information:\n"-       infos <- cacheInfo-       mapM_ (\ v -> putStrLn $ "  " ++ show v) infos-       putStrLn ""-       ProcessorInfo{piFamily = fam, piModel = mod, piStepping = step, piType = typ} <- processorInfo-       printf "processor info: family: %d, model: %d, stepping: %d, processor type: %d\n" fam mod step typ-+main = do+   (a, b, c, d) <- cpuid 0+   _ <- printf "basic CPUID usage: EAX=0: %8x %8x %8x %8x\n\n" a b c d+   _ <- printf "Vendor string: %s\n\n" =<< vendorString+   _ <- printf "Brand string: %s\n\n" =<< brandString+   putStrLn "Cache information:"+   putStrLn . unlines .+      map (\ v -> "  " ++ show v) =<< cacheInfo+   p <- processorInfo+   _ <- printf "processor info: family: %d, model: %d, stepping: %d, processor type: %d\n"+      (piFamily p) (piModel p) (piStepping p) (piType p)+   return ()