Use the GCHeapAffinitizeRanges / GCHeapAffinitizeMask exclusively
authorJan Vorlicek <janvorli@microsoft.com>
Tue, 2 Apr 2019 21:35:09 +0000 (23:35 +0200)
committerJan Vorlicek <janvorli@microsoft.com>
Wed, 3 Apr 2019 19:12:09 +0000 (21:12 +0200)
The GCHeapAffinitizeRanges are now used only when CPU groups are enabled
and the GCHeapAffinitizeMask when CPU groups are disabled.

src/gc/env/gcenv.os.h
src/gc/gc.cpp
src/gc/gcconfig.cpp
src/gc/gcconfig.h
src/gc/unix/gcenv.unix.cpp
src/gc/windows/gcenv.windows.cpp
src/vm/gcenv.os.cpp

index 323e193..b98037b 100644 (file)
@@ -153,12 +153,12 @@ class AffinitySet
 
     uintptr_t m_bitset[MAX_SUPPORTED_CPUS / BitsPerBitsetEntry];
 
-    uintptr_t GetBitsetEntryMask(size_t cpuIndex)
+    static uintptr_t GetBitsetEntryMask(size_t cpuIndex)
     {
         return (uintptr_t)1 << (cpuIndex & (BitsPerBitsetEntry - 1));
     }
 
-    size_t GetBitsetEntryIndex(size_t cpuIndex)
+    static size_t GetBitsetEntryIndex(size_t cpuIndex)
     {
         return cpuIndex / BitsPerBitsetEntry;
     }
@@ -171,7 +171,7 @@ public:
     }
 
     // Check if the set contains a processor
-    bool Contains(size_t cpuIndex)
+    bool Contains(size_t cpuIndex) const
     {
         return (m_bitset[GetBitsetEntryIndex(cpuIndex)] & GetBitsetEntryMask(cpuIndex)) != 0;
     }
@@ -189,7 +189,7 @@ public:
     }
 
     // Check if the set is empty
-    bool IsEmpty()
+    bool IsEmpty() const
     {
         for (size_t i = 0; i < MAX_SUPPORTED_CPUS / BitsPerBitsetEntry; i++)
         {
@@ -203,7 +203,7 @@ public:
     }
 
     // Return number of processors in the affinity set
-    size_t Count()
+    size_t Count() const
     {
         size_t count = 0;
         for (size_t i = 0; i < MAX_SUPPORTED_CPUS; i++)
@@ -388,10 +388,13 @@ public:
     //  true if the priority boost was successful, false otherwise.
     static bool BoostThreadPriority();
 
-    // Get set of processors enabled for GC for the current process
+    // Set the set of processors enabled for GC threads for the current process based on config specified affinity mask and set
+    // Parameters:
+    //  configAffinityMask - mask specified by the GCHeapAffinitizeMask config
+    //  configAffinitySet - affinity set specified by the GCHeapAffinitizeRanges config
     // Return:
     //  set of enabled processors
-    static AffinitySet* GetCurrentProcessAffinitySet();
+    static const AffinitySet* SetGCThreadsAffinitySet(uintptr_t configAffinityMask, const AffinitySet* configAffinitySet);
 
     //
     // Global memory info
@@ -476,7 +479,6 @@ public:
     // Return:
     //  true if it succeeded
     static bool GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_no, uint16_t* node_no);
-
 };
 
 #endif // __GCENV_OS_H__
index 910ff07..704cf26 100644 (file)
@@ -34086,24 +34086,13 @@ HRESULT GCHeap::Initialize()
 
 #ifdef MULTIPLE_HEAPS
     AffinitySet config_affinity_set;
-    if (!ParseGCHeapAffinitySettings(&config_affinity_set))
+    if (!ParseGCHeapAffinitizeRanges(&config_affinity_set))
     {
         return CLR_E_GC_BAD_AFFINITY_CONFIG;
     }
 
