Added support for multiple processor groups. Changed the ThreadAffinity class to use a new struct GroupAffinity. Changed operating system checks to make use of a new flag OperatingSystem.IsUnix.

This commit is contained in:
Michael Möller 2020-05-04 23:11:33 +02:00
parent 87c6f02d33
commit b04c151c77
25 changed files with 336 additions and 167 deletions

View File

@ -130,8 +130,7 @@ namespace OpenHardwareMonitor.GUI {
systemTray.HideShowCommand += hideShowClick; systemTray.HideShowCommand += hideShowClick;
systemTray.ExitCommand += exitClick; systemTray.ExitCommand += exitClick;
int p = (int)Environment.OSVersion.Platform; if (Hardware.OperatingSystem.IsUnix) { // Unix
if ((p == 4) || (p == 128)) { // Unix
treeView.RowHeight = Math.Max(treeView.RowHeight, 18); treeView.RowHeight = Math.Max(treeView.RowHeight, 18);
splitContainer.BorderStyle = BorderStyle.None; splitContainer.BorderStyle = BorderStyle.None;
splitContainer.Border3DStyle = Border3DStyle.Adjust; splitContainer.Border3DStyle = Border3DStyle.Adjust;

View File

@ -23,8 +23,7 @@ namespace OpenHardwareMonitor.GUI {
private NotifyIconWindowsImplementation windowsNotifyIcon; private NotifyIconWindowsImplementation windowsNotifyIcon;
public NotifyIconAdv() { public NotifyIconAdv() {
int p = (int)Environment.OSVersion.Platform; if (Hardware.OperatingSystem.IsUnix) { // Unix
if ((p == 4) || (p == 128)) { // Unix
genericNotifyIcon = new NotifyIcon(); genericNotifyIcon = new NotifyIcon();
} else { // Windows } else { // Windows
windowsNotifyIcon = new NotifyIconWindowsImplementation(); windowsNotifyIcon = new NotifyIconWindowsImplementation();

View File

@ -39,8 +39,7 @@ namespace OpenHardwareMonitor.GUI {
} }
public StartupManager() { public StartupManager() {
int p = (int)System.Environment.OSVersion.Platform; if (Hardware.OperatingSystem.IsUnix) {
if ((p == 4) || (p == 128)) {
scheduler = null; scheduler = null;
isAvailable = false; isAvailable = false;
return; return;

View File

@ -431,8 +431,7 @@ namespace OpenHardwareMonitor.Hardware.ATI {
} }
private static void CreateDelegates(string name) { private static void CreateDelegates(string name) {
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix)
if ((p == 4) || (p == 128))
dllName = name + ".so"; dllName = name + ".so";
else else
dllName = name + ".dll"; dllName = name + ".dll";

View File

@ -130,7 +130,8 @@ namespace OpenHardwareMonitor.Hardware.CPU {
uint eax, edx; uint eax, edx;
if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx, if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx,
1UL << cpuid[i][0].Thread)) { cpuid[i][0].Affinity))
{
// CurrFID can be found in eax bits 0-5, MaxFID in 16-21 // CurrFID can be found in eax bits 0-5, MaxFID in 16-21
// 8-13 hold StartFID, we don't use that here. // 8-13 hold StartFID, we don't use that here.
double curMP = 0.5 * ((eax & 0x3F) + 8); double curMP = 0.5 * ((eax & 0x3F) + 8);

View File

@ -108,7 +108,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
corePerformanceBoostSupport = (cpuid[0][0].ExtData[7, 3] & (1 << 9)) > 0; corePerformanceBoostSupport = (cpuid[0][0].ExtData[7, 3] & (1 << 9)) > 0;
// set affinity to the first thread for all frequency estimations // 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 // disable core performance boost
uint hwcrEax, hwcrEdx; uint hwcrEax, hwcrEdx;
@ -132,12 +132,11 @@ namespace OpenHardwareMonitor.Hardware.CPU {
Ring0.Wrmsr(HWCR, hwcrEax, hwcrEdx); Ring0.Wrmsr(HWCR, hwcrEax, hwcrEdx);
// restore the thread affinity. // restore the thread affinity.
ThreadAffinity.Set(mask); ThreadAffinity.Set(previousAffinity);
// the file reader for lm-sensors support on Linux // the file reader for lm-sensors support on Linux
temperatureStream = null; temperatureStream = null;
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix) {
if ((p == 4) || (p == 128)) {
string[] devicePaths = Directory.GetDirectories("/sys/class/hwmon/"); string[] devicePaths = Directory.GetDirectories("/sys/class/hwmon/");
foreach (string path in devicePaths) { foreach (string path in devicePaths) {
string name = null; string name = null;
@ -346,7 +345,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
uint curEax, curEdx; uint curEax, curEdx;
if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx, if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
1UL << cpuid[i][0].Thread)) cpuid[i][0].Affinity))
{ {
double multiplier; double multiplier;
multiplier = GetCoreMultiplier(curEax); multiplier = GetCoreMultiplier(curEax);

View File

@ -272,7 +272,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
private class Core { private class Core {
private readonly AMD17CPU cpu; private readonly AMD17CPU cpu;
private readonly ulong threadAffinityMask; private readonly GroupAffinity affinity;
private readonly Sensor powerSensor; private readonly Sensor powerSensor;
private readonly Sensor clockSensor; private readonly Sensor clockSensor;
@ -284,7 +284,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
public Core(int index, CPUID[] threads, AMD17CPU cpu, ISettings settings) public Core(int index, CPUID[] threads, AMD17CPU cpu, ISettings settings)
{ {
this.cpu = cpu; this.cpu = cpu;
this.threadAffinityMask = 1UL << threads[0].Thread; this.affinity = threads[0].Affinity;
string coreString = cpu.CoreString(index); string coreString = cpu.CoreString(index);
this.powerSensor = this.powerSensor =
@ -294,7 +294,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
if (cpu.energyUnitMultiplier != 0) { if (cpu.energyUnitMultiplier != 0) {
if (Ring0.RdmsrTx(MSR_CORE_ENERGY_STAT, out uint energyConsumed, if (Ring0.RdmsrTx(MSR_CORE_ENERGY_STAT, out uint energyConsumed,
out _, threadAffinityMask)) out _, affinity))
{ {
lastEnergyTime = DateTime.UtcNow; lastEnergyTime = DateTime.UtcNow;
lastEnergyConsumed = energyConsumed; lastEnergyConsumed = energyConsumed;
@ -319,13 +319,13 @@ namespace OpenHardwareMonitor.Hardware.CPU {
DateTime energyTime = DateTime.MinValue; DateTime energyTime = DateTime.MinValue;
double? multiplier = null; double? multiplier = null;
ulong mask = ThreadAffinity.Set(threadAffinityMask); var previousAffinity = ThreadAffinity.Set(affinity);
if (Ring0.Rdmsr(MSR_CORE_ENERGY_STAT, out uint energyConsumed, out _)) { if (Ring0.Rdmsr(MSR_CORE_ENERGY_STAT, out uint energyConsumed, out _)) {
energyTime = DateTime.UtcNow; energyTime = DateTime.UtcNow;
} }
multiplier = GetMultiplier(); multiplier = GetMultiplier();
ThreadAffinity.Set(mask); ThreadAffinity.Set(previousAffinity);
if (cpu.energyUnitMultiplier != 0) { if (cpu.energyUnitMultiplier != 0) {
float deltaTime = (float)(energyTime - lastEnergyTime).TotalSeconds; float deltaTime = (float)(energyTime - lastEnergyTime).TotalSeconds;

View File

@ -23,10 +23,17 @@ namespace OpenHardwareMonitor.Hardware.CPU {
private static CPUID[][] GetProcessorThreads() { private static CPUID[][] GetProcessorThreads() {
List<CPUID> threads = new List<CPUID>(); List<CPUID> threads = new List<CPUID>();
for (int i = 0; i < 64; i++) { for (int i = 0; i < ThreadAffinity.ProcessorGroupCount; i++) {
try { for (int j = 0; j < 64; j++) {
threads.Add(new CPUID(i)); try {
} catch (ArgumentOutOfRangeException) { } if (!ThreadAffinity.IsValid(GroupAffinity.Single((ushort)i, j)))
continue;
var cpuid = CPUID.Get(i, j);
if (cpuid != null)
threads.Add(cpuid);
} catch (ArgumentOutOfRangeException) {
}
}
} }
SortedDictionary<uint, List<CPUID>> processors = SortedDictionary<uint, List<CPUID>> processors =
@ -172,6 +179,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
r.AppendLine(); r.AppendLine();
for (int j = 0; j < threads[i].Length; j++) for (int j = 0; j < threads[i].Length; j++)
for (int k = 0; k < threads[i][j].Length; k++) { 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(" CPU Thread: " + threads[i][j][k].Thread);
r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId); r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId);
r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId); r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId);

View File

@ -21,7 +21,9 @@ namespace OpenHardwareMonitor.Hardware.CPU {
internal class CPUID { internal class CPUID {
private readonly int group;
private readonly int thread; private readonly int thread;
private readonly GroupAffinity affinity;
private readonly Vendor vendor = Vendor.Unknown; private readonly Vendor vendor = Vendor.Unknown;
@ -68,80 +70,84 @@ namespace OpenHardwareMonitor.Hardware.CPU {
return count; 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.thread = thread;
this.affinity = affinity;
uint maxCpuid = 0; uint maxCpuid = 0;
uint maxCpuidExt = 0; uint maxCpuidExt = 0;
uint eax, ebx, ecx, edx; uint eax, ebx, ecx, edx;
if (thread >= 64) Opcode.Cpuid(CPUID_0, 0, out eax, out ebx, out ecx, out edx);
throw new ArgumentOutOfRangeException("thread"); if (eax > 0)
ulong mask = 1UL << thread; maxCpuid = eax;
else
return;
if (Opcode.CpuidTx(CPUID_0, 0, StringBuilder vendorBuilder = new StringBuilder();
out eax, out ebx, out ecx, out edx, mask)) { AppendRegister(vendorBuilder, ebx);
if (eax > 0) AppendRegister(vendorBuilder, edx);
maxCpuid = eax; AppendRegister(vendorBuilder, ecx);
else string cpuVendor = vendorBuilder.ToString();
return; switch (cpuVendor) {
case "GenuineIntel":
StringBuilder vendorBuilder = new StringBuilder(); vendor = Vendor.Intel;
AppendRegister(vendorBuilder, ebx); break;
AppendRegister(vendorBuilder, edx); case "AuthenticAMD":
AppendRegister(vendorBuilder, ecx); vendor = Vendor.AMD;
string cpuVendor = vendorBuilder.ToString(); break;
switch (cpuVendor) { default:
case "GenuineIntel": vendor = Vendor.Unknown;
vendor = Vendor.Intel; break;
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");
} }
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); maxCpuid = Math.Min(maxCpuid, 1024);
maxCpuidExt = Math.Min(maxCpuidExt, 1024); maxCpuidExt = Math.Min(maxCpuidExt, 1024);
cpuidData = new uint[maxCpuid + 1, 4]; cpuidData = new uint[maxCpuid + 1, 4];
for (uint i = 0; i < (maxCpuid + 1); i++) 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, 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]; cpuidExtData = new uint[maxCpuidExt + 1, 4];
for (uint i = 0; i < (maxCpuidExt + 1); i++) for (uint i = 0; i < (maxCpuidExt + 1); i++)
Opcode.CpuidTx(CPUID_EXT + i, 0, Opcode.Cpuid(CPUID_EXT + i, 0,
out cpuidExtData[i, 0], out cpuidExtData[i, 1], out cpuidExtData[i, 0], out cpuidExtData[i, 1],
out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask); out cpuidExtData[i, 2], out cpuidExtData[i, 3]);
StringBuilder nameBuilder = new StringBuilder(); StringBuilder nameBuilder = new StringBuilder();
for (uint i = 2; i <= 4; i++) { for (uint i = 2; i <= 4; i++) {
if (Opcode.CpuidTx(CPUID_EXT + i, 0, Opcode.Cpuid(CPUID_EXT + i, 0, out eax, out ebx, out ecx, out edx);
out eax, out ebx, out ecx, out edx, mask)) AppendRegister(nameBuilder, eax);
{ AppendRegister(nameBuilder, ebx);
AppendRegister(nameBuilder, eax); AppendRegister(nameBuilder, ecx);
AppendRegister(nameBuilder, ebx); AppendRegister(nameBuilder, edx);
AppendRegister(nameBuilder, ecx);
AppendRegister(nameBuilder, edx);
}
} }
nameBuilder.Replace('\0', ' '); nameBuilder.Replace('\0', ' ');
cpuBrandString = nameBuilder.ToString().Trim(); cpuBrandString = nameBuilder.ToString().Trim();
@ -250,10 +256,22 @@ namespace OpenHardwareMonitor.Hardware.CPU {
get { return cpuBrandString; } get { return cpuBrandString; }
} }
public int Group {
get {
return group;
}
}
public int Thread { public int Thread {
get { return thread; } get { return thread; }
} }
public GroupAffinity Affinity {
get {
return affinity;
}
}
public Vendor Vendor { public Vendor Vendor {
get { return vendor; } get { return vendor; }
} }

View File

@ -106,13 +106,13 @@ namespace OpenHardwareMonitor.Hardware.CPU {
} }
if (hasTimeStampCounter) { if (hasTimeStampCounter) {
ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread); var previousAffinity = ThreadAffinity.Set(cpuid[0][0].Affinity);
EstimateTimeStampCounterFrequency( EstimateTimeStampCounterFrequency(
out estimatedTimeStampCounterFrequency, out estimatedTimeStampCounterFrequency,
out estimatedTimeStampCounterFrequencyError); out estimatedTimeStampCounterFrequencyError);
ThreadAffinity.Set(mask); ThreadAffinity.Set(previousAffinity);
} else { } else {
estimatedTimeStampCounterFrequency = 0; 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; 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(" ");
r.Append((msr).ToString("X8", CultureInfo.InvariantCulture)); r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
r.Append(" "); r.Append(" ");
@ -240,7 +242,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
r.AppendLine(); r.AppendLine();
r.AppendLine(" MSR EDX EAX"); r.AppendLine(" MSR EDX EAX");
foreach (uint msr in msrArray) foreach (uint msr in msrArray)
AppendMSRData(r, msr, cpuid[i][0].Thread); AppendMSRData(r, msr, cpuid[i][0].Affinity);
r.AppendLine(); r.AppendLine();
} }
} }
@ -268,15 +270,15 @@ namespace OpenHardwareMonitor.Hardware.CPU {
if (hasTimeStampCounter && isInvariantTimeStampCounter) { if (hasTimeStampCounter && isInvariantTimeStampCounter) {
// make sure always the same thread is used // 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 // read time before and after getting the TSC to estimate the error
long firstTime = Stopwatch.GetTimestamp(); long firstTime = Stopwatch.GetTimestamp();
ulong timeStampCount = Opcode.Rdtsc(); ulong timeStampCount = Opcode.Rdtsc();
long time = Stopwatch.GetTimestamp(); long time = Stopwatch.GetTimestamp();
// restore the thread affinity mask // restore the previous thread affinity mask
ThreadAffinity.Set(mask); ThreadAffinity.Set(previousAffinity);
double delta = ((double)(time - lastTime)) / Stopwatch.Frequency; double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
double error = ((double)(time - firstTime)) / Stopwatch.Frequency; double error = ((double)(time - firstTime)) / Stopwatch.Frequency;

View File

@ -79,7 +79,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
float[] result = new float[coreCount]; float[] result = new float[coreCount];
for (int i = 0; i < coreCount; i++) { for (int i = 0; i < coreCount; i++) {
if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax, 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; result[i] = (eax >> 16) & 0xFF;
} else { } else {
result[i] = 100; result[i] = 100;
@ -419,7 +419,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
uint eax, edx; uint eax, edx;
// if reading is valid // if reading is valid
if (Ring0.RdmsrTx(IA32_THERM_STATUS_MSR, out eax, out edx, 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 // get the dist from tjMax from bits 22:16
float deltaT = ((eax & 0x007F0000) >> 16); float deltaT = ((eax & 0x007F0000) >> 16);
@ -435,7 +435,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
uint eax, edx; uint eax, edx;
// if reading is valid // if reading is valid
if (Ring0.RdmsrTx(IA32_PACKAGE_THERM_STATUS, out eax, out edx, 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 // get the dist from tjMax from bits 22:16
float deltaT = ((eax & 0x007F0000) >> 16); float deltaT = ((eax & 0x007F0000) >> 16);
@ -453,7 +453,8 @@ namespace OpenHardwareMonitor.Hardware.CPU {
for (int i = 0; i < coreClocks.Length; i++) { for (int i = 0; i < coreClocks.Length; i++) {
System.Threading.Thread.Sleep(1); System.Threading.Thread.Sleep(1);
if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx, if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
1UL << cpuid[i][0].Thread)) { cpuid[i][0].Affinity))
{
newBusClock = newBusClock =
TimeStampCounterFrequency / timeStampCounterMultiplier; TimeStampCounterFrequency / timeStampCounterMultiplier;
switch (microarchitecture) { switch (microarchitecture) {

57
Hardware/GroupAffinity.cs Normal file
View File

@ -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 <mmoeller@openhardwaremonitor.org>
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenHardwareMonitor.Hardware {
/// <summary>
/// This structure describes a group-specific affinity.
/// </summary>
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);
}
}
}

View File

@ -24,8 +24,8 @@ namespace OpenHardwareMonitor.Hardware.HDD {
new List<AbstractHarddrive>(); new List<AbstractHarddrive>();
public HarddriveGroup(ISettings settings) { public HarddriveGroup(ISettings settings) {
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix)
if (p == 4 || p == 128) return; return;
ISmart smart = new WindowsSmart(); ISmart smart = new WindowsSmart();

View File

@ -67,8 +67,7 @@ namespace OpenHardwareMonitor.Hardware.Heatmaster {
public HeatmasterGroup(ISettings settings) { public HeatmasterGroup(ISettings settings) {
// No implementation for Heatmaster on Unix systems // No implementation for Heatmaster on Unix systems
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix)
if ((p == 4) || (p == 128))
return; return;
string[] portNames = GetRegistryPortNames(); string[] portNames = GetRegistryPortNames();

View File

@ -50,8 +50,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
new Identifier(Identifier, "name").ToString(), name); new Identifier(Identifier, "name").ToString(), name);
ISuperIO[] superIO; ISuperIO[] superIO;
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix) {
if ((p == 4) || (p == 128)) {
this.lmSensors = new LMSensors(); this.lmSensors = new LMSensors();
superIO = lmSensors.SuperIO; superIO = lmSensors.SuperIO;
} else { } else {

View File

@ -61,8 +61,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
} }
private static string GetDllName() { private static string GetDllName() {
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix)
if ((p == 4) || (p == 128))
return "libnvidia-ml.so"; return "libnvidia-ml.so";
else else
return "nvml.dll"; return "nvml.dll";

View File

@ -19,8 +19,6 @@ namespace OpenHardwareMonitor.Hardware {
private static ulong size; private static ulong size;
public static void Open() { public static void Open() {
int p = (int)Environment.OSVersion.Platform;
byte[] rdtscCode; byte[] rdtscCode;
byte[] cpuidCode; byte[] cpuidCode;
if (IntPtr.Size == 4) { if (IntPtr.Size == 4) {
@ -29,7 +27,7 @@ namespace OpenHardwareMonitor.Hardware {
} else { } else {
rdtscCode = RDTSC_64; rdtscCode = RDTSC_64;
if ((p == 4) || (p == 128)) { // Unix if (OperatingSystem.IsUnix) { // Unix
cpuidCode = CPUID_64_LINUX; cpuidCode = CPUID_64_LINUX;
} else { // Windows } else { // Windows
cpuidCode = CPUID_64_WINDOWS; cpuidCode = CPUID_64_WINDOWS;
@ -38,7 +36,7 @@ namespace OpenHardwareMonitor.Hardware {
size = (ulong)(rdtscCode.Length + cpuidCode.Length); size = (ulong)(rdtscCode.Length + cpuidCode.Length);
if ((p == 4) || (p == 128)) { // Unix if (OperatingSystem.IsUnix) { // Unix
Assembly assembly = Assembly assembly =
Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " +
"PublicKeyToken=0738eb9f132ed756"); "PublicKeyToken=0738eb9f132ed756");
@ -81,8 +79,7 @@ namespace OpenHardwareMonitor.Hardware {
Rdtsc = null; Rdtsc = null;
Cpuid = null; Cpuid = null;
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix) { // Unix
if ((p == 4) || (p == 128)) { // Unix
Assembly assembly = Assembly assembly =
Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " +
"PublicKeyToken=0738eb9f132ed756"); "PublicKeyToken=0738eb9f132ed756");
@ -201,18 +198,18 @@ namespace OpenHardwareMonitor.Hardware {
public static bool CpuidTx(uint index, uint ecxValue, public static bool CpuidTx(uint index, uint ecxValue,
out uint eax, out uint ebx, out uint ecx, out uint edx, out uint eax, out uint ebx, out uint ecx, out uint edx,
ulong threadAffinityMask) { GroupAffinity affinity)
{
var previousAffinity = ThreadAffinity.Set(affinity);
ulong mask = ThreadAffinity.Set(threadAffinityMask); if (previousAffinity == GroupAffinity.Undefined) {
if (mask == 0) {
eax = ebx = ecx = edx = 0; eax = ebx = ecx = edx = 0;
return false; return false;
} }
Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx); Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx);
ThreadAffinity.Set(mask); ThreadAffinity.Set(previousAffinity);
return true; return true;
} }

View File

@ -4,7 +4,7 @@
License, v. 2.0. If a copy of the MPL was not distributed with this 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/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (C) 2012 Michael Möller <mmoeller@openhardwaremonitor.org> Copyright (C) 2012-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
*/ */
@ -13,9 +13,20 @@ using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace OpenHardwareMonitor.Hardware { 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) if (IntPtr.Size == 8)
return true; return true;

View File

@ -18,8 +18,7 @@ namespace OpenHardwareMonitor.Hardware.RAM {
public RAMGroup(SMBIOS smbios, ISettings settings) { public RAMGroup(SMBIOS smbios, ISettings settings) {
// No implementation for RAM on Unix systems // No implementation for RAM on Unix systems
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix) {
if ((p == 4) || (p == 128)) {
hardware = new Hardware[0]; hardware = new Hardware[0];
return; return;
} }

View File

@ -4,7 +4,7 @@
License, v. 2.0. If a copy of the MPL was not distributed with this 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/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (C) 2010-2016 Michael Möller <mmoeller@openhardwaremonitor.org> Copyright (C) 2010-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
*/ */
@ -80,7 +80,7 @@ namespace OpenHardwareMonitor.Hardware {
private static bool ExtractDriver(string fileName) { private static bool ExtractDriver(string fileName) {
string resourceName = "OpenHardwareMonitor.Hardware." + string resourceName = "OpenHardwareMonitor.Hardware." +
(OperatingSystem.Is64BitOperatingSystem() ? "WinRing0x64.sys" : (OperatingSystem.Is64BitOperatingSystem ? "WinRing0x64.sys" :
"WinRing0.sys"); "WinRing0.sys");
string[] names = GetAssembly().GetManifestResourceNames(); string[] names = GetAssembly().GetManifestResourceNames();
@ -129,8 +129,7 @@ namespace OpenHardwareMonitor.Hardware {
public static void Open() { public static void Open() {
// no implementation for unix systems // no implementation for unix systems
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix)
if ((p == 4) || (p == 128))
return; return;
if (driver != null) if (driver != null)
@ -284,13 +283,13 @@ namespace OpenHardwareMonitor.Hardware {
} }
public static bool RdmsrTx(uint index, out uint eax, out uint edx, 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); bool result = Rdmsr(index, out eax, out edx);
ThreadAffinity.Set(mask); ThreadAffinity.Set(previousAffinity);
return result; return result;
} }

View File

@ -42,8 +42,7 @@ namespace OpenHardwareMonitor.Hardware {
} }
public SMBIOS() { public SMBIOS() {
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix) {
if ((p == 4) || (p == 128)) {
this.raw = null; this.raw = null;
this.table = null; this.table = null;

View File

@ -184,8 +184,7 @@ namespace OpenHardwareMonitor.Hardware.TBalancer {
} }
private static string GetDllName() { private static string GetDllName() {
int p = (int)Environment.OSVersion.Platform; if (OperatingSystem.IsUnix)
if ((p == 4) || (p == 128))
return "libftd2xx.so"; return "libftd2xx.so";
else else
return "ftd2xx.dll"; return "ftd2xx.dll";

View File

@ -4,7 +4,7 @@
License, v. 2.0. If a copy of the MPL was not distributed with this 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/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (C) 2010-2014 Michael Möller <mmoeller@openhardwaremonitor.org> Copyright (C) 2010-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
*/ */
@ -15,29 +15,95 @@ namespace OpenHardwareMonitor.Hardware {
internal static class ThreadAffinity { internal static class ThreadAffinity {
public static ulong Set(ulong mask) { static ThreadAffinity() {
if (mask == 0) ProcessorGroupCount = GetProcessorGroupCount();
return 0; }
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;
}
}
/// <summary>
/// Sets the processor group affinity for the current thread.
/// </summary>
/// <param name="affinity">The processor group affinity.</param>
/// <returns>The previous processor group affinity.</returns>
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");
int p = (int)Environment.OSVersion.Platform;
if ((p == 4) || (p == 128)) { // Unix
ulong result = 0; ulong result = 0;
if (NativeMethods.sched_getaffinity(0, (IntPtr)Marshal.SizeOf(result), if (NativeMethods.sched_getaffinity(0, (IntPtr)8, ref result) != 0)
ref result) != 0) return GroupAffinity.Undefined;
return 0;
if (NativeMethods.sched_setaffinity(0, (IntPtr)Marshal.SizeOf(mask), ulong mask = affinity.Mask;
ref mask) != 0) if (NativeMethods.sched_setaffinity(0, (IntPtr)8, ref mask) != 0)
return 0; return GroupAffinity.Undefined;
return result;
} else { // Windows return new GroupAffinity(0, result);
} else {
UIntPtr uIntPtrMask; UIntPtr uIntPtrMask;
try { try {
uIntPtrMask = (UIntPtr)mask; uIntPtrMask = (UIntPtr)affinity.Mask;
} catch (OverflowException) { } catch (OverflowException) {
throw new ArgumentOutOfRangeException("mask"); 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);
} }
return (ulong)NativeMethods.SetThreadAffinityMask(
NativeMethods.GetCurrentThread(), uIntPtrMask);
} }
} }
@ -51,6 +117,25 @@ namespace OpenHardwareMonitor.Hardware {
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] [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"; private const string LIBC = "libc";
[DllImport(LIBC)] [DllImport(LIBC)]

View File

@ -64,6 +64,7 @@
<Compile Include="Hardware\Control.cs" /> <Compile Include="Hardware\Control.cs" />
<Compile Include="Hardware\CPU\AMD17CPU.cs" /> <Compile Include="Hardware\CPU\AMD17CPU.cs" />
<Compile Include="Hardware\FirmwareTable.cs" /> <Compile Include="Hardware\FirmwareTable.cs" />
<Compile Include="Hardware\GroupAffinity.cs" />
<Compile Include="Hardware\HDD\DebugSmart.cs" /> <Compile Include="Hardware\HDD\DebugSmart.cs" />
<Compile Include="Hardware\HDD\DriveAttributeValue.cs" /> <Compile Include="Hardware\HDD\DriveAttributeValue.cs" />
<Compile Include="Hardware\HDD\DriveThresholdValue.cs" /> <Compile Include="Hardware\HDD\DriveThresholdValue.cs" />

View File

@ -10,5 +10,5 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("0.9.2.3")] [assembly: AssemblyVersion("0.9.2.4")]
[assembly: AssemblyInformationalVersion("0.9.2.3 Alpha")] [assembly: AssemblyInformationalVersion("0.9.2.4 Alpha")]