Hardware/CPU/CPULoad.cs
author moel.mich
Sat, 03 Aug 2013 13:12:07 +0000
changeset 418 3bba187d41c2
parent 313 596df85bb4e1
permissions -rw-r--r--
Changed the Intel core temperature reading to evaluate the "Reading Valid" bit 31 for package level sensors as well (undocumented).
     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 }