Hardware/CPU/CPULoad.cs
author moel.mich
Sun, 23 Sep 2012 18:37:43 +0000
changeset 380 573f1fff48b2
parent 313 596df85bb4e1
permissions -rw-r--r--
Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Runtime.InteropServices;
    13 
    14 namespace OpenHardwareMonitor.Hardware.CPU {
    15   internal class CPULoad {
    16 
    17     [StructLayout(LayoutKind.Sequential)]
    18     protected struct SystemProcessorPerformanceInformation {
    19       public long IdleTime;
    20       public long KernelTime;
    21       public long UserTime;
    22       public long Reserved0;
    23       public long Reserved1;
    24       public ulong Reserved2;
    25     }
    26 
    27     protected enum SystemInformationClass {
    28       SystemBasicInformation = 0,
    29       SystemCpuInformation = 1,
    30       SystemPerformanceInformation = 2,
    31       SystemTimeOfDayInformation = 3,
    32       SystemProcessInformation = 5,
    33       SystemProcessorPerformanceInformation = 8
    34     }
    35 
    36     private readonly CPUID[][] cpuid;
    37 
    38     private long[] idleTimes;
    39     private long[] totalTimes;
    40 
    41     private float totalLoad;
    42     private readonly float[] coreLoads;
    43 
    44     private readonly bool available;
    45 
    46     private static bool GetTimes(out long[] idle, out long[] total) {      
    47       SystemProcessorPerformanceInformation[] informations = new
    48         SystemProcessorPerformanceInformation[64];
    49 
    50       int size = Marshal.SizeOf(typeof(SystemProcessorPerformanceInformation));
    51 
    52       idle = null;
    53       total = null;
    54 
    55       IntPtr returnLength;
    56       if (NativeMethods.NtQuerySystemInformation(
    57         SystemInformationClass.SystemProcessorPerformanceInformation,
    58         informations, informations.Length * size, out returnLength) != 0)
    59         return false;
    60 
    61       idle = new long[(int)returnLength / size];
    62       total = new long[(int)returnLength / size];
    63 
    64       for (int i = 0; i < idle.Length; i++) {
    65         idle[i] = informations[i].IdleTime;
    66         total[i] = informations[i].KernelTime + informations[i].UserTime;
    67       }
    68 
    69       return true;
    70     }
    71 
    72     public CPULoad(CPUID[][] cpuid) {
    73       this.cpuid = cpuid;
    74       this.coreLoads = new float[cpuid.Length];         
    75       this.totalLoad = 0;
    76       try {
    77         GetTimes(out idleTimes, out totalTimes);
    78       } catch (Exception) {
    79         this.idleTimes = null;
    80         this.totalTimes = null;
    81       }
    82       if (idleTimes != null)
    83         available = true;
    84     }
    85 
    86     public bool IsAvailable {
    87       get { return available; }
    88     }
    89 
    90     public float GetTotalLoad() {
    91       return totalLoad;
    92     }
    93 
    94     public float GetCoreLoad(int core) {
    95       return coreLoads[core];
    96     }
    97 
    98     public void Update() {
    99       if (this.idleTimes == null)
   100         return;
   101 
   102       long[] newIdleTimes;
   103       long[] newTotalTimes;
   104 
   105       if (!GetTimes(out newIdleTimes, out newTotalTimes))
   106         return;
   107 
   108       for (int i = 0; i < Math.Min(newTotalTimes.Length, totalTimes.Length); i++) 
   109         if (newTotalTimes[i] - this.totalTimes[i] < 100000)
   110           return;
   111 
   112       if (newIdleTimes == null || newTotalTimes == null)
   113         return;
   114 
   115       float total = 0;
   116       int count = 0;
   117       for (int i = 0; i < cpuid.Length; i++) {
   118         float value = 0;
   119         for (int j = 0; j < cpuid[i].Length; j++) {
   120           long index = cpuid[i][j].Thread;
   121           if (index < newIdleTimes.Length && index < totalTimes.Length) {
   122             float idle = 
   123               (float)(newIdleTimes[index] - this.idleTimes[index]) /
   124               (float)(newTotalTimes[index] - this.totalTimes[index]);
   125             value += idle;
   126             total += idle;
   127             count++;
   128           }
   129         }
   130         value = 1.0f - value / cpuid[i].Length;
   131         value = value < 0 ? 0 : value;
   132         coreLoads[i] = value * 100;
   133       }
   134       if (count > 0) {
   135         total = 1.0f - total / count;
   136         total = total < 0 ? 0 : total;
   137       } else {
   138         total = 0;
   139       }
   140       this.totalLoad = total * 100;
   141 
   142       this.totalTimes = newTotalTimes;
   143       this.idleTimes = newIdleTimes;
   144     }
   145 
   146     protected static class NativeMethods {
   147 
   148       [DllImport("ntdll.dll")]
   149       public static extern int NtQuerySystemInformation(
   150         SystemInformationClass informationClass,
   151         [Out] SystemProcessorPerformanceInformation[] informations,
   152         int structSize, out IntPtr returnLength);
   153     }
   154   }
   155 }