Add support for multiple processor groups.
Merge from upstream.
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user