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.ExitCommand += exitClick;
int p = (int)Environment.OSVersion.Platform;
if ((p == 4) || (p == 128)) { // Unix
if (Hardware.OperatingSystem.IsUnix) { // Unix
treeView.RowHeight = Math.Max(treeView.RowHeight, 18);
splitContainer.BorderStyle = BorderStyle.None;
splitContainer.Border3DStyle = Border3DStyle.Adjust;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (C) 2012 Michael Möller <mmoeller@openhardwaremonitor.org>
Copyright (C) 2012-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
*/
@ -13,9 +13,20 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
namespace OpenHardwareMonitor.Hardware {
internal static class OperatingSystem {
public static class OperatingSystem {
public static bool Is64BitOperatingSystem() {
static OperatingSystem() {
int p = (int)Environment.OSVersion.Platform;
IsUnix = (p == 4) || (p == 6) || (p == 128);
Is64BitOperatingSystem = GetIs64BitOperatingSystem();
}
public static bool IsUnix { get; }
public static bool Is64BitOperatingSystem { get; }
private static bool GetIs64BitOperatingSystem() {
if (IntPtr.Size == 8)
return true;

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (C) 2010-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 {
public static ulong Set(ulong mask) {
if (mask == 0)
return 0;
static ThreadAffinity() {
ProcessorGroupCount = GetProcessorGroupCount();
}
private static int GetProcessorGroupCount() {
if (OperatingSystem.IsUnix)
return 1;
try {
return NativeMethods.GetActiveProcessorGroupCount();
} catch {
return 1;
}
}
public static int ProcessorGroupCount { get; }
public static bool IsValid(GroupAffinity affinity) {
if (OperatingSystem.IsUnix) {
if (affinity.Group > 0)
return false;
}
try {
var previous = Set(affinity);
if (previous == GroupAffinity.Undefined)
return false;
Set(previous);
return true;
} catch {
return false;
}
}
/// <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;
if (NativeMethods.sched_getaffinity(0, (IntPtr)Marshal.SizeOf(result),
ref result) != 0)
return 0;
if (NativeMethods.sched_setaffinity(0, (IntPtr)Marshal.SizeOf(mask),
ref mask) != 0)
return 0;
return result;
} else { // Windows
if (NativeMethods.sched_getaffinity(0, (IntPtr)8, ref result) != 0)
return GroupAffinity.Undefined;
ulong mask = affinity.Mask;
if (NativeMethods.sched_setaffinity(0, (IntPtr)8, ref mask) != 0)
return GroupAffinity.Undefined;
return new GroupAffinity(0, result);
} else {
UIntPtr uIntPtrMask;
try {
uIntPtrMask = (UIntPtr)mask;
uIntPtrMask = (UIntPtr)affinity.Mask;
} catch (OverflowException) {
throw new ArgumentOutOfRangeException("mask");
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)]
public static extern IntPtr GetCurrentThread();
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
public static extern ushort GetActiveProcessorGroupCount();
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct GROUP_AFFINITY {
public UIntPtr Mask;
[MarshalAs(UnmanagedType.U2)]
public ushort Group;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3,
ArraySubType = UnmanagedType.U2)]
public ushort[] Reserved;
}
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
public static extern bool SetThreadGroupAffinity(
IntPtr thread,
ref GROUP_AFFINITY groupAffinity,
out GROUP_AFFINITY previousGroupAffinity);
private const string LIBC = "libc";
[DllImport(LIBC)]

View File

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

View File

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