diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2019-03-14 22:30:00 +0100 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2019-03-14 14:30:00 -0700 |
commit | 23fbf7e7ab231876b9d54b52bac044cdde159118 (patch) | |
tree | 2f50034ca0d6a97c5d089b9ae9d3a5bfe576e1cd /src/gc | |
parent | 20e66e1a1ea4e93916026647bac3347e7863dd9b (diff) | |
download | coreclr-23fbf7e7ab231876b9d54b52bac044cdde159118.tar.gz coreclr-23fbf7e7ab231876b9d54b52bac044cdde159118.tar.bz2 coreclr-23fbf7e7ab231876b9d54b52bac044cdde159118.zip |
Fix GetProcessAffinityMask (#23247)
The function was returning mask not expected by runtime for coreclr
built with NUMA enabled on machines with multiple NUMA nodes.
The mask was 0 in case the current process was affinitized to CPUs
from multiple NUMA nodes. It was following MSDN doc, however the
doc turned out to be ambiguous. Moreover, the runtime depended
on the fact that on Windows, a process is never run on multiple
NUMA nodes unless is explicitly calls APIs to set ideal processor
for threads. But on Unix, there is no such case and by default, a
process is affinitized to all existing processors over all NUMA
nodes.
And there was one more issue. The GetProcessAffinityMask was returning
a mask within a single CPU group, which is a transformed view of
NUMA node on Windows. So the CPU indices in the mask didn't necessarily
correspond to the native Unix CPU indices. But, the SetThreadAffinityMask
was using the native Unix CPU indices.
To fix the problem, the GetProcessAffinityMask is changed so that
it always returns a mask corresponding to the native Unix CPU indices
(reporting upto 64 processors as the mask is 64 bit wide). Thus it
corresponds to what the SetThreadAffinityMask expects. And it also exactly
matches the behavior when NUMA support is not compiled in.
Moreover, the COMPlus_GCHeapAffinitizeMask bits now correspond to
the native Unix CPU indices.
The GetProcessAffinityMask is used by GC and thread pool only when
NUMA is not enabled using the COMPlus_GCCpuGroup env variable.
Diffstat (limited to 'src/gc')
-rw-r--r-- | src/gc/unix/gcenv.unix.cpp | 17 |
1 files changed, 6 insertions, 11 deletions
diff --git a/src/gc/unix/gcenv.unix.cpp b/src/gc/unix/gcenv.unix.cpp index 8148f6ff29..e64f62ac34 100644 --- a/src/gc/unix/gcenv.unix.cpp +++ b/src/gc/unix/gcenv.unix.cpp @@ -467,14 +467,9 @@ static uintptr_t GetFullAffinityMask(int cpuCount) // specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor. bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processAffinityMask, uintptr_t* systemAffinityMask) { - if (g_logicalCpuCount > 64) - { - *processAffinityMask = 0; - *systemAffinityMask = 0; - return true; - } + unsigned int cpuCountInMask = (g_logicalCpuCount > 64) ? 64 : g_logicalCpuCount; - uintptr_t systemMask = GetFullAffinityMask(g_logicalCpuCount); + uintptr_t systemMask = GetFullAffinityMask(cpuCountInMask); #if HAVE_SCHED_GETAFFINITY @@ -485,7 +480,7 @@ bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processAffinityMa { uintptr_t processMask = 0; - for (unsigned int i = 0; i < g_logicalCpuCount; i++) + for (unsigned int i = 0; i < cpuCountInMask; i++) { if (CPU_ISSET(i, &cpuSet)) { @@ -500,9 +495,9 @@ bool GCToOSInterface::GetCurrentProcessAffinityMask(uintptr_t* processAffinityMa else if (errno == EINVAL) { // There are more processors than can fit in a cpu_set_t - // return zero in both masks. - *processAffinityMask = 0; - *systemAffinityMask = 0; + // return all bits set for all processors (upto 64) for both masks + *processAffinityMask = systemMask; + *systemAffinityMask = systemMask; return true; } else |