Added CPUID support for Linux.
authormoel.mich
Wed, 03 Nov 2010 22:07:46 +0000
changeset 238bddc6e01840a
parent 237 9bf70d316cea
child 239 91800d0f54de
Added CPUID support for Linux.
Hardware/CPU/AMD0FCPU.cs
Hardware/CPU/AMD10CPU.cs
Hardware/CPU/CPUGroup.cs
Hardware/CPU/CPUID.cs
Hardware/CPU/GenericCPU.cs
Hardware/CPU/IntelCPU.cs
Hardware/Opcode.cs
Hardware/Ring0.cs
Hardware/ThreadAffinity.cs
OpenHardwareMonitorLib.csproj
     1.1 --- a/Hardware/CPU/AMD0FCPU.cs	Mon Nov 01 20:44:21 2010 +0000
     1.2 +++ b/Hardware/CPU/AMD0FCPU.cs	Wed Nov 03 22:07:46 2010 +0000
     1.3 @@ -146,7 +146,7 @@
     1.4  
     1.5            uint eax, edx;
     1.6            if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx,
     1.7 -            (UIntPtr)(1L << cpuid[i][0].Thread))) {
     1.8 +            1UL << cpuid[i][0].Thread)) {
     1.9              // CurrFID can be found in eax bits 0-5, MaxFID in 16-21
    1.10              // 8-13 hold StartFID, we don't use that here.
    1.11              double curMP = 0.5 * ((eax & 0x3F) + 8);
     2.1 --- a/Hardware/CPU/AMD10CPU.cs	Mon Nov 01 20:44:21 2010 +0000
     2.2 +++ b/Hardware/CPU/AMD10CPU.cs	Wed Nov 03 22:07:46 2010 +0000
     2.3 @@ -87,10 +87,8 @@
     2.4            ActivateSensor(coreClocks[i]);
     2.5        }
     2.6  
     2.7 -      // set affinity to the first thread for all frequency estimations
     2.8 -      IntPtr thread = NativeMethods.GetCurrentThread();
     2.9 -      UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread,
    2.10 -        (UIntPtr)(1L << cpuid[0][0].Thread));
    2.11 +      // set affinity to the first thread for all frequency estimations     
    2.12 +      ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread);
    2.13  
    2.14        uint ctlEax, ctlEdx;
    2.15        Ring0.Rdmsr(PERF_CTL_0, out ctlEax, out ctlEdx);
    2.16 @@ -104,7 +102,7 @@
    2.17        Ring0.Wrmsr(PERF_CTR_0, ctrEax, ctrEdx);
    2.18  
    2.19        // restore the thread affinity.
    2.20 -      NativeMethods.SetThreadAffinityMask(thread, mask);
    2.21 +      ThreadAffinity.Set(mask);
    2.22  
    2.23        Update();                   
    2.24      }
    2.25 @@ -208,7 +206,7 @@
    2.26  
    2.27            uint curEax, curEdx;
    2.28            if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
    2.29 -            (UIntPtr)(1L << cpuid[i][0].Thread))) 
    2.30 +            1UL << cpuid[i][0].Thread)) 
    2.31            {
    2.32              // 8:6 CpuDid: current core divisor ID
    2.33              // 5:0 CpuFid: current core frequency ID
    2.34 @@ -232,16 +230,5 @@
    2.35          }
    2.36        }
    2.37      }
    2.38 -
    2.39 -    private static class NativeMethods {
    2.40 -      private const string KERNEL = "kernel32.dll";
    2.41 -
    2.42 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    2.43 -      public static extern UIntPtr
    2.44 -        SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
    2.45 -
    2.46 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    2.47 -      public static extern IntPtr GetCurrentThread();
    2.48 -    }
    2.49    }
    2.50  }
     3.1 --- a/Hardware/CPU/CPUGroup.cs	Mon Nov 01 20:44:21 2010 +0000
     3.2 +++ b/Hardware/CPU/CPUGroup.cs	Wed Nov 03 22:07:46 2010 +0000
     3.3 @@ -101,10 +101,6 @@
     3.4      }
     3.5  
     3.6      public CPUGroup(ISettings settings) {
     3.7 -      // No implementation for cpuid on Unix systems
     3.8 -      int p = (int)Environment.OSVersion.Platform;
     3.9 -      if ((p == 4) || (p == 128)) 
    3.10 -        return;     
    3.11  
    3.12        CPUID[][] processorThreads = GetProcessorThreads();
    3.13        this.threads = new CPUID[processorThreads.Length][][];
     4.1 --- a/Hardware/CPU/CPUID.cs	Mon Nov 01 20:44:21 2010 +0000
     4.2 +++ b/Hardware/CPU/CPUID.cs	Wed Nov 03 22:07:46 2010 +0000
     4.3 @@ -105,7 +105,7 @@
     4.4  
     4.5        if (thread >= 32)
     4.6          throw new ArgumentOutOfRangeException("thread");
     4.7 -      UIntPtr mask = (UIntPtr)(1L << thread);
     4.8 +      ulong mask = 1UL << thread;
     4.9  
    4.10        if (Opcode.CpuidTx(CPUID_0, 0,
    4.11            out eax, out ebx, out ecx, out edx, mask)) {
     5.1 --- a/Hardware/CPU/GenericCPU.cs	Mon Nov 01 20:44:21 2010 +0000
     5.2 +++ b/Hardware/CPU/GenericCPU.cs	Wed Nov 03 22:07:46 2010 +0000
     5.3 @@ -130,8 +130,12 @@
     5.4        }
     5.5  
     5.6        if (hasTimeStampCounter) {
     5.7 +        ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread);
     5.8 +        
     5.9          estimatedTimeStampCounterFrequency = 
    5.10 -          EstimateTimeStampCounterFrequency();        
    5.11 +          EstimateTimeStampCounterFrequency();  
    5.12 +        
    5.13 +        ThreadAffinity.Set(mask);
    5.14        } else {
    5.15          estimatedTimeStampCounterFrequency = 0;
    5.16        }
    5.17 @@ -139,7 +143,7 @@
    5.18        timeStampCounterFrequency = estimatedTimeStampCounterFrequency;                  
    5.19      }
    5.20  
    5.21 -    private static double EstimateTimeStampCounterFrequency() {
    5.22 +    private static double EstimateTimeStampCounterFrequency() {           
    5.23        // preload the function
    5.24        EstimateTimeStampCounterFrequency(0);
    5.25        EstimateTimeStampCounterFrequency(0);
    5.26 @@ -148,6 +152,7 @@
    5.27        List<double> estimatedFrequency = new List<double>(3);
    5.28        for (int i = 0; i < 3; i++)
    5.29          estimatedFrequency.Add(1e-6 * EstimateTimeStampCounterFrequency(0.025));
    5.30 +                 
    5.31        estimatedFrequency.Sort();
    5.32        return estimatedFrequency[1];
    5.33      }
    5.34 @@ -156,7 +161,6 @@
    5.35        long ticks = (long)(timeWindow * Stopwatch.Frequency);
    5.36        ulong countBegin, countEnd;
    5.37  
    5.38 -      Thread.BeginThreadAffinity();
    5.39        long timeBegin = Stopwatch.GetTimestamp() +
    5.40          (long)Math.Ceiling(0.001 * ticks);
    5.41        long timeEnd = timeBegin + ticks;
    5.42 @@ -164,7 +168,6 @@
    5.43        countBegin = Opcode.Rdtsc();
    5.44        while (Stopwatch.GetTimestamp() < timeEnd) { }
    5.45        countEnd = Opcode.Rdtsc();
    5.46 -      Thread.EndThreadAffinity();
    5.47  
    5.48        return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) /
    5.49          (timeEnd - timeBegin);
    5.50 @@ -173,7 +176,7 @@
    5.51  
    5.52      private static void AppendMSRData(StringBuilder r, uint msr, int thread) {
    5.53        uint eax, edx;
    5.54 -      if (Ring0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) {
    5.55 +      if (Ring0.RdmsrTx(msr, out eax, out edx, 1UL << thread)) {
    5.56          r.Append(" ");
    5.57          r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
    5.58          r.Append("  ");
    5.59 @@ -264,9 +267,7 @@
    5.60        if (hasTimeStampCounter && isInvariantTimeStampCounter) {
    5.61  
    5.62          // make sure always the same thread is used
    5.63 -        IntPtr thread = NativeMethods.GetCurrentThread();
    5.64 -        UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread,
    5.65 -          (UIntPtr)(1L << cpuid[0][0].Thread));
    5.66 +        ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread);
    5.67  
    5.68          // read time before and after getting the TSC to estimate the error
    5.69          long firstTime = Stopwatch.GetTimestamp();
    5.70 @@ -274,7 +275,7 @@
    5.71          long time = Stopwatch.GetTimestamp();
    5.72  
    5.73          // restore the thread affinity mask
    5.74 -        NativeMethods.SetThreadAffinityMask(thread, mask);
    5.75 +        ThreadAffinity.Set(mask);
    5.76  
    5.77          double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
    5.78          double error = ((double)(time - firstTime)) / Stopwatch.Frequency;
    5.79 @@ -304,16 +305,5 @@
    5.80            totalLoad.Value = cpuLoad.GetTotalLoad();
    5.81        }
    5.82      }
    5.83 -
    5.84 -    private static class NativeMethods {
    5.85 -      private const string KERNEL = "kernel32.dll";
    5.86 -
    5.87 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    5.88 -      public static extern UIntPtr
    5.89 -        SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
    5.90 -
    5.91 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    5.92 -      public static extern IntPtr GetCurrentThread();
    5.93 -    }
    5.94    }
    5.95  }
     6.1 --- a/Hardware/CPU/IntelCPU.cs	Mon Nov 01 20:44:21 2010 +0000
     6.2 +++ b/Hardware/CPU/IntelCPU.cs	Wed Nov 03 22:07:46 2010 +0000
     6.3 @@ -118,7 +118,7 @@
     6.4                  tjMax = new float[coreCount];
     6.5                  for (int i = 0; i < coreCount; i++) {
     6.6                    if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
     6.7 -                    out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) {
     6.8 +                    out edx, 1UL << cpuid[i][0].Thread)) {
     6.9                      tjMax[i] = (eax >> 16) & 0xFF;
    6.10                    } else {
    6.11                      tjMax[i] = 100;
    6.12 @@ -217,7 +217,7 @@
    6.13          uint eax, edx;
    6.14          if (Ring0.RdmsrTx(
    6.15            IA32_THERM_STATUS_MSR, out eax, out edx,
    6.16 -            (UIntPtr)(1L << cpuid[i][0].Thread))) {
    6.17 +            1UL << cpuid[i][0].Thread)) {
    6.18            // if reading is valid
    6.19            if ((eax & 0x80000000) != 0) {
    6.20              // get the dist from tjMax from bits 22:16
    6.21 @@ -237,7 +237,7 @@
    6.22          for (int i = 0; i < coreClocks.Length; i++) {
    6.23            System.Threading.Thread.Sleep(1);
    6.24            if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
    6.25 -            (UIntPtr)(1L << cpuid[i][0].Thread))) 
    6.26 +            1UL << cpuid[i][0].Thread)) 
    6.27            {
    6.28              newBusClock = 
    6.29                TimeStampCounterFrequency / timeStampCounterMultiplier;
     7.1 --- a/Hardware/Opcode.cs	Mon Nov 01 20:44:21 2010 +0000
     7.2 +++ b/Hardware/Opcode.cs	Wed Nov 03 22:07:46 2010 +0000
     7.3 @@ -37,17 +37,17 @@
     7.4  
     7.5  using System;
     7.6  using System.Runtime.InteropServices;
     7.7 +using Mono.Unix.Native;
     7.8  
     7.9  namespace OpenHardwareMonitor.Hardware {
    7.10    internal static class Opcode {
    7.11 +    
    7.12      private static IntPtr codeBuffer;
    7.13 +    private static ulong size;
    7.14  
    7.15 -    public static void Open() {
    7.16 -      // No implementation for Unix systems
    7.17 +    public static void Open() {  
    7.18        int p = (int)Environment.OSVersion.Platform;
    7.19 -      if ((p == 4) || (p == 128))
    7.20 -        return;  
    7.21 -
    7.22 +            
    7.23        byte[] rdtscCode;
    7.24        byte[] cpuidCode;
    7.25        if (IntPtr.Size == 4) {
    7.26 @@ -55,13 +55,25 @@
    7.27          cpuidCode = CPUID_32;
    7.28        } else {
    7.29          rdtscCode = RDTSC_64;
    7.30 -        cpuidCode = CPUID_64;
    7.31 +        
    7.32 +        if ((p == 4) || (p == 128)) { // Unix
    7.33 +          cpuidCode = CPUID_64_LINUX;
    7.34 +        } else { // Windows
    7.35 +          cpuidCode = CPUID_64_WINDOWS;
    7.36 +        }
    7.37        }
    7.38 -
    7.39 -      codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
    7.40 -        (UIntPtr)(rdtscCode.Length + cpuidCode.Length),
    7.41 -      AllocationType.COMMIT | AllocationType.RESERVE, 
    7.42 -      MemoryProtection.EXECUTE_READWRITE);
    7.43 +      
    7.44 +      size = (ulong)(rdtscCode.Length + cpuidCode.Length);
    7.45 +      
    7.46 +      if ((p == 4) || (p == 128)) { // Unix
    7.47 +        codeBuffer = Syscall.mmap(IntPtr.Zero, size, 
    7.48 +          MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC, 
    7.49 +          MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_PRIVATE, -1, 0);
    7.50 +      } else { // Windows
    7.51 +        codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
    7.52 +          (UIntPtr)size, AllocationType.COMMIT | AllocationType.RESERVE, 
    7.53 +          MemoryProtection.EXECUTE_READWRITE);
    7.54 +      }
    7.55  
    7.56        Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length);
    7.57  
    7.58 @@ -72,15 +84,20 @@
    7.59        Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length);
    7.60  
    7.61        Cpuid = Marshal.GetDelegateForFunctionPointer(
    7.62 -        cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
    7.63 +        cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;         
    7.64      }
    7.65  
    7.66      public static void Close() {
    7.67        Rdtsc = null;
    7.68        Cpuid = null;
    7.69 -
    7.70 -      NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero, 
    7.71 -        FreeType.RELEASE);
    7.72 +      
    7.73 +      int p = (int)Environment.OSVersion.Platform;
    7.74 +      if ((p == 4) || (p == 128)) { // Unix
    7.75 +        Syscall.munmap(codeBuffer, size);
    7.76 +      } else { // Windows
    7.77 +        NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero, 
    7.78 +          FreeType.RELEASE);        
    7.79 +      }
    7.80      }
    7.81  
    7.82      [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    7.83 @@ -99,8 +116,8 @@
    7.84  
    7.85      private static readonly byte[] RDTSC_64 = new byte[] {
    7.86        0x0F, 0x31,                     // rdtsc  
    7.87 -      0x48, 0xC1, 0xE2, 0x20,         // shl rdx,20h  
    7.88 -      0x48, 0x0B, 0xC2,               // or rax,rdx  
    7.89 +      0x48, 0xC1, 0xE2, 0x20,         // shl rdx, 20h  
    7.90 +      0x48, 0x0B, 0xC2,               // or rax, rdx  
    7.91        0xC3                            // ret  
    7.92      };
    7.93      
    7.94 @@ -125,71 +142,83 @@
    7.95  
    7.96      private static readonly byte[] CPUID_32 = new byte[] {
    7.97        0x55,                           // push ebp  
    7.98 -      0x8B, 0xEC,                      // mov ebp,esp  
    7.99 -      0x83, 0xEC, 0x10,               // sub esp,10h  
   7.100 -      0x8B, 0x45, 0x08,               // mov eax,dword ptr [ebp+8]  
   7.101 -      0x8B, 0x4D, 0x0C,               // mov ecx,dword ptr [ebp+0Ch]  
   7.102 +      0x8B, 0xEC,                     // mov ebp, esp  
   7.103 +      0x83, 0xEC, 0x10,               // sub esp, 10h  
   7.104 +      0x8B, 0x45, 0x08,               // mov eax, dword ptr [ebp+8]  
   7.105 +      0x8B, 0x4D, 0x0C,               // mov ecx, dword ptr [ebp+0Ch]  
   7.106        0x53,                           // push ebx  
   7.107        0x0F, 0xA2,                     // cpuid  
   7.108        0x56,                           // push esi  
   7.109 -      0x8D, 0x75, 0xF0,               // lea esi,[info]  
   7.110 -      0x89, 0x06,                      // mov dword ptr [esi],eax  
   7.111 -      0x8B, 0x45, 0x10,               // mov eax,dword ptr [eax]  
   7.112 -      0x89, 0x5E, 0x04,               // mov dword ptr [esi+4],ebx  
   7.113 -      0x89, 0x4E, 0x08,               // mov dword ptr [esi+8],ecx  
   7.114 -      0x89, 0x56, 0x0C,               // mov dword ptr [esi+0Ch],edx  
   7.115 -      0x8B, 0x4D, 0xF0,               // mov ecx,dword ptr [info]  
   7.116 -      0x89, 0x08,                      // mov dword ptr [eax],ecx  
   7.117 -      0x8B, 0x45, 0x14,               // mov eax,dword ptr [ebx]  
   7.118 -      0x8B, 0x4D, 0xF4,               // mov ecx,dword ptr [ebp-0Ch]  
   7.119 -      0x89, 0x08,                      // mov dword ptr [eax],ecx  
   7.120 -      0x8B, 0x45, 0x18,               // mov eax,dword ptr [ecx]  
   7.121 -      0x8B, 0x4D, 0xF8,               // mov ecx,dword ptr [ebp-8]  
   7.122 -      0x89, 0x08,                      // mov dword ptr [eax],ecx  
   7.123 -      0x8B, 0x45, 0x1C,               // mov eax,dword ptr [edx]  
   7.124 -      0x8B, 0x4D, 0xFC,               // mov ecx,dword ptr [ebp-4]  
   7.125 +      0x8D, 0x75, 0xF0,               // lea esi, [info]  
   7.126 +      0x89, 0x06,                     // mov dword ptr [esi],eax  
   7.127 +      0x8B, 0x45, 0x10,               // mov eax, dword ptr [eax]  
   7.128 +      0x89, 0x5E, 0x04,               // mov dword ptr [esi+4], ebx  
   7.129 +      0x89, 0x4E, 0x08,               // mov dword ptr [esi+8], ecx  
   7.130 +      0x89, 0x56, 0x0C,               // mov dword ptr [esi+0Ch], edx  
   7.131 +      0x8B, 0x4D, 0xF0,               // mov ecx, dword ptr [info]  
   7.132 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   7.133 +      0x8B, 0x45, 0x14,               // mov eax, dword ptr [ebx]  
   7.134 +      0x8B, 0x4D, 0xF4,               // mov ecx, dword ptr [ebp-0Ch]  
   7.135 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   7.136 +      0x8B, 0x45, 0x18,               // mov eax, dword ptr [ecx]  
   7.137 +      0x8B, 0x4D, 0xF8,               // mov ecx, dword ptr [ebp-8]  
   7.138 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   7.139 +      0x8B, 0x45, 0x1C,               // mov eax, dword ptr [edx]  
   7.140 +      0x8B, 0x4D, 0xFC,               // mov ecx, dword ptr [ebp-4]  
   7.141        0x5E,                           // pop esi  
   7.142 -      0x89, 0x08,                     // mov dword ptr [eax],ecx  
   7.143 +      0x89, 0x08,                     // mov dword ptr [eax], ecx  
   7.144        0x5B,                           // pop ebx  
   7.145        0xC9,                           // leave  
   7.146        0xC2, 0x18, 0x00                // ret 18h  
   7.147      };
   7.148               
   7.149 -    private static readonly byte[] CPUID_64 = new byte[] {
   7.150 -      0x48, 0x89, 0x5C, 0x24, 0x08,   // mov qword ptr [rsp+8],rbx  
   7.151 -      0x8B, 0xC1,                     // mov eax,ecx  
   7.152 -      0x8B, 0xCA,                     // mov ecx,edx  
   7.153 -      0x0F, 0xA2,                     // cpuid  
   7.154 -      0x41, 0x89, 0x00,               // mov dword ptr [r8],eax  
   7.155 -      0x48, 0x8B, 0x44, 0x24, 0x28,   // mov rax,qword ptr [ecx]  
   7.156 -      0x41, 0x89, 0x19,               // mov dword ptr [r9],ebx  
   7.157 -      0x48, 0x8B, 0x5C, 0x24, 0x08,   // mov rbx,qword ptr [rsp+8]  
   7.158 -      0x89, 0x08,                     // mov dword ptr [rax],ecx  
   7.159 -      0x48, 0x8B, 0x44, 0x24, 0x30,   // mov rax,qword ptr [rsp+30h]  
   7.160 -      0x89, 0x10,                     // mov dword ptr [rax],edx  
   7.161 +    private static readonly byte[] CPUID_64_WINDOWS = new byte[] {
   7.162 +      0x48, 0x89, 0x5C, 0x24, 0x08,   // mov qword ptr [rsp+8], rbx  
   7.163 +      0x8B, 0xC1,                     // mov eax, ecx  
   7.164 +      0x8B, 0xCA,                     // mov ecx, edx        
   7.165 +      0x0F, 0xA2,                     // cpuid        
   7.166 +      0x41, 0x89, 0x00,               // mov dword ptr [r8], eax        
   7.167 +      0x48, 0x8B, 0x44, 0x24, 0x28,   // mov rax, qword ptr [rsp+28h]       
   7.168 +      0x41, 0x89, 0x19,               // mov dword ptr [r9], ebx        
   7.169 +      0x48, 0x8B, 0x5C, 0x24, 0x08,   // mov rbx, qword ptr [rsp+8]      
   7.170 +      0x89, 0x08,                     // mov dword ptr [rax], ecx        
   7.171 +      0x48, 0x8B, 0x44, 0x24, 0x30,   // mov rax, qword ptr [rsp+30h]  
   7.172 +      0x89, 0x10,                     // mov dword ptr [rax], edx  
   7.173        0xC3                            // ret  
   7.174      };
   7.175 +    
   7.176 +    private static readonly byte[] CPUID_64_LINUX = new byte[] {
   7.177 +      0x49, 0x89, 0xD2,               // mov r10, rdx
   7.178 +      0x49, 0x89, 0xCB,               // mov r11, rcx
   7.179 +      0x53,                           // push rbx
   7.180 +      0x89, 0xF8,                     // mov eax, edi
   7.181 +      0x89, 0xF1,                     // mov ecx, esi
   7.182 +      0x0F, 0xA2,                     // cpuid
   7.183 +      0x41, 0x89, 0x02,               // mov dword ptr [r10], eax
   7.184 +      0x41, 0x89, 0x1B,               // mov dword ptr [r11], ebx
   7.185 +      0x41, 0x89, 0x08,               // mov dword ptr [r8], ecx
   7.186 +      0x41, 0x89, 0x11,               // mov dword ptr [r9], edx
   7.187 +      0x5B,                           // pop rbx
   7.188 +      0xC3,                           // ret
   7.189 +    };
   7.190  
   7.191      public static bool CpuidTx(uint index, uint ecxValue, 
   7.192        out uint eax, out uint ebx, out uint ecx, out uint edx, 
   7.193 -      UIntPtr threadAffinityMask) {
   7.194 +      ulong threadAffinityMask) {
   7.195 +      
   7.196 +      ulong mask = ThreadAffinity.Set(threadAffinityMask);
   7.197  
   7.198 -      IntPtr thread = NativeMethods.GetCurrentThread();
   7.199 -      UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread, 
   7.200 -        threadAffinityMask);
   7.201 -
   7.202 -      if (mask == UIntPtr.Zero) {
   7.203 +      if (mask == 0) {
   7.204          eax = ebx = ecx = edx = 0;
   7.205          return false;
   7.206 -      }
   7.207 +      } 
   7.208  
   7.209        Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx);
   7.210  
   7.211 -      NativeMethods.SetThreadAffinityMask(thread, mask);
   7.212 -      
   7.213 +      ThreadAffinity.Set(mask);      
   7.214        return true;
   7.215      }
   7.216 -
   7.217 +    
   7.218      [Flags()]
   7.219      public enum AllocationType : uint {
   7.220        COMMIT = 0x1000,
   7.221 @@ -222,7 +251,7 @@
   7.222        RELEASE = 0x8000
   7.223      }
   7.224  
   7.225 -    private static class NativeMethods {
   7.226 +    private static class NativeMethods {      
   7.227        private const string KERNEL = "kernel32.dll";
   7.228  
   7.229        [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   7.230 @@ -231,14 +260,7 @@
   7.231  
   7.232        [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   7.233        public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize,
   7.234 -        FreeType dwFreeType);
   7.235 -
   7.236 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   7.237 -      public static extern UIntPtr
   7.238 -        SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
   7.239 -
   7.240 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   7.241 -      public static extern IntPtr GetCurrentThread();
   7.242 +        FreeType dwFreeType);                 
   7.243      }
   7.244    }
   7.245  }
     8.1 --- a/Hardware/Ring0.cs	Mon Nov 01 20:44:21 2010 +0000
     8.2 +++ b/Hardware/Ring0.cs	Wed Nov 03 22:07:46 2010 +0000
     8.3 @@ -95,6 +95,11 @@
     8.4      }
     8.5  
     8.6      public static void Open() {
     8.7 +      // No implementation for Unix systems
     8.8 +      int p = (int)Environment.OSVersion.Platform;
     8.9 +      if ((p == 4) || (p == 128))
    8.10 +        return;  
    8.11 +      
    8.12        if (driver != null)
    8.13          return;
    8.14       
    8.15 @@ -170,15 +175,13 @@
    8.16      }
    8.17  
    8.18      public static bool RdmsrTx(uint index, out uint eax, out uint edx,
    8.19 -      UIntPtr threadAffinityMask) 
    8.20 +      ulong threadAffinityMask) 
    8.21      {
    8.22 -      IntPtr thread = NativeMethods.GetCurrentThread();
    8.23 -      UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread, 
    8.24 -        threadAffinityMask);
    8.25 +      ulong mask = ThreadAffinity.Set(threadAffinityMask);
    8.26  
    8.27        bool result = Rdmsr(index, out eax, out edx);
    8.28  
    8.29 -      NativeMethods.SetThreadAffinityMask(thread, mask);
    8.30 +      ThreadAffinity.Set(mask);
    8.31        return result;
    8.32      }
    8.33  
    8.34 @@ -276,16 +279,5 @@
    8.35  
    8.36        return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
    8.37      }
    8.38 -
    8.39 -    private static class NativeMethods {
    8.40 -      private const string KERNEL = "kernel32.dll";
    8.41 -
    8.42 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    8.43 -      public static extern UIntPtr
    8.44 -        SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
    8.45 -
    8.46 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    8.47 -      public static extern IntPtr GetCurrentThread();
    8.48 -    }
    8.49    }
    8.50  }
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/Hardware/ThreadAffinity.cs	Wed Nov 03 22:07:46 2010 +0000
     9.3 @@ -0,0 +1,87 @@
     9.4 +/*
     9.5 +  
     9.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     9.7 +
     9.8 +  The contents of this file are subject to the Mozilla Public License Version
     9.9 +  1.1 (the "License"); you may not use this file except in compliance with
    9.10 +  the License. You may obtain a copy of the License at
    9.11 + 
    9.12 +  http://www.mozilla.org/MPL/
    9.13 +
    9.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    9.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    9.16 +  for the specific language governing rights and limitations under the License.
    9.17 +
    9.18 +  The Original Code is the Open Hardware Monitor code.
    9.19 +
    9.20 +  The Initial Developer of the Original Code is 
    9.21 +  Michael Möller <m.moeller@gmx.ch>.
    9.22 +  Portions created by the Initial Developer are Copyright (C) 2010
    9.23 +  the Initial Developer. All Rights Reserved.
    9.24 +
    9.25 +  Contributor(s):
    9.26 +
    9.27 +  Alternatively, the contents of this file may be used under the terms of
    9.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    9.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    9.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    9.31 +  of those above. If you wish to allow use of your version of this file only
    9.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    9.33 +  use your version of this file under the terms of the MPL, indicate your
    9.34 +  decision by deleting the provisions above and replace them with the notice
    9.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    9.36 +  the provisions above, a recipient may use your version of this file under
    9.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    9.38 + 
    9.39 +*/
    9.40 +
    9.41 +using System;
    9.42 +using System.Runtime.InteropServices;
    9.43 +
    9.44 +namespace OpenHardwareMonitor.Hardware {
    9.45 +  
    9.46 +  internal static class ThreadAffinity {
    9.47 +  
    9.48 +    public static ulong Set(ulong mask) { 
    9.49 +      if (mask == 0)
    9.50 +        return 0;
    9.51 +        
    9.52 +      int p = (int)Environment.OSVersion.Platform;
    9.53 +      if ((p == 4) || (p == 128)) { // Unix
    9.54 +        ulong result = 0;
    9.55 +        if (NativeMethods.sched_getaffinity(0, (IntPtr)Marshal.SizeOf(result), 
    9.56 +          ref result) != 0)          
    9.57 +          return 0;
    9.58 +        if (NativeMethods.sched_setaffinity(0, (IntPtr)Marshal.SizeOf(mask), 
    9.59 +          ref mask) != 0)
    9.60 +          return 0;
    9.61 +        return result;
    9.62 +      } else { // Windows      
    9.63 +        return (ulong)NativeMethods.SetThreadAffinityMask(
    9.64 +          NativeMethods.GetCurrentThread(), (UIntPtr)mask);
    9.65 +      }
    9.66 +    }
    9.67 +  
    9.68 +    private static class NativeMethods {      
    9.69 +      private const string KERNEL = "kernel32.dll";
    9.70 +
    9.71 +      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    9.72 +      public static extern UIntPtr
    9.73 +        SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
    9.74 +
    9.75 +      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
    9.76 +      public static extern IntPtr GetCurrentThread();       
    9.77 +      
    9.78 +      private const string LIBC = "libc";
    9.79 +      
    9.80 +      [DllImport(LIBC)]
    9.81 +      public static extern int sched_getaffinity(int pid, IntPtr maskSize,
    9.82 +        ref ulong mask);
    9.83 +      
    9.84 +      [DllImport(LIBC)]
    9.85 +      public static extern int sched_setaffinity(int pid, IntPtr maskSize,
    9.86 +        ref ulong mask);  
    9.87 +    }  
    9.88 +  }
    9.89 +}
    9.90 +
    10.1 --- a/OpenHardwareMonitorLib.csproj	Mon Nov 01 20:44:21 2010 +0000
    10.2 +++ b/OpenHardwareMonitorLib.csproj	Wed Nov 03 22:07:46 2010 +0000
    10.3 @@ -1,4 +1,4 @@
    10.4 -<?xml version="1.0" encoding="utf-8"?>
    10.5 +<?xml version="1.0" encoding="utf-8"?>
    10.6  <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    10.7    <PropertyGroup>
    10.8      <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    10.9 @@ -41,7 +41,6 @@
   10.10      <ErrorReport>prompt</ErrorReport>
   10.11      <WarningLevel>4</WarningLevel>
   10.12      <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
   10.13 -    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
   10.14    </PropertyGroup>
   10.15    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   10.16      <DebugType>none</DebugType>
   10.17 @@ -55,6 +54,7 @@
   10.18    <ItemGroup>
   10.19      <Reference Include="System" />
   10.20      <Reference Include="System.Management" />
   10.21 +    <Reference Include="Mono.Posix" />
   10.22    </ItemGroup>
   10.23    <ItemGroup>
   10.24      <Compile Include="Hardware\ATI\ADL.cs" />
   10.25 @@ -117,6 +117,7 @@
   10.26      <Compile Include="Collections\ReadOnlyArray.cs" />
   10.27      <Compile Include="Properties\AssemblyLibInfo.cs" />
   10.28      <Compile Include="Properties\AssemblyVersion.cs" />
   10.29 +    <Compile Include="Hardware\ThreadAffinity.cs" />
   10.30    </ItemGroup>
   10.31    <ItemGroup>
   10.32      <BootstrapperPackage Include="Microsoft.Net.Client.3.5">