From 6a1a28a89323da3754351cf5ad0e36d8f1cb389b Mon Sep 17 00:00:00 2001 From: Arnold Vink Date: Mon, 19 Dec 2022 18:55:10 +0100 Subject: [PATCH] Fix for Windows 11 22H2 (22621) incorrect total CPU load issue. (#933) * Fix for Windows 11 22H2 (22621) incorrect total CPU load issue. * Fix for Windows 11 22H2 (22621) incorrect total CPU load issue. --- .../Hardware/Cpu/CpuLoad.cs | 30 ++++--- LibreHardwareMonitorLib/Interop/NtDll.cs | 78 ++++++------------- 2 files changed, 44 insertions(+), 64 deletions(-) diff --git a/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs b/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs index cf481c1..ceff770 100644 --- a/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs +++ b/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs @@ -39,27 +39,35 @@ internal class CpuLoad private static bool GetTimes(out long[] idle, out long[] total) { - Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] information = new Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[64]; - int size = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); - idle = null; total = null; - if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation, - information, - information.Length * size, - out IntPtr returnLength) != 0) + //Query processor idle information + Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION[] idleInformation = new Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION[64]; + int idleSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION)); + if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorIdleInformation, idleInformation, idleInformation.Length * idleSize, out int idleReturn) != 0) { return false; } - idle = new long[(int)returnLength / size]; - total = new long[(int)returnLength / size]; + //Query processor performance information + Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] perfInformation = new Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[64]; + int perfSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); + if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation, perfInformation, perfInformation.Length * perfSize, out int perfReturn) != 0) + { + return false; + } + idle = new long[idleReturn / idleSize]; for (int i = 0; i < idle.Length; i++) { - idle[i] = information[i].IdleTime; - total[i] = information[i].KernelTime + information[i].UserTime; + idle[i] = idleInformation[i].IdleTime; + } + + total = new long[perfReturn / perfSize]; + for (int i = 0; i < total.Length; i++) + { + total[i] = perfInformation[i].KernelTime + perfInformation[i].UserTime; } return true; diff --git a/LibreHardwareMonitorLib/Interop/NtDll.cs b/LibreHardwareMonitorLib/Interop/NtDll.cs index 11a3591..c57b945 100644 --- a/LibreHardwareMonitorLib/Interop/NtDll.cs +++ b/LibreHardwareMonitorLib/Interop/NtDll.cs @@ -3,7 +3,6 @@ // Copyright (C) LibreHardwareMonitor and Contributors. // All Rights Reserved. -using System; using System.Runtime.InteropServices; // ReSharper disable InconsistentNaming @@ -12,7 +11,7 @@ namespace LibreHardwareMonitor.Interop; internal class NtDll { - private const string DllName = "ntdll"; + private const string DllName = "ntdll.dll"; [StructLayout(LayoutKind.Sequential)] internal struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION @@ -20,62 +19,35 @@ internal class NtDll public long IdleTime; public long KernelTime; public long UserTime; - public long Reserved0; - public long Reserved1; - public ulong Reserved2; + public long DpcTime; + public long InterruptTime; + public uint InterruptCount; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct SYSTEM_PROCESSOR_IDLE_INFORMATION + { + public long IdleTime; + public long C1Time; + public long C2Time; + public long C3Time; + public uint C1Transitions; + public uint C2Transitions; + public uint C3Transitions; + public uint Padding; } internal enum SYSTEM_INFORMATION_CLASS { - SystemBasicInformation, - SystemProcessorInformation, - SystemPerformanceInformation, - SystemTimeOfDayInformation, - SystemPathInformation, - SystemProcessInformation, - SystemCallCountInformation, - SystemDeviceInformation, - SystemProcessorPerformanceInformation, - SystemFlagsInformation, - SystemCallTimeInformation, - SystemModuleInformation, - SystemLocksInformation, - SystemStackTraceInformation, - SystemPagedPoolInformation, - SystemNonPagedPoolInformation, - SystemHandleInformation, - SystemObjectInformation, - SystemPageFileInformation, - SystemVdmInstemulInformation, - SystemVdmBopInformation, - SystemFileCacheInformation, - SystemPoolTagInformation, - SystemInterruptInformation, - SystemDpcBehaviorInformation, - SystemFullMemoryInformation, - SystemLoadGdiDriverInformation, - SystemUnloadGdiDriverInformation, - SystemTimeAdjustmentInformation, - SystemSummaryMemoryInformation, - SystemNextEventIdInformation, - SystemEventIdsInformation, - SystemCrashDumpInformation, - SystemExceptionInformation, - SystemCrashDumpStateInformation, - SystemKernelDebuggerInformation, - SystemContextSwitchInformation, - SystemRegistryQuotaInformation, - SystemExtendServiceTableInformation, - SystemPrioritySeperation, - SystemPlugPlayBusInformation, - SystemDockInformation, - SystemPowerInformation, - SystemProcessorSpeedInformation, - SystemCurrentTimeZoneInformation, - SystemLookasideInformation + SystemProcessorPerformanceInformation = 8, + SystemProcessorIdleInformation = 42 } [DllImport(DllName)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - internal static extern int NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, [Out] SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] SystemInformation, int SystemInformationLength, out IntPtr ReturnLength); -} \ No newline at end of file + internal static extern int NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, [Out] SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] SystemInformation, int SystemInformationLength, out int ReturnLength); + + [DllImport(DllName)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern int NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, [Out] SYSTEM_PROCESSOR_IDLE_INFORMATION[] SystemInformation, int SystemInformationLength, out int ReturnLength); +}