# HG changeset patch # User moel.mich # Date 1265318367 0 # Node ID 0e01b63e1fdc507644ed67eaf912e0bb7914373e # Parent ff3e6edc71139b0f7ec7fe9f241b85ed60d10849 Release version 0.1.13. Replaced PerformanceCounter based CPU load sensors with an implementation using NtQuerySystemInformation. Fixed a temperature reading problem for W83627DHG chips (sensors with invalid value 127?C). diff -r ff3e6edc7113 -r 0e01b63e1fdc Hardware/CPU/AMD0FCPU.cs --- a/Hardware/CPU/AMD0FCPU.cs Wed Feb 03 22:02:58 2010 +0000 +++ b/Hardware/CPU/AMD0FCPU.cs Thu Feb 04 21:19:27 2010 +0000 @@ -58,8 +58,7 @@ private List active = new List(); - private PerformanceCounter totalLoadCounter; - private PerformanceCounter[] coreLoadCounters; + private CPULoad cpuLoad; private const ushort PCI_AMD_VENDOR_ID = 0x1022; private const ushort PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID = 0x1103; @@ -80,37 +79,23 @@ // max two cores coreCount = coreCount > 2 ? 2 : coreCount; - try { - totalLoadCounter = new PerformanceCounter(); - totalLoadCounter.CategoryName = "Processor"; - totalLoadCounter.CounterName = "% Processor Time"; - totalLoadCounter.InstanceName = "_Total"; - totalLoadCounter.NextValue(); - } catch (Exception) { - totalLoadCounter = null; - } totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); - - coreLoadCounters = new PerformanceCounter[coreCount]; + + coreTemperatures = new Sensor[coreCount]; coreLoads = new Sensor[coreCount]; - for (int i = 0; i < coreLoadCounters.Length; i++) { - try { - coreLoadCounters[i] = new PerformanceCounter(); - coreLoadCounters[i].CategoryName = "Processor"; - coreLoadCounters[i].CounterName = "% Processor Time"; - coreLoadCounters[i].InstanceName = i.ToString(); - coreLoadCounters[i].NextValue(); - } catch (Exception) { - coreLoadCounters[i] = null; - } + for (int i = 0; i < coreCount; i++) { + coreTemperatures[i] = + new Sensor("Core #" + (i + 1), i, SensorType.Temperature, this); coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, SensorType.Load, this); - } + } - coreTemperatures = new Sensor[coreCount]; - for (int i = 0; i < coreCount; i++) - coreTemperatures[i] = - new Sensor("Core #" + (i + 1), i, SensorType.Temperature, this); + cpuLoad = new CPULoad(coreCount, 1); + if (cpuLoad.IsAvailable) { + foreach (Sensor sensor in coreLoads) + ActivateSensor(sensor); + ActivateSensor(totalLoad); + } pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID, PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID, 0); @@ -163,16 +148,12 @@ } } - if (totalLoadCounter != null) { - totalLoad.Value = totalLoadCounter.NextValue(); - ActivateSensor(totalLoad); + if (cpuLoad.IsAvailable) { + cpuLoad.Update(); + for (int i = 0; i < coreLoads.Length; i++) + coreLoads[i].Value = cpuLoad.GetCoreLoad(i); + totalLoad.Value = cpuLoad.GetTotalLoad(); } - - for (int i = 0; i < coreLoads.Length; i++) - if (coreLoadCounters[i] != null) { - coreLoads[i].Value = coreLoadCounters[i].NextValue(); - ActivateSensor(coreLoads[i]); - } } private void ActivateSensor(Sensor sensor) { diff -r ff3e6edc7113 -r 0e01b63e1fdc Hardware/CPU/AMD10CPU.cs --- a/Hardware/CPU/AMD10CPU.cs Wed Feb 03 22:02:58 2010 +0000 +++ b/Hardware/CPU/AMD10CPU.cs Thu Feb 04 21:19:27 2010 +0000 @@ -55,8 +55,7 @@ private List active = new List(); - private PerformanceCounter totalLoadCounter; - private PerformanceCounter[] coreLoadCounters; + private CPULoad cpuLoad; private const ushort PCI_AMD_VENDOR_ID = 0x1022; private const ushort PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID = 0x1203; @@ -72,32 +71,19 @@ if (cpuidExtData.GetLength(0) > 8) coreCount = (cpuidExtData[8, 2] & 0xFF) + 1; - try { - totalLoadCounter = new PerformanceCounter(); - totalLoadCounter.CategoryName = "Processor"; - totalLoadCounter.CounterName = "% Processor Time"; - totalLoadCounter.InstanceName = "_Total"; - totalLoadCounter.NextValue(); - } catch (Exception) { - totalLoadCounter = null; - } totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); - coreLoadCounters = new PerformanceCounter[coreCount]; coreLoads = new Sensor[coreCount]; - for (int i = 0; i < coreLoadCounters.Length; i++) { - try { - coreLoadCounters[i] = new PerformanceCounter(); - coreLoadCounters[i].CategoryName = "Processor"; - coreLoadCounters[i].CounterName = "% Processor Time"; - coreLoadCounters[i].InstanceName = i.ToString(); - coreLoadCounters[i].NextValue(); - } catch (Exception) { - coreLoadCounters[i] = null; - } + for (int i = 0; i < coreCount; i++) coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, SensorType.Load, this); - } + + cpuLoad = new CPULoad(coreCount, 1); + if (cpuLoad.IsAvailable) { + foreach (Sensor sensor in coreLoads) + ActivateSensor(sensor); + ActivateSensor(totalLoad); + } // AMD family 10h processors support only one temperature sensor coreTemperature = new Sensor( @@ -142,16 +128,12 @@ DeactivateSensor(coreTemperature); } - if (totalLoadCounter != null) { - totalLoad.Value = totalLoadCounter.NextValue(); - ActivateSensor(totalLoad); + if (cpuLoad.IsAvailable) { + cpuLoad.Update(); + for (int i = 0; i < coreLoads.Length; i++) + coreLoads[i].Value = cpuLoad.GetCoreLoad(i); + totalLoad.Value = cpuLoad.GetTotalLoad(); } - - for (int i = 0; i < coreLoads.Length; i++) - if (coreLoadCounters[i] != null) { - coreLoads[i].Value = coreLoadCounters[i].NextValue(); - ActivateSensor(coreLoads[i]); - } } private void ActivateSensor(Sensor sensor) { diff -r ff3e6edc7113 -r 0e01b63e1fdc Hardware/CPU/CPULoad.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/CPU/CPULoad.cs Thu Feb 04 21:19:27 2010 +0000 @@ -0,0 +1,161 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2009-2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace OpenHardwareMonitor.Hardware.CPU { + public class CPULoad { + + [StructLayout(LayoutKind.Sequential)] + private struct SystemProcessorPerformanceInformation { + public long IdleTime; + public long KernelTime; + public long UserTime; + public long Reserved0; + public long Reserved1; + public ulong Reserved2; + } + + private enum SystemInformationClass : int { + SystemBasicInformation = 0, + SystemCpuInformation = 1, + SystemPerformanceInformation = 2, + SystemTimeOfDayInformation = 3, + SystemProcessInformation = 5, + SystemProcessorPerformanceInformation = 8 + } + + [DllImport("ntdll.dll")] + private static extern int NtQuerySystemInformation( + SystemInformationClass informationClass, + [Out] SystemProcessorPerformanceInformation[] informations, + int structSize, out IntPtr returnLength); + + private uint coreCount; + private uint logicalProcessorsPerCore; + + private long systemTime; + private long[] idleTimes; + + private float totalLoad; + private float[] coreLoads; + + private bool available = false; + + private long[] GetIdleTimes() { + long[] result = new long[coreCount * logicalProcessorsPerCore]; + SystemProcessorPerformanceInformation[] informations = new + SystemProcessorPerformanceInformation[result.Length]; + + IntPtr returnLength; + NtQuerySystemInformation( + SystemInformationClass.SystemProcessorPerformanceInformation, + informations, informations.Length * + Marshal.SizeOf(typeof(SystemProcessorPerformanceInformation)), + out returnLength); + + for (int i = 0; i < result.Length; i++) + result[i] = informations[i].IdleTime; + + return result; + } + + public CPULoad(uint coreCount, uint logicalProcessorsPerCore) { + this.coreCount = coreCount; + this.logicalProcessorsPerCore = logicalProcessorsPerCore; + this.coreLoads = new float[coreCount]; + this.systemTime = DateTime.Now.Ticks; + this.totalLoad = 0; + try { + this.idleTimes = GetIdleTimes(); + } catch (Exception) { + this.idleTimes = null; + } + if (idleTimes != null) + available = true; + } + + public bool IsAvailable { + get { return available; } + } + + public float GetTotalLoad() { + return totalLoad; + } + + public float GetCoreLoad(int core) { + return coreLoads[core]; + } + + public void Update() { + if (this.idleTimes == null) + return; + + long systemTime = DateTime.Now.Ticks; + long[] idleTimes = GetIdleTimes(); + + if (systemTime - this.systemTime < 10000) + return; + + float total = 0; + for (int i = 0; i < coreCount; i++) { + float value = 0; + for (int j = 0; j < logicalProcessorsPerCore; j++) { + long index = i * logicalProcessorsPerCore + j; + long delta = idleTimes[index] - this.idleTimes[index]; + value += delta; + total += delta; + } + value = 1.0f - value / (logicalProcessorsPerCore * + (systemTime - this.systemTime)); + value = value < 0 ? 0 : value; + coreLoads[i] = value * 100; + } + total = 1.0f - total / (coreCount * logicalProcessorsPerCore * + (systemTime - this.systemTime)); + total = total < 0 ? 0 : total; + this.totalLoad = total * 100; + + this.systemTime = systemTime; + this.idleTimes = idleTimes; + } + + } +} diff -r ff3e6edc7113 -r 0e01b63e1fdc Hardware/CPU/IntelCPU.cs --- a/Hardware/CPU/IntelCPU.cs Wed Feb 03 22:02:58 2010 +0000 +++ b/Hardware/CPU/IntelCPU.cs Thu Feb 04 21:19:27 2010 +0000 @@ -59,9 +59,8 @@ private uint logicalProcessorsPerCore; private uint coreCount; - private PerformanceCounter totalLoadCounter; - private PerformanceCounter[] coreLoadCounters; - + private CPULoad cpuLoad; + private const uint IA32_THERM_STATUS_MSR = 0x019C; private const uint IA32_TEMPERATURE_TARGET = 0x01A2; @@ -133,30 +132,7 @@ default: tjMax = 100; break; } - try { - totalLoadCounter = new PerformanceCounter(); - totalLoadCounter.CategoryName = "Processor"; - totalLoadCounter.CounterName = "% Processor Time"; - totalLoadCounter.InstanceName = "_Total"; - totalLoadCounter.NextValue(); - } catch (Exception) { - totalLoadCounter = null; - } - totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); - - coreLoadCounters = new PerformanceCounter[ - coreCount * logicalProcessorsPerCore]; - for (int i = 0; i < coreLoadCounters.Length; i++) { - try { - coreLoadCounters[i] = new PerformanceCounter(); - coreLoadCounters[i].CategoryName = "Processor"; - coreLoadCounters[i].CounterName = "% Processor Time"; - coreLoadCounters[i].InstanceName = i.ToString(); - coreLoadCounters[i].NextValue(); - } catch (Exception) { - coreLoadCounters[i] = null; - } - } + totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this); coreTemperatures = new Sensor[coreCount]; coreLoads = new Sensor[coreCount]; @@ -167,6 +143,13 @@ SensorType.Load, this); } + cpuLoad = new CPULoad(coreCount, logicalProcessorsPerCore); + if (cpuLoad.IsAvailable) { + foreach (Sensor sensor in coreLoads) + ActivateSensor(sensor); + ActivateSensor(totalLoad); + } + Update(); } @@ -221,27 +204,11 @@ } } - if (totalLoadCounter != null) { - totalLoad.Value = totalLoadCounter.NextValue(); - ActivateSensor(totalLoad); - } - - for (int i = 0; i < coreLoads.Length; i++) { - float value = 0; - int count = 0; - for (int j = 0; j < logicalProcessorsPerCore; j++) { - PerformanceCounter counter = - coreLoadCounters[logicalProcessorsPerCore * i + j]; - if (counter != null) { - value += counter.NextValue(); - count++; - } - } - if (count > 0) { - value /= count; - coreLoads[i].Value = value; - ActivateSensor(coreLoads[i]); - } + if (cpuLoad.IsAvailable) { + cpuLoad.Update(); + for (int i = 0; i < coreLoads.Length; i++) + coreLoads[i].Value = cpuLoad.GetCoreLoad(i); + totalLoad.Value = cpuLoad.GetTotalLoad(); } } diff -r ff3e6edc7113 -r 0e01b63e1fdc Hardware/LPC/W83627DHG.cs --- a/Hardware/LPC/W83627DHG.cs Wed Feb 03 22:02:58 2010 +0000 +++ b/Hardware/LPC/W83627DHG.cs Thu Feb 04 21:19:27 2010 +0000 @@ -94,7 +94,7 @@ (ushort)(address + ADDRESS_REGISTER_OFFSET), register); return WinRing0.ReadIoPortByte( (ushort)(address + DATA_REGISTER_OFFSET)); - } + } public W83627DHG(Chip chip, byte revision, ushort address) { this.chip = chip; @@ -215,14 +215,14 @@ foreach (Sensor sensor in temperatures) { int value; if (sensor.Index < 2) { - value = ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG); + value = (sbyte)ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG); value = (value << 1) | ReadByte((byte)(sensor.Index + 1), (byte)(TEMPERATURE_BASE_REG + 1)) >> 7; } else { - value = ReadByte(0, TEMPERATURE_SYS_REG) << 1; + value = (sbyte)ReadByte(0, TEMPERATURE_SYS_REG) << 1; } sensor.Value = value / 2.0f; - if (value < 0x1FE) + if (value < 0xFE) ActivateSensor(sensor); else DeactivateSensor(sensor); diff -r ff3e6edc7113 -r 0e01b63e1fdc OpenHardwareMonitor.csproj --- a/OpenHardwareMonitor.csproj Wed Feb 03 22:02:58 2010 +0000 +++ b/OpenHardwareMonitor.csproj Thu Feb 04 21:19:27 2010 +0000 @@ -13,6 +13,8 @@ 512 OpenHardwareMonitor Resources\icon.ico + Resources\app.manifest + OpenHardwareMonitor.Program true @@ -59,6 +61,7 @@ + @@ -139,6 +142,9 @@ + + + diff -r ff3e6edc7113 -r 0e01b63e1fdc Properties/AssemblyInfo.cs --- a/Properties/AssemblyInfo.cs Wed Feb 03 22:02:58 2010 +0000 +++ b/Properties/AssemblyInfo.cs Thu Feb 04 21:19:27 2010 +0000 @@ -69,5 +69,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.1.12.0")] -[assembly: AssemblyFileVersion("0.1.12.0")] +[assembly: AssemblyVersion("0.1.13.0")] +[assembly: AssemblyFileVersion("0.1.13.0")] diff -r ff3e6edc7113 -r 0e01b63e1fdc Resources/app.manifest --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/app.manifest Thu Feb 04 21:19:27 2010 +0000 @@ -0,0 +1,10 @@ + + + + + + + + + + diff -r ff3e6edc7113 -r 0e01b63e1fdc Utilities/HexStringArray.cs --- a/Utilities/HexStringArray.cs Wed Feb 03 22:02:58 2010 +0000 +++ b/Utilities/HexStringArray.cs Thu Feb 04 21:19:27 2010 +0000 @@ -47,8 +47,9 @@ public HexStringArray(string input) { List list = new List(); foreach (string str in input.Split(' ')) { - if (str.Trim().Length > 0) - list.Add(Convert.ToByte(str, 16)); + string s = str.Trim(); + if (s.Length > 0) + list.Add(Convert.ToByte(s, 16)); } array = list.ToArray(); }