From: Jan Vorlicek Date: Tue, 2 Apr 2019 21:35:09 +0000 (+0200) Subject: Use the GCHeapAffinitizeRanges / GCHeapAffinitizeMask exclusively X-Git-Tag: accepted/tizen/unified/20190813.215958~53^2~8^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cb8b829fd3717acc2688025341f822e4097cf5c5;p=platform%2Fupstream%2Fcoreclr.git Use the GCHeapAffinitizeRanges / GCHeapAffinitizeMask exclusively The GCHeapAffinitizeRanges are now used only when CPU groups are enabled and the GCHeapAffinitizeMask when CPU groups are disabled. --- diff --git a/src/gc/env/gcenv.os.h b/src/gc/env/gcenv.os.h index 323e193..b98037b 100644 --- a/src/gc/env/gcenv.os.h +++ b/src/gc/env/gcenv.os.h @@ -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__ diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index 910ff07..704cf26 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -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(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)) diff --git a/src/gc/gcconfig.cpp b/src/gc/gcconfig.cpp index 1e9dbe1..b151511 100644 --- a/src/gc/gcconfig.cpp +++ b/src/gc/gcconfig.cpp @@ -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; diff --git a/src/gc/gcconfig.h b/src/gc/gcconfig.h index f292a12..b2fea16 100644 --- a/src/gc/gcconfig.h +++ b/src/gc/gcconfig.h @@ -156,6 +156,6 @@ static void Initialize(); }; -bool ParseGCHeapAffinitySettings(AffinitySet* config_affinity_set); +bool ParseGCHeapAffinitizeRanges(AffinitySet* config_affinity_set); #endif // __GCCONFIG_H__ diff --git a/src/gc/unix/gcenv.unix.cpp b/src/gc/unix/gcenv.unix.cpp index 140c546..4719dc9 100644 --- a/src/gc/unix/gcenv.unix.cpp +++ b/src/gc/unix/gcenv.unix.cpp @@ -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; } diff --git a/src/gc/windows/gcenv.windows.cpp b/src/gc/windows/gcenv.windows.cpp index 738fdec..5d323dd 100644 --- a/src/gc/windows/gcenv.windows.cpp +++ b/src/gc/windows/gcenv.windows.cpp @@ -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()) diff --git a/src/vm/gcenv.os.cpp b/src/vm/gcenv.os.cpp index fcf716f..243b897 100644 --- a/src/vm/gcenv.os.cpp +++ b/src/vm/gcenv.os.cpp @@ -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())