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