-    AffinitySet* process_affinity_set = GCToOSInterface::GetCurrentProcessAffinitySet();
-
-    if (!config_affinity_set.IsEmpty())
-    {
-        // Update the process affinity set using the configured set
-        for (size_t i = 0; i < MAX_SUPPORTED_CPUS; i++)
-        {
-            if (process_affinity_set->Contains(i) && !config_affinity_set.Contains(i))
-            {
-                process_affinity_set->Remove(i);
-            }
-        }
-    }
+    uintptr_t config_affinity_mask = static_cast<uintptr_t>(GCConfig::GetGCHeapAffinitizeMask());
+    const AffinitySet* process_affinity_set = GCToOSInterface::SetGCThreadsAffinitySet(config_affinity_mask, &config_affinity_set);
 
     if (process_affinity_set->IsEmpty())
     {
@@ -34129,7 +34118,7 @@ HRESULT GCHeap::Initialize()
 
     if (gc_heap::heap_hard_limit)
     {
-        gc_heap::gc_thread_no_affinitize_p = (config_affinity_set.Count() == 0);
+        gc_heap::gc_thread_no_affinitize_p = ((config_affinity_set.Count() == 0) && (config_affinity_mask == 0));
     }
 
     if (!(gc_heap::gc_thread_no_affinitize_p))
index 1e9dbe1..b151511 100644 (file)
@@ -47,71 +47,56 @@ GC_CONFIGURATION_KEYS
 #undef INT_CONFIG
 }
 
-bool ParseGCHeapAffinitySettings(AffinitySet* config_affinity_set)
+bool ParseGCHeapAffinitizeRanges(AffinitySet* config_affinity_set)
 {
     bool success = true;
 
-    // Get the affinity set configured by the user
-    uintptr_t heap_affinity_mask = GCConfig::GetGCHeapAffinitizeMask();
-    if (heap_affinity_mask != 0)
+    GCConfigStringHolder cpu_index_ranges_holder(GCConfig::GetGCHeapAffinitizeRanges());
+    const char* cpu_index_ranges = cpu_index_ranges_holder.Get();
+
+    // The cpu index ranges is a comma separated list of indices or ranges of indices (e.g. 1-5).
+    // Example 1,3,5,7-9,12
+
+    if (cpu_index_ranges != NULL)
     {
-        for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
+        char* number_end;
+
+        do
         {
-            if (heap_affinity_mask & ((uintptr_t)1 << i))
+            size_t start_index = strtoul(cpu_index_ranges, &number_end, 10);
+
+            if (number_end == cpu_index_ranges)
             {
-                config_affinity_set->Add(i);
+                // No number found, invalid format
+                break;
             }
-        }
-    }
-    else
-    {
-        GCConfigStringHolder cpu_index_ranges_holder(GCConfig::GetGCHeapAffinitizeRanges());
-        const char* cpu_index_ranges = cpu_index_ranges_holder.Get();
 
-        // The cpu index ranges is a comma separated list of indices or ranges of indices (e.g. 1-5).
-        // Example 1,3,5,7-9,12
-
-        if (cpu_index_ranges != NULL)
-        {
-            char* number_end;
+            size_t end_index = start_index;
 
-            do
+            if (*number_end == '-')
             {
-                size_t start_index = strtoul(cpu_index_ranges, &number_end, 10);
-
-                if (number_end == cpu_index_ranges)
+                char* range_end_start = number_end + 1;
+                end_index = strtoul(range_end_start, &number_end, 10);
+                if (number_end == range_end_start)
                 {
                     // No number found, invalid format
                     break;
                 }
+            }
 
-                size_t end_index = start_index;
-
-                if (*number_end == '-')
-                {
-                    char* range_end_start = number_end + 1;
-                    end_index = strtoul(range_end_start, &number_end, 10);
-                    if (number_end == range_end_start)
-                    {
-                        // No number found, invalid format
-                        break;
-                    }
-                }
-
-                if ((start_index < MAX_SUPPORTED_CPUS) && end_index < (MAX_SUPPORTED_CPUS))
+            if ((start_index < MAX_SUPPORTED_CPUS) && end_index < (MAX_SUPPORTED_CPUS))
+            {
+                for (size_t i = start_index; i <= end_index; i++)
                 {
-                    for (size_t i = start_index; i <= end_index; i++)
-                    {
-                        config_affinity_set->Add(i);
-                    }
+                    config_affinity_set->Add(i);
                 }
-
-                cpu_index_ranges = number_end + 1;
             }
-            while (*number_end == ',');
 
-            success = (*number_end == '\0');
+            cpu_index_ranges = number_end + 1;
         }
+        while (*number_end == ',');
+
+        success = (*number_end == '\0');
     }
 
     return success;
index f292a12..b2fea16 100644 (file)
@@ -156,6 +156,6 @@ static void Initialize();
 
 };
 
-bool ParseGCHeapAffinitySettings(AffinitySet* config_affinity_set);
+bool ParseGCHeapAffinitizeRanges(AffinitySet* config_affinity_set);
 
 #endif // __GCCONFIG_H__
