From 9733c30b27ca90d3eeb07928df6e6e5861c203bb Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Fri, 26 Apr 2019 11:53:41 +0200 Subject: [PATCH] Fix creation of the NUMA node to heap number map The current implementation assumes that the NUMA nodes of CPUs used for GC threads form a zero based continous range. However that doesn't have to be true for cases when user selects only a subset of the available CPUs for the GC heap threads using the COMPlus_GCHeapAffinitizeMask or COMPlus_GCHeapAffinitizeRanges. The selected CPUs may belong only to a subset of NUMA nodes that don't necessarily start at node 0 or form a continuous range. This change fixes the algorithm that initializes the numa_node_to_heap_map lookup array so that it works correctly even in such cases. --- src/gc/gc.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index bcffca0..b3bb610 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -5195,23 +5195,31 @@ public: } static void init_numa_node_to_heap_map(int nheaps) - { // called right after GCHeap::Init() for each heap is finished - // when numa is not enabled, heap_no_to_numa_node[] are all filled - // with 0s during initialization, and will be treated as one node - numa_node_to_heap_map[0] = 0; - int node_index = 1; + { // Called right after GCHeap::Init() for each heap + // For each NUMA node used by the heaps, the + // numa_node_to_heap_map[numa_node] is set to the first heap number on that node and + // numa_node_to_heap_map[numa_node + 1] is set to the first heap number not on that node + + // Set the start of the heap number range for the first NUMA node + numa_node_to_heap_map[heap_no_to_numa_node[0]] = 0; for (int i=1; i < nheaps; i++) { if (heap_no_to_numa_node[i] != heap_no_to_numa_node[i-1]) - numa_node_to_heap_map[node_index++] = (uint16_t)i; + { + // Set the end of the heap number range for the previous NUMA node + numa_node_to_heap_map[heap_no_to_numa_node[i-1] + 1] = + // Set the start of the heap number range for the current NUMA node + numa_node_to_heap_map[heap_no_to_numa_node[i]] = (uint16_t)i; + } } - numa_node_to_heap_map[node_index] = (uint16_t)nheaps; //mark the end with nheaps + + // Set the end of the heap range for the last NUMA node + numa_node_to_heap_map[heap_no_to_numa_node[nheaps-1] + 1] = (uint16_t)nheaps; //mark the end with nheaps } static void get_heap_range_for_heap(int hn, int* start, int* end) - { // 1-tier/no numa case: heap_no_to_numa_node[] all zeros, - // and treated as in one node. thus: start=0, end=n_heaps + { uint16_t numa_node = heap_no_to_numa_node[hn]; *start = (int)numa_node_to_heap_map[numa_node]; *end = (int)(numa_node_to_heap_map[numa_node+1]); -- 2.7.4