Hardware/CPU/CPULoad.cs
author moel.mich
Sat, 11 Aug 2012 21:48:54 +0000
changeset 379 7af3aaeb42e9
parent 313 596df85bb4e1
permissions -rw-r--r--
Added a few checks and delays to the driver loading code to increase the chance of loading the driver.
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
}