Skip to content

Commit

Permalink
Fix: Support X86 Windows Environments in ThreadAffinity.cs
Browse files Browse the repository at this point in the history
Ref: #19
  • Loading branch information
L3tum committed Oct 22, 2020
1 parent d8ed136 commit eda5612
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 90 deletions.
4 changes: 2 additions & 2 deletions HardwareInformation.sln
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E1B535FC-D186-47C7-AFE3-70BC051A7CF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1B535FC-D186-47C7-AFE3-70BC051A7CF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1B535FC-D186-47C7-AFE3-70BC051A7CF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1B535FC-D186-47C7-AFE3-70BC051A7CF4}.Release|Any CPU.Build.0 = Release|Any CPU
{E1B535FC-D186-47C7-AFE3-70BC051A7CF4}.Debug|Any CPU.ActiveCfg = Debug|X86
{E1B535FC-D186-47C7-AFE3-70BC051A7CF4}.Debug|Any CPU.Build.0 = Debug|X86
{B2FFFB2B-A4C7-4E38-A8FE-FF5467317FBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2FFFB2B-A4C7-4E38-A8FE-FF5467317FBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2FFFB2B-A4C7-4E38-A8FE-FF5467317FBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down
2 changes: 2 additions & 0 deletions HardwareInformation/HardwareInformation.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>sgKey.snk</AssemblyOriginatorKeyFile>
<Description>.NET Standard 2 Cross-Platform Hardware Information Gatherer</Description>
<Configurations>Debug;Release</Configurations>
<Platforms>AnyCPU;X86</Platforms>
</PropertyGroup>

<PropertyGroup>
Expand Down
194 changes: 106 additions & 88 deletions HardwareInformation/ThreadAffinity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,119 +9,137 @@

namespace HardwareInformation
{
internal static class ThreadAffinity
{
internal static ulong Set(ulong mask = 0xffffffffuL)
{
if (mask == 0)
return 0;
internal static class ThreadAffinity
{
internal static ulong Set(ulong mask = 0xffffffffuL)
{
if (mask == 0)
{
return 0;
}

var x86Mask = (uint) mask;

var returnMask = 0xffffffffuL;

// Unix/POSIX
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// Unix/Posix
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 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
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;
}

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// OSX
return returnMask;
}

// Windows
var threads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread processThread in threads)
{
var threadId = NativeMethods.GetCurrentThreadId();

if (processThread.Id == threadId)
{
try
{
processThread.ProcessorAffinity = (IntPtr) mask;
}
catch (Win32Exception)
{
//Console.WriteLine("{0} with mask {1}", e.Message, GetIntBinaryString(mask));
// Intentionally left blank
}
}
}

//Console.WriteLine("Mask worked {0}", GetIntBinaryString(mask));

return returnMask;
}

private static string GetIntBinaryString(ulong n)
{
var b = new char[64];
var pos = 63;
var i = 0;

while (i < 64)
{
if ((n & (1uL << i)) != 0)
{
b[pos] = '1';
}
else
{
b[pos] = '0';
}

pos--;
i++;
}

return new string(b);
}

private static class NativeMethods
{
private const string KERNEL = "kernel32.dll";

private const string LIBC = "libc";

[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
public static extern int GetCurrentThreadId();

[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
public static extern int GetLastError();
var threads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread processThread in threads)
{
var threadId = NativeMethods.GetCurrentThreadId();

if (processThread.Id == threadId)
{
try
{
processThread.ProcessorAffinity = (IntPtr) (Environment.Is64BitProcess ? mask : x86Mask);
}
catch (Win32Exception)
{
//Console.WriteLine("{0} with mask {1}", e.Message, GetIntBinaryString(mask));
// Intentionally left blank
}
catch (OverflowException)
{
// Intentionally left blank
}

break;
}
}

//Console.WriteLine("Mask worked {0}", GetIntBinaryString(mask));

return returnMask;
}

private static string GetIntBinaryString(ulong n)
{
var b = new char[64];
var pos = 63;
var i = 0;

while (i < 64)
{
if ((n & (1uL << i)) != 0)
{
b[pos] = '1';
}
else
{
b[pos] = '0';
}

pos--;
i++;
}

return new string(b);
}

private static class NativeMethods
{
private const string KERNEL = "kernel32.dll";

private const string LIBC = "libc";

[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
public static extern int GetCurrentThreadId();

[DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
public static extern int GetLastError();

/// <summary>
/// If pid is zero, then the calling thread is used.
/// If pid is zero, then the calling thread is used.
/// </summary>
/// <param name="pid"></param>
/// <param name="maskSize"></param>
/// <param name="mask"></param>
/// <returns></returns>
[DllImport(LIBC)]
public static extern int sched_getaffinity(int pid, IntPtr maskSize,
ref ulong mask);
[DllImport(LIBC)]
public static extern int sched_getaffinity(int pid, IntPtr maskSize,
ref ulong mask);

/// <summary>
/// If pid is zero, then the calling thread is used.
/// If pid is zero, then the calling thread is used.
/// </summary>
/// <param name="pid"></param>
/// <param name="maskSize"></param>
/// <param name="mask"></param>
/// <returns></returns>
[DllImport(LIBC)]
public static extern int sched_setaffinity(int pid, IntPtr maskSize,
ref ulong mask);
public static extern int sched_setaffinity(int pid, IntPtr maskSize,
ref ulong mask);

[DllImport(LIBC, CharSet = CharSet.Unicode)]
public static extern int sysctlbyname(string function, ref Int32 coreCount, ref Int32 length, int newP = 0, int newPLength = 0);

public static extern int sysctlbyname(string function, ref int coreCount, ref int length, int newP = 0,
int newPLength = 0);
}
}
}
}

0 comments on commit eda5612

Please sign in to comment.