Add support for multiple processor groups.

Merge from upstream.
This commit is contained in:
Phyxion
2020-05-11 13:29:52 +02:00
parent a18136b55e
commit 3cc3d9139c
22 changed files with 390 additions and 135 deletions
@@ -23,7 +23,7 @@ namespace LibreHardwareMonitor.Hardware.Controller.Heatmaster
public HeatmasterGroup(ISettings settings)
{
// No implementation for Heatmaster on Unix systems
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
return;
@@ -120,7 +120,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
{
Thread.Sleep(1);
if (Ring0.ReadMsr(FIDVID_STATUS, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(FIDVID_STATUS, out uint eax, out uint _, _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.
@@ -143,7 +143,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
bool 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
Ring0.ReadMsr(HWCR, out uint hwcrEax, out uint hwcrEdx);
@@ -164,12 +164,12 @@ namespace LibreHardwareMonitor.Hardware.CPU
Ring0.WriteMsr(HWCR, hwcrEax, hwcrEdx);
// restore the thread affinity.
ThreadAffinity.Set(mask);
ThreadAffinity.Set(previousAffinity);
// the file reader for lm-sensors support on Linux
_temperatureStream = null;
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
{
string[] devicePaths = Directory.GetDirectories("/sys/class/hwmon/");
foreach (string path in devicePaths)
@@ -177,8 +177,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
string name = null;
try
{
using (StreamReader reader = new StreamReader(path + "/device/name"))
name = reader.ReadLine();
using StreamReader reader = new StreamReader(path + "/device/name");
name = reader.ReadLine();
}
catch (IOException)
{ }
@@ -450,7 +451,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
{
Thread.Sleep(1);
if (Ring0.ReadMsr(COFVID_STATUS, out uint curEax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(COFVID_STATUS, out uint curEax, out uint _, _cpuId[i][0].Affinity))
{
double multiplier = GetCoreMultiplier(curEax);
@@ -96,7 +96,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
private readonly Sensor _coreTemperatureTctlTdie;
private readonly Sensor[] _ccdTemperatures;
private readonly Sensor _coreVoltage;
private readonly Amd17Cpu _hw;
private readonly Amd17Cpu _hardware;
private readonly Sensor _packagePower;
private readonly Sensor _socVoltage;
private Sensor _ccdsMaxTemperature;
@@ -104,20 +104,20 @@ namespace LibreHardwareMonitor.Hardware.CPU
private DateTime _lastPwrTime = new DateTime(0);
private uint _lastPwrValue;
public Processor(Hardware hw)
public Processor(Hardware hardware)
{
_hw = (Amd17Cpu)hw;
_hardware = (Amd17Cpu)hardware;
Nodes = new List<NumaNode>();
_packagePower = new Sensor("Package Power", _hw._sensorPower++, SensorType.Power, _hw, _hw._settings);
_coreTemperatureTctl = new Sensor("Core (Tctl)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
_coreTemperatureTdie = new Sensor("Core (Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
_coreTemperatureTctlTdie = new Sensor("Core (Tctl/Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
_packagePower = new Sensor("Package Power", _hardware._sensorPower++, SensorType.Power, _hardware, _hardware._settings);
_coreTemperatureTctl = new Sensor("Core (Tctl)", _hardware._sensorTemperatures++, SensorType.Temperature, _hardware, _hardware._settings);
_coreTemperatureTdie = new Sensor("Core (Tdie)", _hardware._sensorTemperatures++, SensorType.Temperature, _hardware, _hardware._settings);
_coreTemperatureTctlTdie = new Sensor("Core (Tctl/Tdie)", _hardware._sensorTemperatures++, SensorType.Temperature, _hardware, _hardware._settings);
_ccdTemperatures = new Sensor[8]; // Hardcoded until there's a way to get max CCDs.
_coreVoltage = new Sensor("Core (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
_socVoltage = new Sensor("SoC (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
_coreVoltage = new Sensor("Core (SVI2 TFN)", _hardware._sensorVoltage++, SensorType.Voltage, _hardware, _hardware._settings);
_socVoltage = new Sensor("SoC (SVI2 TFN)", _hardware._sensorVoltage++, SensorType.Voltage, _hardware, _hardware._settings);
_hw.ActivateSensor(_packagePower);
_hardware.ActivateSensor(_packagePower);
}
public List<NumaNode> Nodes { get; }
@@ -131,7 +131,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
return;
ulong mask = Ring0.ThreadAffinitySet(1UL << cpu.Thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(cpu.Affinity);
// MSRC001_0299
// TU [19:16]
@@ -195,7 +195,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset);
Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1);
Ring0.ThreadAffinitySet(mask);
ThreadAffinity.Set(previousAffinity);
// power consumption
// power.Value = (float) ((double)pu * 0.125);
@@ -250,14 +250,14 @@ namespace LibreHardwareMonitor.Hardware.CPU
_coreTemperatureTctl.Value = t;
_coreTemperatureTdie.Value = t + offset;
_hw.ActivateSensor(_coreTemperatureTctl);
_hw.ActivateSensor(_coreTemperatureTdie);
_hardware.ActivateSensor(_coreTemperatureTctl);
_hardware.ActivateSensor(_coreTemperatureTdie);
}
else
{
// Zen 2 doesn't have an offset so Tdie and Tctl are the same.
_coreTemperatureTctlTdie.Value = t;
_hw.ActivateSensor(_coreTemperatureTctlTdie);
_hardware.ActivateSensor(_coreTemperatureTctlTdie);
}
// Tested only on R5 3600 & Threadripper 3960X.
@@ -279,11 +279,11 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (_ccdTemperatures[i] == null)
{
_hw.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)",
_hw._sensorTemperatures++,
_hardware.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)",
_hardware._sensorTemperatures++,
SensorType.Temperature,
_hw,
_hw._settings));
_hardware,
_hardware._settings));
}
_ccdTemperatures[i].Value = ccdTemp;
@@ -296,20 +296,20 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (_ccdsMaxTemperature == null)
{
_hw.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)",
_hw._sensorTemperatures++,
_hardware.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)",
_hardware._sensorTemperatures++,
SensorType.Temperature,
_hw,
_hw._settings));
_hardware,
_hardware._settings));
}
if (_ccdsAverageTemperature == null)
{
_hw.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)",
_hw._sensorTemperatures++,
_hardware.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)",
_hardware._sensorTemperatures++,
SensorType.Temperature,
_hw,
_hw._settings));
_hardware,
_hardware._settings));
}
_ccdsMaxTemperature.Value = activeCcds.Max(x => x.Value);
@@ -329,7 +329,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
vcc = 1.550 - vidStep * svi0PlaneXVddCor;
_coreVoltage.Value = (float)vcc;
_hw.ActivateSensor(_coreVoltage);
_hardware.ActivateSensor(_coreVoltage);
}
// SoC (0x02), not every Zen cpu has this voltage.
@@ -339,7 +339,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
vcc = 1.550 - vidStep * svi0PlaneXVddCor;
_socVoltage.Value = (float)vcc;
_hw.ActivateSensor(_socVoltage);
_hardware.ActivateSensor(_socVoltage);
}
}
@@ -357,7 +357,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (node == null)
{
node = new NumaNode(_hw, numaId);
node = new NumaNode(_hardware, numaId);
Nodes.Add(node);
}
@@ -441,7 +441,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
return;
ulong mask = Ring0.ThreadAffinitySet(1UL << cpu.Thread);
var previousAffinity = ThreadAffinity.Set(cpu.Affinity);
// MSRC001_0299
// TU [19:16]
@@ -476,7 +476,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
// int IddDiv = (int)((eax >> 30) & 0x03);
// int IddValue = (int)((eax >> 22) & 0xff);
// int CpuVid = (int)((eax >> 14) & 0xff);
Ring0.ThreadAffinitySet(mask);
ThreadAffinity.Set(previousAffinity);
// clock
// CoreCOF is (Core::X86::Msr::PStateDef[CpuFid[7:0]] / Core::X86::Msr::PStateDef[CpuDfsId]) * 200
@@ -96,6 +96,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
{
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);
@@ -124,19 +125,30 @@ namespace LibreHardwareMonitor.Hardware.CPU
private static CpuId[][] GetProcessorThreads()
{
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));
}
catch (ArgumentOutOfRangeException)
{
// All cores found.
break;
try
{
if (!ThreadAffinity.IsValid(GroupAffinity.Single((ushort)i, j)))
continue;
var cpuid = CpuId.Get(i, j);
if (cpuid != null)
threads.Add(cpuid);
}
catch (ArgumentOutOfRangeException)
{
// All cores found.
break;
}
}
}
SortedDictionary<uint, List<CpuId>> processors = new SortedDictionary<uint, List<CpuId>>();
foreach (CpuId thread in threads)
{
+67 -13
View File
@@ -18,25 +18,28 @@ namespace LibreHardwareMonitor.Hardware.CPU
public class CpuId
{
// ReSharper disable InconsistentNaming
public const uint CPUID_0 = 0;
public const uint CPUID_EXT = 0x80000000;
// ReSharper restore InconsistentNaming
public CpuId(int thread)
/// <summary>
/// Initializes a new instance of the <see cref="CpuId" /> class.
/// </summary>
/// <param name="group">The group.</param>
/// <param name="thread">The thread.</param>
/// <param name="affinity">The affinity.</param>
private CpuId(int group, int thread, GroupAffinity affinity)
{
Thread = thread;
Group = group;
Affinity = affinity;
uint threadMaskWith;
uint coreMaskWith;
Thread = thread;
uint maxCpuidExt;
if (thread >= 64)
throw new ArgumentOutOfRangeException(nameof(thread));
ulong mask = 1UL << thread;
uint maxCpuid;
if (OpCode.CpuidTx(CPUID_0, 0, out uint eax, out uint ebx, out uint ecx, out uint edx, mask))
if (OpCode.CpuId(CPUID_0, 0, out uint eax, out uint ebx, out uint ecx, out uint edx))
{
if (eax > 0)
maxCpuid = eax;
@@ -49,6 +52,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
AppendRegister(vendorBuilder, edx);
AppendRegister(vendorBuilder, ecx);
string cpuVendor = vendorBuilder.ToString();
switch (cpuVendor)
{
case "GenuineIntel":
@@ -62,7 +66,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
break;
}
if (OpCode.CpuidTx(CPUID_EXT, 0, out eax, out _, out _, out _, mask))
if (OpCode.CpuId(CPUID_EXT, 0, out eax, out _, out _, out _))
{
if (eax > CPUID_EXT)
maxCpuidExt = eax - CPUID_EXT;
@@ -85,19 +89,19 @@ namespace LibreHardwareMonitor.Hardware.CPU
Data = new uint[maxCpuid + 1, 4];
for (uint i = 0; i < maxCpuid + 1; i++)
{
OpCode.CpuidTx(CPUID_0 + i, 0, out Data[i, 0], out Data[i, 1], out Data[i, 2], out Data[i, 3], mask);
OpCode.CpuId(CPUID_0 + i, 0, out Data[i, 0], out Data[i, 1], out Data[i, 2], out Data[i, 3]);
}
ExtData = new uint[maxCpuidExt + 1, 4];
for (uint i = 0; i < maxCpuidExt + 1; i++)
{
OpCode.CpuidTx(CPUID_EXT + i, 0, out ExtData[i, 0], out ExtData[i, 1], out ExtData[i, 2], out ExtData[i, 3], mask);
OpCode.CpuId(CPUID_EXT + i, 0, out ExtData[i, 0], out ExtData[i, 1], out ExtData[i, 2], out ExtData[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))
if (OpCode.CpuId(CPUID_EXT + i, 0, out eax, out ebx, out ecx, out edx))
{
AppendRegister(nameBuilder, eax);
AppendRegister(nameBuilder, ebx);
@@ -141,6 +145,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
switch (Vendor)
{
case Vendor.Intel:
{
uint maxCoreAndThreadIdPerPackage = (Data[1, 1] >> 16) & 0xFF;
uint maxCoreIdPerPackage;
if (maxCpuid >= 4)
@@ -151,7 +156,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
threadMaskWith = NextLog2(maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage);
coreMaskWith = NextLog2(maxCoreIdPerPackage);
break;
}
case Vendor.AMD:
{
uint corePerPackage;
if (maxCpuidExt >= 8)
corePerPackage = (ExtData[8, 2] & 0xFF) + 1;
@@ -171,22 +178,31 @@ namespace LibreHardwareMonitor.Hardware.CPU
switch (maxCoresPerDie)
{
case 0x04: // Ryzen
{
coreMaskWith = NextLog2(16);
break;
}
case 0x05: // Threadripper
{
coreMaskWith = NextLog2(32);
break;
}
case 0x06: // Epic
{
coreMaskWith = NextLog2(64);
break;
}
}
}
break;
}
default:
{
threadMaskWith = 0;
coreMaskWith = 0;
break;
}
}
ProcessorId = ApicId >> (int)(coreMaskWith + threadMaskWith);
@@ -194,6 +210,8 @@ namespace LibreHardwareMonitor.Hardware.CPU
ThreadId = ApicId - (ProcessorId << (int)(coreMaskWith + threadMaskWith)) - (CoreId << (int)threadMaskWith);
}
public GroupAffinity Affinity { get; }
public uint ApicId { get; }
public string BrandString { get; } = string.Empty;
@@ -206,6 +224,8 @@ namespace LibreHardwareMonitor.Hardware.CPU
public uint Family { get; }
public int Group { get; }
public uint Model { get; }
public string Name { get; } = string.Empty;
@@ -220,6 +240,35 @@ namespace LibreHardwareMonitor.Hardware.CPU
public Vendor Vendor { get; } = Vendor.Unknown;
/// <summary>
/// Gets the specified <see cref="CpuId" />.
/// </summary>
/// <param name="group">The group.</param>
/// <param name="thread">The thread.</param>
/// <returns><see cref="CpuId" />.</returns>
public static CpuId Get(int group, int thread)
{
if (thread >= 64)
return null;
var affinity = GroupAffinity.Single((ushort)group, thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(affinity);
if (previousAffinity == GroupAffinity.Undefined)
return null;
try
{
return new CpuId(group, thread, affinity);
}
finally
{
ThreadAffinity.Set(previousAffinity);
}
}
private static void AppendRegister(StringBuilder b, uint value)
{
b.Append((char)(value & 0xff));
@@ -244,5 +293,10 @@ namespace LibreHardwareMonitor.Hardware.CPU
return count;
}
// ReSharper disable InconsistentNaming
public const uint CPUID_0 = 0;
public const uint CPUID_EXT = 0x80000000;
// ReSharper restore InconsistentNaming
}
}
@@ -79,9 +79,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (HasTimeStampCounter)
{
ulong mask = ThreadAffinity.Set(1UL << cpuId[0][0].Thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(cpuId[0][0].Affinity);
EstimateTimeStampCounterFrequency(out _estimatedTimeStampCounterFrequency, out _estimatedTimeStampCounterFrequencyError);
ThreadAffinity.Set(mask);
ThreadAffinity.Set(previousAffinity);
}
else
{
@@ -182,9 +182,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
error = beginError + endError;
}
private static void AppendMsrData(StringBuilder r, uint msr, int thread)
private static void AppendMsrData(StringBuilder r, uint msr, GroupAffinity affinity)
{
if (Ring0.ReadMsr(msr, out uint eax, out uint edx, 1UL << thread))
if (Ring0.ReadMsr(msr, out uint eax, out uint edx, affinity))
{
r.Append(" ");
r.Append(msr.ToString("X8", CultureInfo.InvariantCulture));
@@ -241,7 +241,7 @@ namespace LibreHardwareMonitor.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();
}
@@ -255,7 +255,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (HasTimeStampCounter && _isInvariantTimeStampCounter)
{
// make sure always the same thread is used
ulong mask = ThreadAffinity.Set(1UL << _cpuId[0][0].Thread);
GroupAffinity previousAffinity = ThreadAffinity.Set(_cpuId[0][0].Affinity);
// read time before and after getting the TSC to estimate the error
long firstTime = Stopwatch.GetTimestamp();
@@ -263,7 +263,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
long time = Stopwatch.GetTimestamp();
// restore the thread affinity mask
ThreadAffinity.Set(mask);
ThreadAffinity.Set(previousAffinity);
double delta = (double)(time - _lastTime) / Stopwatch.Frequency;
double error = (double)(time - firstTime) / Stopwatch.Frequency;
@@ -413,7 +413,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
float[] result = new float[_coreCount];
for (int i = 0; i < _coreCount; i++)
{
if (Ring0.ReadMsr(IA32_TEMPERATURE_TARGET, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(IA32_TEMPERATURE_TARGET, out uint eax, out uint _, _cpuId[i][0].Affinity))
result[i] = (eax >> 16) & 0xFF;
else
result[i] = 100;
@@ -461,7 +461,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
for (int i = 0; i < _coreTemperatures.Length; i++)
{
// if reading is valid
if (Ring0.ReadMsr(IA32_THERM_STATUS_MSR, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread) && (eax & 0x80000000) != 0)
if (Ring0.ReadMsr(IA32_THERM_STATUS_MSR, out uint eax, out uint _, _cpuId[i][0].Affinity) && (eax & 0x80000000) != 0)
{
// get the dist from tjMax from bits 22:16
float deltaT = (eax & 0x007F0000) >> 16;
@@ -493,7 +493,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (_packageTemperature != null)
{
// if reading is valid
if (Ring0.ReadMsr(IA32_PACKAGE_THERM_STATUS, out uint eax, out uint _, 1UL << _cpuId[0][0].Thread) && (eax & 0x80000000) != 0)
if (Ring0.ReadMsr(IA32_PACKAGE_THERM_STATUS, out uint eax, out uint _, _cpuId[0][0].Affinity) && (eax & 0x80000000) != 0)
{
// get the dist from tjMax from bits 22:16
float deltaT = (eax & 0x007F0000) >> 16;
@@ -513,7 +513,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
for (int i = 0; i < _coreClocks.Length; i++)
{
System.Threading.Thread.Sleep(1);
if (Ring0.ReadMsr(IA32_PERF_STATUS, out uint eax, out uint _, 1UL << _cpuId[i][0].Thread))
if (Ring0.ReadMsr(IA32_PERF_STATUS, out uint eax, out uint _, _cpuId[i][0].Affinity))
{
newBusClock = TimeStampCounterFrequency / _timeStampCounterMultiplier;
switch (_microArchitecture)
@@ -0,0 +1,94 @@
// 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) LibreHardwareMonitor and Contributors.
// Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> and Contributors.
// All Rights Reserved.
namespace LibreHardwareMonitor.Hardware
{
/// <summary>
/// This structure describes a group-specific affinity.
/// </summary>
public readonly struct GroupAffinity
{
public static GroupAffinity Undefined = new GroupAffinity(ushort.MaxValue, 0);
/// <summary>
/// Initializes a new instance of the <see cref="GroupAffinity" /> struct.
/// </summary>
/// <param name="group">The group.</param>
/// <param name="mask">The mask.</param>
public GroupAffinity(ushort group, ulong mask)
{
Group = group;
Mask = mask;
}
/// <summary>
/// Gets a single group affinity.
/// </summary>
/// <param name="group">The group.</param>
/// <param name="index">The index.</param>
/// <returns><see cref="GroupAffinity" />.</returns>
public static GroupAffinity Single(ushort group, int index)
{
return new GroupAffinity(group, 1UL << index);
}
/// <summary>
/// Gets the group.
/// </summary>
public ushort Group { get; }
/// <summary>
/// Gets the mask.
/// </summary>
public ulong Mask { get; }
/// <summary>
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
/// </summary>
/// <param name="o">The <see cref="System.Object" /> to compare with this instance.</param>
/// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
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);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode()
{
return Group.GetHashCode() ^ Mask.GetHashCode();
}
/// <summary>
/// Implements the == operator.
/// </summary>
/// <param name="a1">The a1.</param>
/// <param name="a2">The a2.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(GroupAffinity a1, GroupAffinity a2)
{
return (a1.Group == a2.Group) && (a1.Mask == a2.Mask);
}
/// <summary>
/// Implements the != operator.
/// </summary>
/// <param name="a1">The a1.</param>
/// <param name="a2">The a2.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(GroupAffinity a1, GroupAffinity a2)
{
return (a1.Group != a2.Group) || (a1.Mask != a2.Mask);
}
}
}
@@ -15,7 +15,7 @@ namespace LibreHardwareMonitor.Hardware.Memory
public MemoryGroup(ISettings settings)
{
// No implementation for RAM on Unix systems
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
{
_hardware = new Hardware[0];
return;
@@ -49,7 +49,7 @@ namespace LibreHardwareMonitor.Hardware.Motherboard
_customName = settings.GetValue(new Identifier(Identifier, "name").ToString(), _name);
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
{
_lmSensors = new LMSensors();
superIO = _lmSensors.SuperIO;
+11 -11
View File
@@ -12,7 +12,7 @@ namespace LibreHardwareMonitor.Hardware
{
internal static class OpCode
{
public static CpuidDelegate Cpuid;
public static CpuidDelegate CpuId;
public static RdtscDelegate Rdtsc;
private static IntPtr _codeBuffer;
@@ -218,12 +218,12 @@ namespace LibreHardwareMonitor.Hardware
{
rdTscCode = Rdtsc64;
cpuidCode = Software.OperatingSystem.IsLinux ? CpuId64Linux : CpuId64Windows;
cpuidCode = Software.OperatingSystem.IsUnix ? CpuId64Linux : CpuId64Windows;
}
_size = (ulong)(rdTscCode.Length + cpuidCode.Length);
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
{
Assembly assembly = Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + "PublicKeyToken=0738eb9f132ed756");
Type sysCall = assembly.GetType("Mono.Unix.Native.Syscall");
@@ -255,15 +255,15 @@ namespace LibreHardwareMonitor.Hardware
Rdtsc = Marshal.GetDelegateForFunctionPointer(_codeBuffer, typeof(RdtscDelegate)) as RdtscDelegate;
IntPtr cpuidAddress = (IntPtr)((long)_codeBuffer + rdTscCode.Length);
Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length);
Cpuid = Marshal.GetDelegateForFunctionPointer(cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
CpuId = Marshal.GetDelegateForFunctionPointer(cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
}
public static void Close()
{
Rdtsc = null;
Cpuid = null;
CpuId = null;
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
{
Assembly assembly = Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " + "PublicKeyToken=0738eb9f132ed756");
Type sysCall = assembly.GetType("Mono.Unix.Native.Syscall");
@@ -276,17 +276,17 @@ namespace LibreHardwareMonitor.Hardware
}
}
public static bool CpuidTx(uint index, uint ecxValue, out uint eax, out uint ebx, out uint ecx, out uint edx, ulong threadAffinityMask)
public static bool CpuIdTx(uint index, uint ecxValue, out uint eax, out uint ebx, out uint ecx, out uint edx, GroupAffinity affinity)
{
ulong mask = ThreadAffinity.Set(threadAffinityMask);
if (mask == 0)
GroupAffinity previousAffinity = ThreadAffinity.Set(affinity);
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);
CpuId(index, ecxValue, out eax, out ebx, out ecx, out edx);
ThreadAffinity.Set(previousAffinity);
return true;
}
}
+15 -20
View File
@@ -23,7 +23,7 @@ namespace LibreHardwareMonitor.Hardware
private static string _fileName;
private static Mutex _isaBusMutex;
private static readonly StringBuilder Report = new StringBuilder();
private static readonly StringBuilder _report = new StringBuilder();
public static bool IsOpen
{
@@ -138,7 +138,7 @@ namespace LibreHardwareMonitor.Hardware
public static void Open()
{
// no implementation for unix systems
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
return;
if (_driver != null)
@@ -146,7 +146,7 @@ namespace LibreHardwareMonitor.Hardware
// clear the current report
Report.Length = 0;
_report.Length = 0;
_driver = new KernelDriver("WinRing0_1_2_0");
_driver.Open();
@@ -164,7 +164,7 @@ namespace LibreHardwareMonitor.Hardware
if (!_driver.IsOpen)
{
_driver.Delete();
Report.AppendLine("Status: Opening driver failed after install");
_report.AppendLine("Status: Opening driver failed after install");
}
}
else
@@ -184,20 +184,20 @@ namespace LibreHardwareMonitor.Hardware
if (!_driver.IsOpen)
{
_driver.Delete();
Report.AppendLine("Status: Opening driver failed after reinstall");
_report.AppendLine("Status: Opening driver failed after reinstall");
}
}
else
{
Report.AppendLine("Status: Installing driver \"" + _fileName + "\" failed" + (File.Exists(_fileName) ? " and file exists" : string.Empty));
Report.AppendLine("First Exception: " + errorFirstInstall);
Report.AppendLine("Second Exception: " + errorSecondInstall);
_report.AppendLine("Status: Installing driver \"" + _fileName + "\" failed" + (File.Exists(_fileName) ? " and file exists" : string.Empty));
_report.AppendLine("First Exception: " + errorFirstInstall);
_report.AppendLine("Second Exception: " + errorSecondInstall);
}
}
}
else
{
Report.AppendLine("Status: Extracting driver failed");
_report.AppendLine("Status: Extracting driver failed");
}
try
@@ -280,20 +280,15 @@ namespace LibreHardwareMonitor.Hardware
{ }
}
}
public static ulong ThreadAffinitySet(ulong mask)
{
return ThreadAffinity.Set(mask);
}
public static string GetReport()
{
if (Report.Length > 0)
if (_report.Length > 0)
{
StringBuilder r = new StringBuilder();
r.AppendLine("Ring0");
r.AppendLine();
r.Append(Report);
r.Append(_report);
r.AppendLine();
return r.ToString();
}
@@ -342,11 +337,11 @@ namespace LibreHardwareMonitor.Hardware
return result;
}
public static bool ReadMsr(uint index, out uint eax, out uint edx, ulong threadAffinityMask)
public static bool ReadMsr(uint index, out uint eax, out uint edx, GroupAffinity affinity)
{
ulong mask = ThreadAffinity.Set(threadAffinityMask);
GroupAffinity previousAffinity = ThreadAffinity.Set(affinity);
bool result = ReadMsr(index, out eax, out edx);
ThreadAffinity.Set(mask);
ThreadAffinity.Set(previousAffinity);
return result;
}
+1 -1
View File
@@ -581,7 +581,7 @@ namespace LibreHardwareMonitor.Hardware
public SMBios()
{
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
{
_raw = null;
@@ -4,10 +4,6 @@
// Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> and Contributors.
// All Rights Reserved.
using System;
using System.Collections.Generic;
using LibreHardwareMonitor.Interop;
namespace LibreHardwareMonitor.Hardware.Storage
{
#if DEBUG
@@ -16,7 +16,7 @@ namespace LibreHardwareMonitor.Hardware.Storage
public StorageGroup(ISettings settings)
{
if (Software.OperatingSystem.IsLinux)
if (Software.OperatingSystem.IsUnix)
return;
//https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskdrive
@@ -5,38 +5,122 @@
// All Rights Reserved.
using System;
using System.Runtime.InteropServices;
using LibreHardwareMonitor.Interop;
namespace LibreHardwareMonitor.Hardware
{
internal static class ThreadAffinity
{
public static ulong Set(ulong mask)
/// <summary>
/// Initializes static members of the <see cref="ThreadAffinity" /> class.
/// </summary>
static ThreadAffinity()
{
if (mask == 0)
return 0;
ProcessorGroupCount = Software.OperatingSystem.IsUnix ? 1 : Kernel32.GetActiveProcessorGroupCount();
if (ProcessorGroupCount < 1)
ProcessorGroupCount = 1;
}
if (Software.OperatingSystem.IsLinux)
/// <summary>
/// Gets the processor group count.
/// </summary>
public static int ProcessorGroupCount { get; }
/// <summary>
/// Returns true if the <paramref name="affinity"/> is valid.
/// </summary>
/// <param name="affinity">The affinity.</param>
/// <returns><c>true</c> if the specified affinity is valid; otherwise, <c>false</c>.</returns>
public static bool IsValid(GroupAffinity affinity)
{
if (Software.OperatingSystem.IsUnix)
{
ulong result = 0;
if (Interop.LibC.sched_getaffinity(0, (IntPtr)Marshal.SizeOf(result), ref result) != 0)
return 0;
if (affinity.Group > 0)
return false;
}
return Interop.LibC.sched_setaffinity(0, (IntPtr)Marshal.SizeOf(mask), ref mask) != 0 ? (ulong) 0 : result;
try
{
GroupAffinity previousAffinity = Set(affinity);
if (previousAffinity == GroupAffinity.Undefined)
return false;
Set(previousAffinity);
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 (Software.OperatingSystem.IsUnix)
{
if (affinity.Group > 0)
throw new ArgumentOutOfRangeException(nameof(affinity));
ulong result = 0;
if (LibC.sched_getaffinity(0, (IntPtr)8, ref result) != 0)
return GroupAffinity.Undefined;
ulong mask = affinity.Mask;
if (LibC.sched_setaffinity(0, (IntPtr)8, ref mask) != 0)
return GroupAffinity.Undefined;
return new GroupAffinity(0, result);
}
UIntPtr uIntPtrMask;
try
{
uIntPtrMask = (UIntPtr)mask;
uIntPtrMask = (UIntPtr)affinity.Mask;
}
catch (OverflowException)
{
throw new ArgumentOutOfRangeException(nameof(mask));
throw new ArgumentOutOfRangeException(nameof(affinity));
}
var groupAffinity = new Kernel32.GROUP_AFFINITY { Group = affinity.Group, Mask = uIntPtrMask };
IntPtr currentThread = Kernel32.GetCurrentThread();
try
{
if (Kernel32.SetThreadGroupAffinity(currentThread,
ref groupAffinity,
out Kernel32.GROUP_AFFINITY previousGroupAffinity))
{
return new GroupAffinity(previousGroupAffinity.Group, (ulong)previousGroupAffinity.Mask);
}
return GroupAffinity.Undefined;
}
catch (EntryPointNotFoundException)
{
if (affinity.Group > 0)
throw new ArgumentOutOfRangeException(nameof(affinity));
ulong previous = (ulong)Kernel32.SetThreadAffinityMask(currentThread, uIntPtrMask);
return new GroupAffinity(0, previous);
}
return (ulong)Interop.Kernel32.SetThreadAffinityMask(Interop.Kernel32.GetCurrentThread(), uIntPtrMask);
}
}
}