diff --git a/GUI/MainForm.cs b/GUI/MainForm.cs index d1dd9d0..217ff9b 100644 --- a/GUI/MainForm.cs +++ b/GUI/MainForm.cs @@ -130,8 +130,7 @@ namespace OpenHardwareMonitor.GUI { systemTray.HideShowCommand += hideShowClick; systemTray.ExitCommand += exitClick; - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { // Unix + if (Hardware.OperatingSystem.IsUnix) { // Unix treeView.RowHeight = Math.Max(treeView.RowHeight, 18); splitContainer.BorderStyle = BorderStyle.None; splitContainer.Border3DStyle = Border3DStyle.Adjust; diff --git a/GUI/NotifyIconAdv.cs b/GUI/NotifyIconAdv.cs index e40782d..15a9a8c 100644 --- a/GUI/NotifyIconAdv.cs +++ b/GUI/NotifyIconAdv.cs @@ -23,8 +23,7 @@ namespace OpenHardwareMonitor.GUI { private NotifyIconWindowsImplementation windowsNotifyIcon; public NotifyIconAdv() { - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { // Unix + if (Hardware.OperatingSystem.IsUnix) { // Unix genericNotifyIcon = new NotifyIcon(); } else { // Windows windowsNotifyIcon = new NotifyIconWindowsImplementation(); diff --git a/GUI/StartupManager.cs b/GUI/StartupManager.cs index e51cbee..5b89ae2 100644 --- a/GUI/StartupManager.cs +++ b/GUI/StartupManager.cs @@ -39,8 +39,7 @@ namespace OpenHardwareMonitor.GUI { } public StartupManager() { - int p = (int)System.Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { + if (Hardware.OperatingSystem.IsUnix) { scheduler = null; isAvailable = false; return; diff --git a/Hardware/ATI/ADL.cs b/Hardware/ATI/ADL.cs index 5931708..ee090bb 100644 --- a/Hardware/ATI/ADL.cs +++ b/Hardware/ATI/ADL.cs @@ -431,8 +431,7 @@ namespace OpenHardwareMonitor.Hardware.ATI { } private static void CreateDelegates(string name) { - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) + if (OperatingSystem.IsUnix) dllName = name + ".so"; else dllName = name + ".dll"; diff --git a/Hardware/CPU/AMD0FCPU.cs b/Hardware/CPU/AMD0FCPU.cs index ed2ad80..fb54bc3 100644 --- a/Hardware/CPU/AMD0FCPU.cs +++ b/Hardware/CPU/AMD0FCPU.cs @@ -129,8 +129,9 @@ namespace OpenHardwareMonitor.Hardware.CPU { Thread.Sleep(1); uint eax, edx; - if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx, - 1UL << cpuid[i][0].Thread)) { + if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx, + cpuid[i][0].Affinity)) + { // CurrFID can be found in eax bits 0-5, MaxFID in 16-21 // 8-13 hold StartFID, we don't use that here. double curMP = 0.5 * ((eax & 0x3F) + 8); diff --git a/Hardware/CPU/AMD10CPU.cs b/Hardware/CPU/AMD10CPU.cs index fb0378a..9624119 100644 --- a/Hardware/CPU/AMD10CPU.cs +++ b/Hardware/CPU/AMD10CPU.cs @@ -108,7 +108,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { corePerformanceBoostSupport = (cpuid[0][0].ExtData[7, 3] & (1 << 9)) > 0; // set affinity to the first thread for all frequency estimations - ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread); + var previousAffinity = ThreadAffinity.Set(cpuid[0][0].Affinity); // disable core performance boost uint hwcrEax, hwcrEdx; @@ -132,12 +132,11 @@ namespace OpenHardwareMonitor.Hardware.CPU { Ring0.Wrmsr(HWCR, hwcrEax, hwcrEdx); // restore the thread affinity. - ThreadAffinity.Set(mask); + ThreadAffinity.Set(previousAffinity); // the file reader for lm-sensors support on Linux temperatureStream = null; - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { + if (OperatingSystem.IsUnix) { string[] devicePaths = Directory.GetDirectories("/sys/class/hwmon/"); foreach (string path in devicePaths) { string name = null; @@ -345,8 +344,8 @@ namespace OpenHardwareMonitor.Hardware.CPU { Thread.Sleep(1); uint curEax, curEdx; - if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx, - 1UL << cpuid[i][0].Thread)) + if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx, + cpuid[i][0].Affinity)) { double multiplier; multiplier = GetCoreMultiplier(curEax); diff --git a/Hardware/CPU/AMD17CPU.cs b/Hardware/CPU/AMD17CPU.cs index 8b284e7..88a4bb2 100644 --- a/Hardware/CPU/AMD17CPU.cs +++ b/Hardware/CPU/AMD17CPU.cs @@ -272,7 +272,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { private class Core { private readonly AMD17CPU cpu; - private readonly ulong threadAffinityMask; + private readonly GroupAffinity affinity; private readonly Sensor powerSensor; private readonly Sensor clockSensor; @@ -284,7 +284,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { public Core(int index, CPUID[] threads, AMD17CPU cpu, ISettings settings) { this.cpu = cpu; - this.threadAffinityMask = 1UL << threads[0].Thread; + this.affinity = threads[0].Affinity; string coreString = cpu.CoreString(index); this.powerSensor = @@ -294,7 +294,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { if (cpu.energyUnitMultiplier != 0) { if (Ring0.RdmsrTx(MSR_CORE_ENERGY_STAT, out uint energyConsumed, - out _, threadAffinityMask)) + out _, affinity)) { lastEnergyTime = DateTime.UtcNow; lastEnergyConsumed = energyConsumed; @@ -319,13 +319,13 @@ namespace OpenHardwareMonitor.Hardware.CPU { DateTime energyTime = DateTime.MinValue; double? multiplier = null; - ulong mask = ThreadAffinity.Set(threadAffinityMask); + var previousAffinity = ThreadAffinity.Set(affinity); if (Ring0.Rdmsr(MSR_CORE_ENERGY_STAT, out uint energyConsumed, out _)) { energyTime = DateTime.UtcNow; } multiplier = GetMultiplier(); - ThreadAffinity.Set(mask); + ThreadAffinity.Set(previousAffinity); if (cpu.energyUnitMultiplier != 0) { float deltaTime = (float)(energyTime - lastEnergyTime).TotalSeconds; diff --git a/Hardware/CPU/CPUGroup.cs b/Hardware/CPU/CPUGroup.cs index 2e2aed9..e760cde 100644 --- a/Hardware/CPU/CPUGroup.cs +++ b/Hardware/CPU/CPUGroup.cs @@ -23,10 +23,17 @@ namespace OpenHardwareMonitor.Hardware.CPU { private static CPUID[][] GetProcessorThreads() { List threads = new List(); - for (int i = 0; i < 64; i++) { - try { - threads.Add(new CPUID(i)); - } catch (ArgumentOutOfRangeException) { } + for (int i = 0; i < ThreadAffinity.ProcessorGroupCount; i++) { + for (int j = 0; j < 64; j++) { + try { + if (!ThreadAffinity.IsValid(GroupAffinity.Single((ushort)i, j))) + continue; + var cpuid = CPUID.Get(i, j); + if (cpuid != null) + threads.Add(cpuid); + } catch (ArgumentOutOfRangeException) { + } + } } SortedDictionary> processors = @@ -172,6 +179,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { r.AppendLine(); for (int j = 0; j < threads[i].Length; j++) for (int k = 0; k < threads[i][j].Length; k++) { + r.AppendLine(" CPU Group: " + threads[i][j][k].Group); r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread); r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId); r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId); diff --git a/Hardware/CPU/CPUID.cs b/Hardware/CPU/CPUID.cs index cabcd36..b176c28 100644 --- a/Hardware/CPU/CPUID.cs +++ b/Hardware/CPU/CPUID.cs @@ -21,7 +21,9 @@ namespace OpenHardwareMonitor.Hardware.CPU { internal class CPUID { + private readonly int group; private readonly int thread; + private readonly GroupAffinity affinity; private readonly Vendor vendor = Vendor.Unknown; @@ -68,83 +70,87 @@ namespace OpenHardwareMonitor.Hardware.CPU { return count; } - public CPUID(int thread) { + public static CPUID Get(int group, int thread) { + if (thread >= 64) + return null; + + var affinity = GroupAffinity.Single((ushort)group, thread); + + var previousAffinity = ThreadAffinity.Set(affinity); + if (previousAffinity == GroupAffinity.Undefined) + return null; + + try { + return new CPUID(group, thread, affinity); + } finally { + ThreadAffinity.Set(previousAffinity); + } + } + + private CPUID(int group, int thread, GroupAffinity affinity) { + this.group = group; this.thread = thread; + this.affinity = affinity; uint maxCpuid = 0; uint maxCpuidExt = 0; uint eax, ebx, ecx, edx; - if (thread >= 64) - throw new ArgumentOutOfRangeException("thread"); - ulong mask = 1UL << thread; + Opcode.Cpuid(CPUID_0, 0, out eax, out ebx, out ecx, out edx); + if (eax > 0) + maxCpuid = eax; + else + return; - if (Opcode.CpuidTx(CPUID_0, 0, - out eax, out ebx, out ecx, out edx, mask)) { - if (eax > 0) - maxCpuid = eax; - else - return; - - StringBuilder vendorBuilder = new StringBuilder(); - AppendRegister(vendorBuilder, ebx); - AppendRegister(vendorBuilder, edx); - AppendRegister(vendorBuilder, ecx); - string cpuVendor = vendorBuilder.ToString(); - switch (cpuVendor) { - case "GenuineIntel": - vendor = Vendor.Intel; - break; - case "AuthenticAMD": - vendor = Vendor.AMD; - break; - default: - vendor = Vendor.Unknown; - break; - } - eax = ebx = ecx = edx = 0; - if (Opcode.CpuidTx(CPUID_EXT, 0, - out eax, out ebx, out ecx, out edx, mask)) { - if (eax > CPUID_EXT) - maxCpuidExt = eax - CPUID_EXT; - else - return; - } else { - throw new ArgumentOutOfRangeException("thread"); - } - } else { - throw new ArgumentOutOfRangeException("thread"); + StringBuilder vendorBuilder = new StringBuilder(); + AppendRegister(vendorBuilder, ebx); + AppendRegister(vendorBuilder, edx); + AppendRegister(vendorBuilder, ecx); + string cpuVendor = vendorBuilder.ToString(); + switch (cpuVendor) { + case "GenuineIntel": + vendor = Vendor.Intel; + break; + case "AuthenticAMD": + vendor = Vendor.AMD; + break; + default: + vendor = Vendor.Unknown; + break; } + eax = ebx = ecx = edx = 0; + Opcode.Cpuid(CPUID_EXT, 0, out eax, out ebx, out ecx, out edx); + if (eax > CPUID_EXT) + maxCpuidExt = eax - CPUID_EXT; + else + return; maxCpuid = Math.Min(maxCpuid, 1024); - maxCpuidExt = Math.Min(maxCpuidExt, 1024); + maxCpuidExt = Math.Min(maxCpuidExt, 1024); cpuidData = new uint[maxCpuid + 1, 4]; for (uint i = 0; i < (maxCpuid + 1); i++) - Opcode.CpuidTx(CPUID_0 + i, 0, + Opcode.Cpuid(CPUID_0 + i, 0, out cpuidData[i, 0], out cpuidData[i, 1], - out cpuidData[i, 2], out cpuidData[i, 3], mask); + out cpuidData[i, 2], out cpuidData[i, 3]); cpuidExtData = new uint[maxCpuidExt + 1, 4]; for (uint i = 0; i < (maxCpuidExt + 1); i++) - Opcode.CpuidTx(CPUID_EXT + i, 0, - out cpuidExtData[i, 0], out cpuidExtData[i, 1], - out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask); + Opcode.Cpuid(CPUID_EXT + i, 0, + out cpuidExtData[i, 0], out cpuidExtData[i, 1], + out cpuidExtData[i, 2], out cpuidExtData[i, 3]); StringBuilder nameBuilder = new StringBuilder(); for (uint i = 2; i <= 4; i++) { - if (Opcode.CpuidTx(CPUID_EXT + i, 0, - out eax, out ebx, out ecx, out edx, mask)) - { - AppendRegister(nameBuilder, eax); - AppendRegister(nameBuilder, ebx); - AppendRegister(nameBuilder, ecx); - AppendRegister(nameBuilder, edx); - } + Opcode.Cpuid(CPUID_EXT + i, 0, out eax, out ebx, out ecx, out edx); + AppendRegister(nameBuilder, eax); + AppendRegister(nameBuilder, ebx); + AppendRegister(nameBuilder, ecx); + AppendRegister(nameBuilder, edx); } nameBuilder.Replace('\0', ' '); - cpuBrandString = nameBuilder.ToString().Trim(); + cpuBrandString = nameBuilder.ToString().Trim(); nameBuilder.Replace("Dual-Core Processor", ""); nameBuilder.Replace("Triple-Core Processor", ""); nameBuilder.Replace("Quad-Core Processor", ""); @@ -175,7 +181,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { nameBuilder.Replace("RADEON R5, 10 COMPUTE CORES 4C+6G", ""); nameBuilder.Replace("RADEON R7, 10 COMPUTE CORES 4C+6G", ""); nameBuilder.Replace("RADEON R7, 12 COMPUTE CORES 4C+8G", ""); - nameBuilder.Replace("Radeon R5, 6 Compute Cores 2C+4G", ""); + nameBuilder.Replace("Radeon R5, 6 Compute Cores 2C+4G", ""); nameBuilder.Replace("Radeon R5, 8 Compute Cores 4C+4G", ""); nameBuilder.Replace("Radeon R6, 10 Compute Cores 4C+6G", ""); nameBuilder.Replace("Radeon R7, 10 Compute Cores 4C+6G", ""); @@ -191,7 +197,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { name = nameBuilder.ToString(); if (name.Contains("@")) name = name.Remove(name.LastIndexOf('@')); - name = name.Trim(); + name = name.Trim(); this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) + ((cpuidData[1, 0] & 0x0F00) >> 8); @@ -209,14 +215,14 @@ namespace OpenHardwareMonitor.Hardware.CPU { maxCoreIdPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1; else maxCoreIdPerPackage = 1; - threadMaskWith = + threadMaskWith = NextLog2(maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage); coreMaskWith = NextLog2(maxCoreIdPerPackage); break; - case Vendor.AMD: + case Vendor.AMD: if (this.family == 0x17) { coreMaskWith = (cpuidExtData[8, 2] >> 12) & 0xF; - threadMaskWith = + threadMaskWith = NextLog2(((cpuidExtData[0x1E, 1] >> 8) & 0xFF) + 1); } else { uint corePerPackage; @@ -226,7 +232,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { corePerPackage = 1; coreMaskWith = NextLog2(corePerPackage); threadMaskWith = 0; - } + } break; default: threadMaskWith = 0; @@ -235,11 +241,11 @@ namespace OpenHardwareMonitor.Hardware.CPU { } processorId = (apicId >> (int)(coreMaskWith + threadMaskWith)); - coreId = ((apicId >> (int)(threadMaskWith)) + coreId = ((apicId >> (int)(threadMaskWith)) - (processorId << (int)(coreMaskWith))); threadId = apicId - (processorId << (int)(coreMaskWith + threadMaskWith)) - - (coreId << (int)(threadMaskWith)); + - (coreId << (int)(threadMaskWith)); } public string Name { @@ -250,10 +256,22 @@ namespace OpenHardwareMonitor.Hardware.CPU { get { return cpuBrandString; } } + public int Group { + get { + return group; + } + } + public int Thread { get { return thread; } } + public GroupAffinity Affinity { + get { + return affinity; + } + } + public Vendor Vendor { get { return vendor; } } diff --git a/Hardware/CPU/GenericCPU.cs b/Hardware/CPU/GenericCPU.cs index cfdc9b5..cbac6a3 100644 --- a/Hardware/CPU/GenericCPU.cs +++ b/Hardware/CPU/GenericCPU.cs @@ -106,13 +106,13 @@ namespace OpenHardwareMonitor.Hardware.CPU { } if (hasTimeStampCounter) { - ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread); + var previousAffinity = ThreadAffinity.Set(cpuid[0][0].Affinity); EstimateTimeStampCounterFrequency( out estimatedTimeStampCounterFrequency, out estimatedTimeStampCounterFrequencyError); - ThreadAffinity.Set(mask); + ThreadAffinity.Set(previousAffinity); } else { estimatedTimeStampCounterFrequency = 0; } @@ -185,9 +185,11 @@ namespace OpenHardwareMonitor.Hardware.CPU { } - private static void AppendMSRData(StringBuilder r, uint msr, int thread) { + private static void AppendMSRData(StringBuilder r, uint msr, + GroupAffinity affinity) + { uint eax, edx; - if (Ring0.RdmsrTx(msr, out eax, out edx, 1UL << thread)) { + if (Ring0.RdmsrTx(msr, out eax, out edx, affinity)) { r.Append(" "); r.Append((msr).ToString("X8", CultureInfo.InvariantCulture)); r.Append(" "); @@ -240,7 +242,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { r.AppendLine(); r.AppendLine(" MSR EDX EAX"); foreach (uint msr in msrArray) - AppendMSRData(r, msr, cpuid[i][0].Thread); + AppendMSRData(r, msr, cpuid[i][0].Affinity); r.AppendLine(); } } @@ -268,15 +270,15 @@ namespace OpenHardwareMonitor.Hardware.CPU { if (hasTimeStampCounter && isInvariantTimeStampCounter) { // make sure always the same thread is used - ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread); + var previousAffinity = ThreadAffinity.Set(cpuid[0][0].Affinity); // read time before and after getting the TSC to estimate the error long firstTime = Stopwatch.GetTimestamp(); ulong timeStampCount = Opcode.Rdtsc(); long time = Stopwatch.GetTimestamp(); - // restore the thread affinity mask - ThreadAffinity.Set(mask); + // restore the previous thread affinity mask + ThreadAffinity.Set(previousAffinity); double delta = ((double)(time - lastTime)) / Stopwatch.Frequency; double error = ((double)(time - firstTime)) / Stopwatch.Frequency; diff --git a/Hardware/CPU/IntelCPU.cs b/Hardware/CPU/IntelCPU.cs index ba73188..b33ec77 100644 --- a/Hardware/CPU/IntelCPU.cs +++ b/Hardware/CPU/IntelCPU.cs @@ -79,7 +79,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { float[] result = new float[coreCount]; for (int i = 0; i < coreCount; i++) { if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax, - out edx, 1UL << cpuid[i][0].Thread)) { + out edx, cpuid[i][0].Affinity)) { result[i] = (eax >> 16) & 0xFF; } else { result[i] = 100; @@ -419,7 +419,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { uint eax, edx; // if reading is valid if (Ring0.RdmsrTx(IA32_THERM_STATUS_MSR, out eax, out edx, - 1UL << cpuid[i][0].Thread) && (eax & 0x80000000) != 0) + cpuid[i][0].Affinity) && (eax & 0x80000000) != 0) { // get the dist from tjMax from bits 22:16 float deltaT = ((eax & 0x007F0000) >> 16); @@ -435,7 +435,7 @@ namespace OpenHardwareMonitor.Hardware.CPU { uint eax, edx; // if reading is valid if (Ring0.RdmsrTx(IA32_PACKAGE_THERM_STATUS, out eax, out edx, - 1UL << cpuid[0][0].Thread) && (eax & 0x80000000) != 0) + cpuid[0][0].Affinity) && (eax & 0x80000000) != 0) { // get the dist from tjMax from bits 22:16 float deltaT = ((eax & 0x007F0000) >> 16); @@ -452,8 +452,9 @@ namespace OpenHardwareMonitor.Hardware.CPU { uint eax, edx; for (int i = 0; i < coreClocks.Length; i++) { System.Threading.Thread.Sleep(1); - if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx, - 1UL << cpuid[i][0].Thread)) { + if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx, + cpuid[i][0].Affinity)) + { newBusClock = TimeStampCounterFrequency / timeStampCounterMultiplier; switch (microarchitecture) { diff --git a/Hardware/GroupAffinity.cs b/Hardware/GroupAffinity.cs new file mode 100644 index 0000000..536e5bb --- /dev/null +++ b/Hardware/GroupAffinity.cs @@ -0,0 +1,57 @@ +/* + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + + Copyright (C) 2020 Michael Möller + +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenHardwareMonitor.Hardware { + + /// + /// This structure describes a group-specific affinity. + /// + internal struct GroupAffinity { + + public static GroupAffinity Undefined = + new GroupAffinity(ushort.MaxValue, 0); + + public GroupAffinity(ushort group, ulong mask) { + this.Group = group; + this.Mask = mask; + } + + public static GroupAffinity Single(ushort group, int index) { + return new GroupAffinity(group, 1UL << index); + } + + public ushort Group { get; } + + public ulong Mask { get; } + + public override bool Equals(object o) { + if (o == null || GetType() != o.GetType()) return false; + GroupAffinity a = (GroupAffinity)o; + return (Group == a.Group) && (Mask == a.Mask); + } + + public override int GetHashCode() { + return Group.GetHashCode() ^ Mask.GetHashCode(); + } + + public static bool operator ==(GroupAffinity a1, GroupAffinity a2) { + return (a1.Group == a2.Group) && (a1.Mask == a2.Mask); + } + + public static bool operator !=(GroupAffinity a1, GroupAffinity a2) { + return (a1.Group != a2.Group) || (a1.Mask != a2.Mask); + } + + } +} diff --git a/Hardware/HDD/HarddriveGroup.cs b/Hardware/HDD/HarddriveGroup.cs index 65ea0dd..0bdff6d 100644 --- a/Hardware/HDD/HarddriveGroup.cs +++ b/Hardware/HDD/HarddriveGroup.cs @@ -24,8 +24,8 @@ namespace OpenHardwareMonitor.Hardware.HDD { new List(); public HarddriveGroup(ISettings settings) { - int p = (int)Environment.OSVersion.Platform; - if (p == 4 || p == 128) return; + if (OperatingSystem.IsUnix) + return; ISmart smart = new WindowsSmart(); diff --git a/Hardware/Heatmaster/HeatmasterGroup.cs b/Hardware/Heatmaster/HeatmasterGroup.cs index f65a015..940ca13 100644 --- a/Hardware/Heatmaster/HeatmasterGroup.cs +++ b/Hardware/Heatmaster/HeatmasterGroup.cs @@ -66,9 +66,8 @@ namespace OpenHardwareMonitor.Hardware.Heatmaster { public HeatmasterGroup(ISettings settings) { - // No implementation for Heatmaster on Unix systems - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) + // No implementation for Heatmaster on Unix systems + if (OperatingSystem.IsUnix) return; string[] portNames = GetRegistryPortNames(); diff --git a/Hardware/Mainboard/Mainboard.cs b/Hardware/Mainboard/Mainboard.cs index 9912636..e9ac28d 100644 --- a/Hardware/Mainboard/Mainboard.cs +++ b/Hardware/Mainboard/Mainboard.cs @@ -50,8 +50,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { new Identifier(Identifier, "name").ToString(), name); ISuperIO[] superIO; - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { + if (OperatingSystem.IsUnix) { this.lmSensors = new LMSensors(); superIO = lmSensors.SuperIO; } else { diff --git a/Hardware/Nvidia/NVML.cs b/Hardware/Nvidia/NVML.cs index 92b0cb8..93c3a8b 100644 --- a/Hardware/Nvidia/NVML.cs +++ b/Hardware/Nvidia/NVML.cs @@ -61,8 +61,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia { } private static string GetDllName() { - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) + if (OperatingSystem.IsUnix) return "libnvidia-ml.so"; else return "nvml.dll"; diff --git a/Hardware/Opcode.cs b/Hardware/Opcode.cs index 178d13c..6c49f9e 100644 --- a/Hardware/Opcode.cs +++ b/Hardware/Opcode.cs @@ -18,9 +18,7 @@ namespace OpenHardwareMonitor.Hardware { private static IntPtr codeBuffer; private static ulong size; - public static void Open() { - int p = (int)Environment.OSVersion.Platform; - + public static void Open() { byte[] rdtscCode; byte[] cpuidCode; if (IntPtr.Size == 4) { @@ -29,7 +27,7 @@ namespace OpenHardwareMonitor.Hardware { } else { rdtscCode = RDTSC_64; - if ((p == 4) || (p == 128)) { // Unix + if (OperatingSystem.IsUnix) { // Unix cpuidCode = CPUID_64_LINUX; } else { // Windows cpuidCode = CPUID_64_WINDOWS; @@ -38,7 +36,7 @@ namespace OpenHardwareMonitor.Hardware { size = (ulong)(rdtscCode.Length + cpuidCode.Length); - if ((p == 4) || (p == 128)) { // Unix + if (OperatingSystem.IsUnix) { // Unix Assembly assembly = Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + "PublicKeyToken=0738eb9f132ed756"); @@ -81,8 +79,7 @@ namespace OpenHardwareMonitor.Hardware { Rdtsc = null; Cpuid = null; - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { // Unix + if (OperatingSystem.IsUnix) { // Unix Assembly assembly = Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + "PublicKeyToken=0738eb9f132ed756"); @@ -201,18 +198,18 @@ namespace OpenHardwareMonitor.Hardware { public static bool CpuidTx(uint index, uint ecxValue, out uint eax, out uint ebx, out uint ecx, out uint edx, - ulong threadAffinityMask) { - - ulong mask = ThreadAffinity.Set(threadAffinityMask); + GroupAffinity affinity) + { + var previousAffinity = ThreadAffinity.Set(affinity); - if (mask == 0) { + if (previousAffinity == GroupAffinity.Undefined) { eax = ebx = ecx = edx = 0; return false; } Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx); - ThreadAffinity.Set(mask); + ThreadAffinity.Set(previousAffinity); return true; } diff --git a/Hardware/OperatingSystem.cs b/Hardware/OperatingSystem.cs index 6cc2b34..468e996 100644 --- a/Hardware/OperatingSystem.cs +++ b/Hardware/OperatingSystem.cs @@ -4,7 +4,7 @@ License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - Copyright (C) 2012 Michael Möller + Copyright (C) 2012-2020 Michael Möller */ @@ -13,9 +13,20 @@ using System.Diagnostics; using System.Runtime.InteropServices; namespace OpenHardwareMonitor.Hardware { - internal static class OperatingSystem { + public static class OperatingSystem { - public static bool Is64BitOperatingSystem() { + static OperatingSystem() { + int p = (int)Environment.OSVersion.Platform; + IsUnix = (p == 4) || (p == 6) || (p == 128); + + Is64BitOperatingSystem = GetIs64BitOperatingSystem(); + } + + public static bool IsUnix { get; } + + public static bool Is64BitOperatingSystem { get; } + + private static bool GetIs64BitOperatingSystem() { if (IntPtr.Size == 8) return true; diff --git a/Hardware/RAM/RAMGroup.cs b/Hardware/RAM/RAMGroup.cs index 58fc4b4..0c945a9 100644 --- a/Hardware/RAM/RAMGroup.cs +++ b/Hardware/RAM/RAMGroup.cs @@ -18,8 +18,7 @@ namespace OpenHardwareMonitor.Hardware.RAM { public RAMGroup(SMBIOS smbios, ISettings settings) { // No implementation for RAM on Unix systems - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { + if (OperatingSystem.IsUnix) { hardware = new Hardware[0]; return; } diff --git a/Hardware/Ring0.cs b/Hardware/Ring0.cs index 44633aa..5985821 100644 --- a/Hardware/Ring0.cs +++ b/Hardware/Ring0.cs @@ -4,7 +4,7 @@ License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - Copyright (C) 2010-2016 Michael Möller + Copyright (C) 2010-2020 Michael Möller */ @@ -80,7 +80,7 @@ namespace OpenHardwareMonitor.Hardware { private static bool ExtractDriver(string fileName) { string resourceName = "OpenHardwareMonitor.Hardware." + - (OperatingSystem.Is64BitOperatingSystem() ? "WinRing0x64.sys" : + (OperatingSystem.Is64BitOperatingSystem ? "WinRing0x64.sys" : "WinRing0.sys"); string[] names = GetAssembly().GetManifestResourceNames(); @@ -129,8 +129,7 @@ namespace OpenHardwareMonitor.Hardware { public static void Open() { // no implementation for unix systems - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) + if (OperatingSystem.IsUnix) return; if (driver != null) @@ -284,13 +283,13 @@ namespace OpenHardwareMonitor.Hardware { } public static bool RdmsrTx(uint index, out uint eax, out uint edx, - ulong threadAffinityMask) + GroupAffinity affinity) { - ulong mask = ThreadAffinity.Set(threadAffinityMask); + var previousAffinity = ThreadAffinity.Set(affinity); bool result = Rdmsr(index, out eax, out edx); - ThreadAffinity.Set(mask); + ThreadAffinity.Set(previousAffinity); return result; } diff --git a/Hardware/SMBIOS.cs b/Hardware/SMBIOS.cs index ea49a79..c562451 100644 --- a/Hardware/SMBIOS.cs +++ b/Hardware/SMBIOS.cs @@ -42,8 +42,7 @@ namespace OpenHardwareMonitor.Hardware { } public SMBIOS() { - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { + if (OperatingSystem.IsUnix) { this.raw = null; this.table = null; diff --git a/Hardware/TBalancer/FTD2XX.cs b/Hardware/TBalancer/FTD2XX.cs index c6999ad..e9a4ff2 100644 --- a/Hardware/TBalancer/FTD2XX.cs +++ b/Hardware/TBalancer/FTD2XX.cs @@ -184,8 +184,7 @@ namespace OpenHardwareMonitor.Hardware.TBalancer { } private static string GetDllName() { - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) + if (OperatingSystem.IsUnix) return "libftd2xx.so"; else return "ftd2xx.dll"; diff --git a/Hardware/ThreadAffinity.cs b/Hardware/ThreadAffinity.cs index a4b8560..7120fca 100755 --- a/Hardware/ThreadAffinity.cs +++ b/Hardware/ThreadAffinity.cs @@ -4,43 +4,109 @@ License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - Copyright (C) 2010-2014 Michael Möller + Copyright (C) 2010-2020 Michael Möller */ using System; using System.Runtime.InteropServices; -namespace OpenHardwareMonitor.Hardware { - +namespace OpenHardwareMonitor.Hardware { + internal static class ThreadAffinity { - - public static ulong Set(ulong mask) { - if (mask == 0) - return 0; - - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { // Unix + + static ThreadAffinity() { + ProcessorGroupCount = GetProcessorGroupCount(); + } + + private static int GetProcessorGroupCount() { + if (OperatingSystem.IsUnix) + return 1; + + try { + return NativeMethods.GetActiveProcessorGroupCount(); + } catch { + return 1; + } + } + + public static int ProcessorGroupCount { get; } + + public static bool IsValid(GroupAffinity affinity) { + if (OperatingSystem.IsUnix) { + if (affinity.Group > 0) + return false; + } + + try { + var previous = Set(affinity); + if (previous == GroupAffinity.Undefined) + return false; + Set(previous); + return true; + } catch { + return false; + } + } + + /// + /// Sets the processor group affinity for the current thread. + /// + /// The processor group affinity. + /// The previous processor group affinity. + public static GroupAffinity Set(GroupAffinity affinity) { + if (affinity == GroupAffinity.Undefined) + return GroupAffinity.Undefined; + + if (OperatingSystem.IsUnix) { + if (affinity.Group > 0) + throw new ArgumentOutOfRangeException("affinity.Group"); + ulong result = 0; - if (NativeMethods.sched_getaffinity(0, (IntPtr)Marshal.SizeOf(result), - ref result) != 0) - return 0; - if (NativeMethods.sched_setaffinity(0, (IntPtr)Marshal.SizeOf(mask), - ref mask) != 0) - return 0; - return result; - } else { // Windows + if (NativeMethods.sched_getaffinity(0, (IntPtr)8, ref result) != 0) + return GroupAffinity.Undefined; + + ulong mask = affinity.Mask; + if (NativeMethods.sched_setaffinity(0, (IntPtr)8, ref mask) != 0) + return GroupAffinity.Undefined; + + return new GroupAffinity(0, result); + } else { UIntPtr uIntPtrMask; try { - uIntPtrMask = (UIntPtr)mask; + uIntPtrMask = (UIntPtr)affinity.Mask; } catch (OverflowException) { - throw new ArgumentOutOfRangeException("mask"); - } - return (ulong)NativeMethods.SetThreadAffinityMask( - NativeMethods.GetCurrentThread(), uIntPtrMask); - } - } - + throw new ArgumentOutOfRangeException("affinity.Mask"); + } + + var groupAffinity = new NativeMethods.GROUP_AFFINITY { + Group = affinity.Group, + Mask = uIntPtrMask + }; + + var currentThread = NativeMethods.GetCurrentThread(); + + try { + if (NativeMethods.SetThreadGroupAffinity(currentThread, + ref groupAffinity, out var previousGroupAffinity)) + { + return new GroupAffinity(previousGroupAffinity.Group, + (ulong)previousGroupAffinity.Mask); + } else { + return GroupAffinity.Undefined; + } + } catch (EntryPointNotFoundException) { + if (affinity.Group > 0) + throw new ArgumentOutOfRangeException("affinity.Group"); + + var previous = (ulong)NativeMethods.SetThreadAffinityMask( + currentThread, uIntPtrMask); + + return new GroupAffinity(0, previous); + } + } + } + private static class NativeMethods { private const string KERNEL = "kernel32.dll"; @@ -49,8 +115,27 @@ namespace OpenHardwareMonitor.Hardware { SetThreadAffinityMask(IntPtr handle, UIntPtr mask); [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] - public static extern IntPtr GetCurrentThread(); - + public static extern IntPtr GetCurrentThread(); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern ushort GetActiveProcessorGroupCount(); + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct GROUP_AFFINITY { + public UIntPtr Mask; + [MarshalAs(UnmanagedType.U2)] + public ushort Group; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, + ArraySubType = UnmanagedType.U2)] + public ushort[] Reserved; + } + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern bool SetThreadGroupAffinity( + IntPtr thread, + ref GROUP_AFFINITY groupAffinity, + out GROUP_AFFINITY previousGroupAffinity); + private const string LIBC = "libc"; [DllImport(LIBC)] diff --git a/OpenHardwareMonitorLib.csproj b/OpenHardwareMonitorLib.csproj index b1c4818..97cd5a8 100644 --- a/OpenHardwareMonitorLib.csproj +++ b/OpenHardwareMonitorLib.csproj @@ -64,6 +64,7 @@ + diff --git a/Properties/AssemblyVersion.cs b/Properties/AssemblyVersion.cs index a44214c..706f2bf 100644 --- a/Properties/AssemblyVersion.cs +++ b/Properties/AssemblyVersion.cs @@ -10,5 +10,5 @@ using System.Reflection; -[assembly: AssemblyVersion("0.9.2.3")] -[assembly: AssemblyInformationalVersion("0.9.2.3 Alpha")] \ No newline at end of file +[assembly: AssemblyVersion("0.9.2.4")] +[assembly: AssemblyInformationalVersion("0.9.2.4 Alpha")] \ No newline at end of file