Added CPUID support for Linux.
This commit is contained in:
@@ -146,7 +146,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
|
||||
uint eax, edx;
|
||||
if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx,
|
||||
(UIntPtr)(1L << cpuid[i][0].Thread))) {
|
||||
1UL << cpuid[i][0].Thread)) {
|
||||
// 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);
|
||||
|
||||
@@ -87,10 +87,8 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
ActivateSensor(coreClocks[i]);
|
||||
}
|
||||
|
||||
// set affinity to the first thread for all frequency estimations
|
||||
IntPtr thread = NativeMethods.GetCurrentThread();
|
||||
UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread,
|
||||
(UIntPtr)(1L << cpuid[0][0].Thread));
|
||||
// set affinity to the first thread for all frequency estimations
|
||||
ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread);
|
||||
|
||||
uint ctlEax, ctlEdx;
|
||||
Ring0.Rdmsr(PERF_CTL_0, out ctlEax, out ctlEdx);
|
||||
@@ -104,7 +102,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
Ring0.Wrmsr(PERF_CTR_0, ctrEax, ctrEdx);
|
||||
|
||||
// restore the thread affinity.
|
||||
NativeMethods.SetThreadAffinityMask(thread, mask);
|
||||
ThreadAffinity.Set(mask);
|
||||
|
||||
Update();
|
||||
}
|
||||
@@ -208,7 +206,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
|
||||
uint curEax, curEdx;
|
||||
if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
|
||||
(UIntPtr)(1L << cpuid[i][0].Thread)))
|
||||
1UL << cpuid[i][0].Thread))
|
||||
{
|
||||
// 8:6 CpuDid: current core divisor ID
|
||||
// 5:0 CpuFid: current core frequency ID
|
||||
@@ -232,16 +230,5 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class NativeMethods {
|
||||
private const string KERNEL = "kernel32.dll";
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern UIntPtr
|
||||
SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern IntPtr GetCurrentThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,10 +101,6 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
}
|
||||
|
||||
public CPUGroup(ISettings settings) {
|
||||
// No implementation for cpuid on Unix systems
|
||||
int p = (int)Environment.OSVersion.Platform;
|
||||
if ((p == 4) || (p == 128))
|
||||
return;
|
||||
|
||||
CPUID[][] processorThreads = GetProcessorThreads();
|
||||
this.threads = new CPUID[processorThreads.Length][][];
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
|
||||
if (thread >= 32)
|
||||
throw new ArgumentOutOfRangeException("thread");
|
||||
UIntPtr mask = (UIntPtr)(1L << thread);
|
||||
ulong mask = 1UL << thread;
|
||||
|
||||
if (Opcode.CpuidTx(CPUID_0, 0,
|
||||
out eax, out ebx, out ecx, out edx, mask)) {
|
||||
|
||||
+10
-20
@@ -130,8 +130,12 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
}
|
||||
|
||||
if (hasTimeStampCounter) {
|
||||
ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread);
|
||||
|
||||
estimatedTimeStampCounterFrequency =
|
||||
EstimateTimeStampCounterFrequency();
|
||||
EstimateTimeStampCounterFrequency();
|
||||
|
||||
ThreadAffinity.Set(mask);
|
||||
} else {
|
||||
estimatedTimeStampCounterFrequency = 0;
|
||||
}
|
||||
@@ -139,7 +143,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
timeStampCounterFrequency = estimatedTimeStampCounterFrequency;
|
||||
}
|
||||
|
||||
private static double EstimateTimeStampCounterFrequency() {
|
||||
private static double EstimateTimeStampCounterFrequency() {
|
||||
// preload the function
|
||||
EstimateTimeStampCounterFrequency(0);
|
||||
EstimateTimeStampCounterFrequency(0);
|
||||
@@ -148,6 +152,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
List<double> estimatedFrequency = new List<double>(3);
|
||||
for (int i = 0; i < 3; i++)
|
||||
estimatedFrequency.Add(1e-6 * EstimateTimeStampCounterFrequency(0.025));
|
||||
|
||||
estimatedFrequency.Sort();
|
||||
return estimatedFrequency[1];
|
||||
}
|
||||
@@ -156,7 +161,6 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
long ticks = (long)(timeWindow * Stopwatch.Frequency);
|
||||
ulong countBegin, countEnd;
|
||||
|
||||
Thread.BeginThreadAffinity();
|
||||
long timeBegin = Stopwatch.GetTimestamp() +
|
||||
(long)Math.Ceiling(0.001 * ticks);
|
||||
long timeEnd = timeBegin + ticks;
|
||||
@@ -164,7 +168,6 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
countBegin = Opcode.Rdtsc();
|
||||
while (Stopwatch.GetTimestamp() < timeEnd) { }
|
||||
countEnd = Opcode.Rdtsc();
|
||||
Thread.EndThreadAffinity();
|
||||
|
||||
return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) /
|
||||
(timeEnd - timeBegin);
|
||||
@@ -173,7 +176,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
|
||||
private static void AppendMSRData(StringBuilder r, uint msr, int thread) {
|
||||
uint eax, edx;
|
||||
if (Ring0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) {
|
||||
if (Ring0.RdmsrTx(msr, out eax, out edx, 1UL << thread)) {
|
||||
r.Append(" ");
|
||||
r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
|
||||
r.Append(" ");
|
||||
@@ -264,9 +267,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
if (hasTimeStampCounter && isInvariantTimeStampCounter) {
|
||||
|
||||
// make sure always the same thread is used
|
||||
IntPtr thread = NativeMethods.GetCurrentThread();
|
||||
UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread,
|
||||
(UIntPtr)(1L << cpuid[0][0].Thread));
|
||||
ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread);
|
||||
|
||||
// read time before and after getting the TSC to estimate the error
|
||||
long firstTime = Stopwatch.GetTimestamp();
|
||||
@@ -274,7 +275,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
long time = Stopwatch.GetTimestamp();
|
||||
|
||||
// restore the thread affinity mask
|
||||
NativeMethods.SetThreadAffinityMask(thread, mask);
|
||||
ThreadAffinity.Set(mask);
|
||||
|
||||
double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
|
||||
double error = ((double)(time - firstTime)) / Stopwatch.Frequency;
|
||||
@@ -304,16 +305,5 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
totalLoad.Value = cpuLoad.GetTotalLoad();
|
||||
}
|
||||
}
|
||||
|
||||
private static class NativeMethods {
|
||||
private const string KERNEL = "kernel32.dll";
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern UIntPtr
|
||||
SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern IntPtr GetCurrentThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
tjMax = new float[coreCount];
|
||||
for (int i = 0; i < coreCount; i++) {
|
||||
if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
|
||||
out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) {
|
||||
out edx, 1UL << cpuid[i][0].Thread)) {
|
||||
tjMax[i] = (eax >> 16) & 0xFF;
|
||||
} else {
|
||||
tjMax[i] = 100;
|
||||
@@ -217,7 +217,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
uint eax, edx;
|
||||
if (Ring0.RdmsrTx(
|
||||
IA32_THERM_STATUS_MSR, out eax, out edx,
|
||||
(UIntPtr)(1L << cpuid[i][0].Thread))) {
|
||||
1UL << cpuid[i][0].Thread)) {
|
||||
// if reading is valid
|
||||
if ((eax & 0x80000000) != 0) {
|
||||
// get the dist from tjMax from bits 22:16
|
||||
@@ -237,7 +237,7 @@ 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,
|
||||
(UIntPtr)(1L << cpuid[i][0].Thread)))
|
||||
1UL << cpuid[i][0].Thread))
|
||||
{
|
||||
newBusClock =
|
||||
TimeStampCounterFrequency / timeStampCounterMultiplier;
|
||||
|
||||
+91
-69
@@ -37,17 +37,17 @@
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Mono.Unix.Native;
|
||||
|
||||
namespace OpenHardwareMonitor.Hardware {
|
||||
internal static class Opcode {
|
||||
|
||||
private static IntPtr codeBuffer;
|
||||
private static ulong size;
|
||||
|
||||
public static void Open() {
|
||||
// No implementation for Unix systems
|
||||
public static void Open() {
|
||||
int p = (int)Environment.OSVersion.Platform;
|
||||
if ((p == 4) || (p == 128))
|
||||
return;
|
||||
|
||||
|
||||
byte[] rdtscCode;
|
||||
byte[] cpuidCode;
|
||||
if (IntPtr.Size == 4) {
|
||||
@@ -55,13 +55,25 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
cpuidCode = CPUID_32;
|
||||
} else {
|
||||
rdtscCode = RDTSC_64;
|
||||
cpuidCode = CPUID_64;
|
||||
|
||||
if ((p == 4) || (p == 128)) { // Unix
|
||||
cpuidCode = CPUID_64_LINUX;
|
||||
} else { // Windows
|
||||
cpuidCode = CPUID_64_WINDOWS;
|
||||
}
|
||||
}
|
||||
|
||||
size = (ulong)(rdtscCode.Length + cpuidCode.Length);
|
||||
|
||||
if ((p == 4) || (p == 128)) { // Unix
|
||||
codeBuffer = Syscall.mmap(IntPtr.Zero, size,
|
||||
MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC,
|
||||
MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_PRIVATE, -1, 0);
|
||||
} else { // Windows
|
||||
codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
|
||||
(UIntPtr)size, AllocationType.COMMIT | AllocationType.RESERVE,
|
||||
MemoryProtection.EXECUTE_READWRITE);
|
||||
}
|
||||
|
||||
codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
|
||||
(UIntPtr)(rdtscCode.Length + cpuidCode.Length),
|
||||
AllocationType.COMMIT | AllocationType.RESERVE,
|
||||
MemoryProtection.EXECUTE_READWRITE);
|
||||
|
||||
Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length);
|
||||
|
||||
@@ -72,15 +84,20 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length);
|
||||
|
||||
Cpuid = Marshal.GetDelegateForFunctionPointer(
|
||||
cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
|
||||
cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
|
||||
}
|
||||
|
||||
public static void Close() {
|
||||
Rdtsc = null;
|
||||
Cpuid = null;
|
||||
|
||||
NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero,
|
||||
FreeType.RELEASE);
|
||||
|
||||
int p = (int)Environment.OSVersion.Platform;
|
||||
if ((p == 4) || (p == 128)) { // Unix
|
||||
Syscall.munmap(codeBuffer, size);
|
||||
} else { // Windows
|
||||
NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero,
|
||||
FreeType.RELEASE);
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
@@ -99,8 +116,8 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
|
||||
private static readonly byte[] RDTSC_64 = new byte[] {
|
||||
0x0F, 0x31, // rdtsc
|
||||
0x48, 0xC1, 0xE2, 0x20, // shl rdx,20h
|
||||
0x48, 0x0B, 0xC2, // or rax,rdx
|
||||
0x48, 0xC1, 0xE2, 0x20, // shl rdx, 20h
|
||||
0x48, 0x0B, 0xC2, // or rax, rdx
|
||||
0xC3 // ret
|
||||
};
|
||||
|
||||
@@ -125,71 +142,83 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
|
||||
private static readonly byte[] CPUID_32 = new byte[] {
|
||||
0x55, // push ebp
|
||||
0x8B, 0xEC, // mov ebp,esp
|
||||
0x83, 0xEC, 0x10, // sub esp,10h
|
||||
0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp+8]
|
||||
0x8B, 0x4D, 0x0C, // mov ecx,dword ptr [ebp+0Ch]
|
||||
0x8B, 0xEC, // mov ebp, esp
|
||||
0x83, 0xEC, 0x10, // sub esp, 10h
|
||||
0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8]
|
||||
0x8B, 0x4D, 0x0C, // mov ecx, dword ptr [ebp+0Ch]
|
||||
0x53, // push ebx
|
||||
0x0F, 0xA2, // cpuid
|
||||
0x56, // push esi
|
||||
0x8D, 0x75, 0xF0, // lea esi,[info]
|
||||
0x89, 0x06, // mov dword ptr [esi],eax
|
||||
0x8B, 0x45, 0x10, // mov eax,dword ptr [eax]
|
||||
0x89, 0x5E, 0x04, // mov dword ptr [esi+4],ebx
|
||||
0x89, 0x4E, 0x08, // mov dword ptr [esi+8],ecx
|
||||
0x89, 0x56, 0x0C, // mov dword ptr [esi+0Ch],edx
|
||||
0x8B, 0x4D, 0xF0, // mov ecx,dword ptr [info]
|
||||
0x89, 0x08, // mov dword ptr [eax],ecx
|
||||
0x8B, 0x45, 0x14, // mov eax,dword ptr [ebx]
|
||||
0x8B, 0x4D, 0xF4, // mov ecx,dword ptr [ebp-0Ch]
|
||||
0x89, 0x08, // mov dword ptr [eax],ecx
|
||||
0x8B, 0x45, 0x18, // mov eax,dword ptr [ecx]
|
||||
0x8B, 0x4D, 0xF8, // mov ecx,dword ptr [ebp-8]
|
||||
0x89, 0x08, // mov dword ptr [eax],ecx
|
||||
0x8B, 0x45, 0x1C, // mov eax,dword ptr [edx]
|
||||
0x8B, 0x4D, 0xFC, // mov ecx,dword ptr [ebp-4]
|
||||
0x8D, 0x75, 0xF0, // lea esi, [info]
|
||||
0x89, 0x06, // mov dword ptr [esi],eax
|
||||
0x8B, 0x45, 0x10, // mov eax, dword ptr [eax]
|
||||
0x89, 0x5E, 0x04, // mov dword ptr [esi+4], ebx
|
||||
0x89, 0x4E, 0x08, // mov dword ptr [esi+8], ecx
|
||||
0x89, 0x56, 0x0C, // mov dword ptr [esi+0Ch], edx
|
||||
0x8B, 0x4D, 0xF0, // mov ecx, dword ptr [info]
|
||||
0x89, 0x08, // mov dword ptr [eax], ecx
|
||||
0x8B, 0x45, 0x14, // mov eax, dword ptr [ebx]
|
||||
0x8B, 0x4D, 0xF4, // mov ecx, dword ptr [ebp-0Ch]
|
||||
0x89, 0x08, // mov dword ptr [eax], ecx
|
||||
0x8B, 0x45, 0x18, // mov eax, dword ptr [ecx]
|
||||
0x8B, 0x4D, 0xF8, // mov ecx, dword ptr [ebp-8]
|
||||
0x89, 0x08, // mov dword ptr [eax], ecx
|
||||
0x8B, 0x45, 0x1C, // mov eax, dword ptr [edx]
|
||||
0x8B, 0x4D, 0xFC, // mov ecx, dword ptr [ebp-4]
|
||||
0x5E, // pop esi
|
||||
0x89, 0x08, // mov dword ptr [eax],ecx
|
||||
0x89, 0x08, // mov dword ptr [eax], ecx
|
||||
0x5B, // pop ebx
|
||||
0xC9, // leave
|
||||
0xC2, 0x18, 0x00 // ret 18h
|
||||
};
|
||||
|
||||
private static readonly byte[] CPUID_64 = new byte[] {
|
||||
0x48, 0x89, 0x5C, 0x24, 0x08, // mov qword ptr [rsp+8],rbx
|
||||
0x8B, 0xC1, // mov eax,ecx
|
||||
0x8B, 0xCA, // mov ecx,edx
|
||||
0x0F, 0xA2, // cpuid
|
||||
0x41, 0x89, 0x00, // mov dword ptr [r8],eax
|
||||
0x48, 0x8B, 0x44, 0x24, 0x28, // mov rax,qword ptr [ecx]
|
||||
0x41, 0x89, 0x19, // mov dword ptr [r9],ebx
|
||||
0x48, 0x8B, 0x5C, 0x24, 0x08, // mov rbx,qword ptr [rsp+8]
|
||||
0x89, 0x08, // mov dword ptr [rax],ecx
|
||||
0x48, 0x8B, 0x44, 0x24, 0x30, // mov rax,qword ptr [rsp+30h]
|
||||
0x89, 0x10, // mov dword ptr [rax],edx
|
||||
private static readonly byte[] CPUID_64_WINDOWS = new byte[] {
|
||||
0x48, 0x89, 0x5C, 0x24, 0x08, // mov qword ptr [rsp+8], rbx
|
||||
0x8B, 0xC1, // mov eax, ecx
|
||||
0x8B, 0xCA, // mov ecx, edx
|
||||
0x0F, 0xA2, // cpuid
|
||||
0x41, 0x89, 0x00, // mov dword ptr [r8], eax
|
||||
0x48, 0x8B, 0x44, 0x24, 0x28, // mov rax, qword ptr [rsp+28h]
|
||||
0x41, 0x89, 0x19, // mov dword ptr [r9], ebx
|
||||
0x48, 0x8B, 0x5C, 0x24, 0x08, // mov rbx, qword ptr [rsp+8]
|
||||
0x89, 0x08, // mov dword ptr [rax], ecx
|
||||
0x48, 0x8B, 0x44, 0x24, 0x30, // mov rax, qword ptr [rsp+30h]
|
||||
0x89, 0x10, // mov dword ptr [rax], edx
|
||||
0xC3 // ret
|
||||
};
|
||||
|
||||
private static readonly byte[] CPUID_64_LINUX = new byte[] {
|
||||
0x49, 0x89, 0xD2, // mov r10, rdx
|
||||
0x49, 0x89, 0xCB, // mov r11, rcx
|
||||
0x53, // push rbx
|
||||
0x89, 0xF8, // mov eax, edi
|
||||
0x89, 0xF1, // mov ecx, esi
|
||||
0x0F, 0xA2, // cpuid
|
||||
0x41, 0x89, 0x02, // mov dword ptr [r10], eax
|
||||
0x41, 0x89, 0x1B, // mov dword ptr [r11], ebx
|
||||
0x41, 0x89, 0x08, // mov dword ptr [r8], ecx
|
||||
0x41, 0x89, 0x11, // mov dword ptr [r9], edx
|
||||
0x5B, // pop rbx
|
||||
0xC3, // ret
|
||||
};
|
||||
|
||||
public static bool CpuidTx(uint index, uint ecxValue,
|
||||
out uint eax, out uint ebx, out uint ecx, out uint edx,
|
||||
UIntPtr threadAffinityMask) {
|
||||
ulong threadAffinityMask) {
|
||||
|
||||
ulong mask = ThreadAffinity.Set(threadAffinityMask);
|
||||
|
||||
IntPtr thread = NativeMethods.GetCurrentThread();
|
||||
UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread,
|
||||
threadAffinityMask);
|
||||
|
||||
if (mask == UIntPtr.Zero) {
|
||||
if (mask == 0) {
|
||||
eax = ebx = ecx = edx = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx);
|
||||
|
||||
NativeMethods.SetThreadAffinityMask(thread, mask);
|
||||
|
||||
ThreadAffinity.Set(mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
[Flags()]
|
||||
public enum AllocationType : uint {
|
||||
COMMIT = 0x1000,
|
||||
@@ -222,7 +251,7 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
RELEASE = 0x8000
|
||||
}
|
||||
|
||||
private static class NativeMethods {
|
||||
private static class NativeMethods {
|
||||
private const string KERNEL = "kernel32.dll";
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
@@ -231,14 +260,7 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize,
|
||||
FreeType dwFreeType);
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern UIntPtr
|
||||
SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern IntPtr GetCurrentThread();
|
||||
FreeType dwFreeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-16
@@ -95,6 +95,11 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
}
|
||||
|
||||
public static void Open() {
|
||||
// No implementation for Unix systems
|
||||
int p = (int)Environment.OSVersion.Platform;
|
||||
if ((p == 4) || (p == 128))
|
||||
return;
|
||||
|
||||
if (driver != null)
|
||||
return;
|
||||
|
||||
@@ -170,15 +175,13 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
}
|
||||
|
||||
public static bool RdmsrTx(uint index, out uint eax, out uint edx,
|
||||
UIntPtr threadAffinityMask)
|
||||
ulong threadAffinityMask)
|
||||
{
|
||||
IntPtr thread = NativeMethods.GetCurrentThread();
|
||||
UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread,
|
||||
threadAffinityMask);
|
||||
ulong mask = ThreadAffinity.Set(threadAffinityMask);
|
||||
|
||||
bool result = Rdmsr(index, out eax, out edx);
|
||||
|
||||
NativeMethods.SetThreadAffinityMask(thread, mask);
|
||||
ThreadAffinity.Set(mask);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -276,16 +279,5 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
|
||||
return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
|
||||
}
|
||||
|
||||
private static class NativeMethods {
|
||||
private const string KERNEL = "kernel32.dll";
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern UIntPtr
|
||||
SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern IntPtr GetCurrentThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the License.
|
||||
|
||||
The Original Code is the Open Hardware Monitor code.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael Möller <m.moeller@gmx.ch>.
|
||||
Portions created by the Initial Developer are Copyright (C) 2010
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenHardwareMonitor.Hardware {
|
||||
|
||||
internal static class ThreadAffinity {
|
||||
|
||||
public static ulong Set(ulong mask) {
|
||||
if (mask == 0)
|
||||
return 0;
|
||||
|
||||
int p = (int)Environment.OSVersion.Platform;
|
||||
if ((p == 4) || (p == 128)) { // Unix
|
||||
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
|
||||
return (ulong)NativeMethods.SetThreadAffinityMask(
|
||||
NativeMethods.GetCurrentThread(), (UIntPtr)mask);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NativeMethods {
|
||||
private const string KERNEL = "kernel32.dll";
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern UIntPtr
|
||||
SetThreadAffinityMask(IntPtr handle, UIntPtr mask);
|
||||
|
||||
[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
|
||||
public static extern IntPtr GetCurrentThread();
|
||||
|
||||
private const string LIBC = "libc";
|
||||
|
||||
[DllImport(LIBC)]
|
||||
public static extern int sched_getaffinity(int pid, IntPtr maskSize,
|
||||
ref ulong mask);
|
||||
|
||||
[DllImport(LIBC)]
|
||||
public static extern int sched_setaffinity(int pid, IntPtr maskSize,
|
||||
ref ulong mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user