index 140c546..4719dc9 100644 (file)
@@ -490,11 +490,26 @@ bool GCToOSInterface::BoostThreadPriority()
     return false;
 }
 
-// Get set of processors enabled for GC for the current process
+// Set the set of processors enabled for GC threads for the current process based on config specified affinity mask and set
+// Parameters:
+//  configAffinityMask - mask specified by the GCHeapAffinitizeMask config
+//  configAffinitySet  - affinity set specified by the GCHeapAffinitizeRanges config
 // Return:
 //  set of enabled processors
-AffinitySet* GCToOSInterface::GetCurrentProcessAffinitySet()
+const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffinityMask, const AffinitySet* configAffinitySet)
 {
+    if (!configAffinitySet->IsEmpty())
+    {
+        // Update the process affinity set using the configured set
+        for (size_t i = 0; i < MAX_SUPPORTED_CPUS; i++)
+        {
+            if (g_processAffinitySet.Contains(i) && !configAffinitySet->Contains(i))
+            {
+                g_processAffinitySet.Remove(i);
+            }
+        }
+    }
+
     return &g_processAffinitySet;
 }
 
index 738fdec..5d323dd 100644 (file)
@@ -518,16 +518,30 @@ bool GCToOSInterface::Initialize()
     InitNumaNodeInfo();
     InitCPUGroupInfo();
 
-    uintptr_t pmask, smask;
-    if (!!::GetProcessAffinityMask(::GetCurrentProcess(), (PDWORD_PTR)&pmask, (PDWORD_PTR)&smask))
+    if (CanEnableGCCPUGroups())
     {
-        pmask &= smask;
-
-        for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
+        // When CPU groups are enabled, then the process is not bound by the process affinity set at process launch.
+        // Set the initial affinity mask so that all processors are enabled.
+        for (size_t i = 0; i < g_nProcessors; i++)
+        {
+            g_processAffinitySet.Add(i);
+        }
+    }
+    else
+    {
+        // When CPU groups are disabled, the process affinity mask specified at the process launch cannot be
+        // escaped.
+        uintptr_t pmask, smask;
+        if (!!::GetProcessAffinityMask(::GetCurrentProcess(), (PDWORD_PTR)&pmask, (PDWORD_PTR)&smask))
         {
-            if ((pmask & ((uintptr_t)1 << i)) != 0)
+            pmask &= smask;
+
+            for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
             {
-                g_processAffinitySet.Add(i);
+                if ((pmask & ((uintptr_t)1 << i)) != 0)
+                {
+                    g_processAffinitySet.Add(i);
+                }
             }
         }
     }
@@ -953,11 +967,44 @@ bool GCToOSInterface::BoostThreadPriority()
     return !!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
 }
 
-// Get set of processors enabled for GC for the current process
+// Set the set of processors enabled for GC threads for the current process based on config specified affinity mask and set
+// Parameters:
+//  configAffinityMask - mask specified by the GCHeapAffinitizeMask config
+//  configAffinitySet  - affinity set specified by the GCHeapAffinitizeRanges config
 // Return:
 //  set of enabled processors
-AffinitySet* GCToOSInterface::GetCurrentProcessAffinitySet()
+const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffinityMask, const AffinitySet* configAffinitySet)
 {
+    // When the configAffinitySet is not empty, enforce the cpu groups
+    if (CanEnableGCCPUGroups())
+    {
+        if (!configAffinitySet->IsEmpty())
+        {
+            // Update the process affinity set using the configured set
+            for (size_t i = 0; i < MAX_SUPPORTED_CPUS; i++)
+            {
+                if (g_processAffinitySet.Contains(i) && !configAffinitySet->Contains(i))
+                {
+                    g_processAffinitySet.Remove(i);
+                }
+            }
+        }
+    }
+    else
+    {
+        if (configAffinityMask != 0)
+        {
+            // Update the process affinity set using the configured mask
+            for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
+            {
+                if (g_processAffinitySet.Contains(i) && ((configAffinityMask & ((uintptr_t)1 << i)) == 0))
+                {
+                    g_processAffinitySet.Remove(i);
+                }
+            }
+        }
+    }
+
     return &g_processAffinitySet;
 }
 
@@ -1205,7 +1252,6 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n
         uint16_t gn, gpn;
         GetGroupForProcessor((uint16_t)heap_number, &gn, &gpn);
 
-//      dprintf(3, ("using processor group %d, mask %Ix for heap %d\n", gn, (uintptr_t)1 << gpn), heap_number));
         *proc_no = GroupProcNo(gn, gpn).GetCombinedValue();
 
         if (GCToOSInterface::CanEnableGCNumaAware())
@@ -1232,7 +1278,6 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n
             {
                 if (bit_number == heap_number)
                 {
-                    //dprintf (3, ("Using processor %d for heap %d", proc_number, heap_number));
                     *proc_no = GroupProcNo(GroupProcNo::NoGroup, proc_number).GetCombinedValue();
 
                     if (GCToOSInterface::CanEnableGCNumaAware())
index fcf716f..243b897 100644 (file)
@@ -66,16 +66,30 @@ bool GCToOSInterface::Initialize()
     g_pageSizeUnixInl = GetOsPageSize();
 #endif
 
-    uintptr_t pmask, smask;
-    if (!!::GetProcessAffinityMask(::GetCurrentProcess(), (PDWORD_PTR)&pmask, (PDWORD_PTR)&smask))
+    if (CPUGroupInfo::CanEnableGCCPUGroups())
     {
-        pmask &= smask;
-
-        for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
+        // When CPU groups are enabled, then the process is not bound by the process affinity set at process launch.
+        // Set the initial affinity mask so that all processors are enabled.
+        for (size_t i = 0; i < CPUGroupInfo::GetNumActiveProcessors(); i++)
+        {
+            g_processAffinitySet.Add(i);
+        }
+    }
+    else
+    {
+        // When CPU groups are disabled, the process affinity mask specified at the process launch cannot be
+        // escaped.
+        uintptr_t pmask, smask;
+        if (!!::GetProcessAffinityMask(::GetCurrentProcess(), (PDWORD_PTR)&pmask, (PDWORD_PTR)&smask))
         {
-            if ((pmask & ((uintptr_t)1 << i)) != 0)
+            pmask &= smask;
+
+            for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
             {
-                g_processAffinitySet.Add(i);
+                if ((pmask & ((uintptr_t)1 << i)) != 0)
+                {
+                    g_processAffinitySet.Add(i);
+                }
             }
         }
     }
@@ -419,11 +433,43 @@ bool GCToOSInterface::BoostThreadPriority()
     return !!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
 }
 
-// Get set of processors enabled for GC for the current process
+// Set the set of processors enabled for GC threads for the current process based on config specified affinity mask and set
+// Parameters:
+//  configAffinityMask - mask specified by the GCHeapAffinitizeMask config
+//  configAffinitySet  - affinity set specified by the GCHeapAffinitizeRanges config
 // Return:
 //  set of enabled processors
-AffinitySet* GCToOSInterface::GetCurrentProcessAffinitySet()
+const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffinityMask, const AffinitySet* configAffinitySet)
 {
+    if (CPUGroupInfo::CanEnableGCCPUGroups())
+    {
+        if (!configAffinitySet->IsEmpty())
+        {
+            // Update the process affinity set using the configured set
+            for (size_t i = 0; i < MAX_SUPPORTED_CPUS; i++)
+            {
+                if (g_processAffinitySet.Contains(i) && !configAffinitySet->Contains(i))
+                {
+                    g_processAffinitySet.Remove(i);
+                }
+            }
+        }
+    }
+    else
+    {
+        if (configAffinityMask != 0)
+        {
+            // Update the process affinity set using the configured mask
+            for (size_t i = 0; i < 8 * sizeof(uintptr_t); i++)
+            {
+                if (g_processAffinitySet.Contains(i) && ((configAffinityMask & ((uintptr_t)1 << i)) == 0))
+                {
+                    g_processAffinitySet.Remove(i);
+                }
+            }
+        }
+    }
+
     return &g_processAffinitySet;
 }
 
@@ -819,7 +865,6 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n
         uint16_t gn, gpn;
         CPUGroupInfo::GetGroupForProcessor((uint16_t)heap_number, &gn, &gpn);
 
-//      dprintf(3, ("using processor group %d, mask %Ix for heap %d\n", gn, (uintptr_t)1 << gpn), heap_number));
         *proc_no = GroupProcNo(gn, gpn).GetCombinedValue();
         if (GCToOSInterface::CanEnableGCNumaAware())
         {
@@ -845,7 +890,6 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n
             {
                 if (bit_number == heap_number)
                 {
-                    //dprintf (3, ("Using processor %d for heap %d", proc_number, heap_number));
                     *proc_no = GroupProcNo(GroupProcNo::NoGroup, proc_number).GetCombinedValue();
 
                     if (GCToOSInterface::CanEnableGCNumaAware())