From: Gena Tertychnyi <[email protected]>

Fix specific to Windows NUMA machines with more than 64 cores per node
(e.g. 2 NUMAs with 128 cores each):

- NumaNode.GroupMasks[] array is used instead of NumaNode.GroupMask.
- RelationAll is used instead of RelationNumaNode when calling
GetLogicalProcessorInformationEx because RelationAll returns the full
multi-group NUMA affinity as RelationNumaNode returns only the NUMA
node's primary group.

Signed-off-by: Gena Tertychnyi <[email protected]>
Signed-off-by: Andre Muezerie <[email protected]>
---
 lib/eal/windows/eal_lcore.c | 68 +++++++++++++++++++++++++++----------
 1 file changed, 51 insertions(+), 17 deletions(-)

diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c
index a498044620..d2a2c2d091 100644
--- a/lib/eal/windows/eal_lcore.c
+++ b/lib/eal/windows/eal_lcore.c
@@ -17,13 +17,27 @@
 /** Number of logical processors (cores) in a processor group (32 or 64). */
 #define EAL_PROCESSOR_GROUP_SIZE (sizeof(KAFFINITY) * CHAR_BIT)
 
+/*
+ * NUMA_NODE_RELATIONSHIP layout differs:
+ *  - MSVC + modern SDK: GroupCount + GroupMasks[]
+ *  - MinGW-w64: only GroupMask (MinGW headers lag behind Windows SDK ABI 
changes)
+ */
+#ifdef RTE_TOOLCHAIN_GCC
+#define EAL_NUMA_GROUP_COUNT(numa) (RTE_SET_USED(numa), 1)
+#define EAL_NUMA_GROUP_MASKS(numa) (&((numa).GroupMask))
+#else
+#define EAL_NUMA_GROUP_COUNT(numa) ((numa).GroupCount)
+#define EAL_NUMA_GROUP_MASKS(numa) ((numa).GroupMasks)
+#endif
+
 struct lcore_map {
-       uint8_t socket_id;
-       uint8_t core_id;
+       unsigned int socket_id;
+       unsigned int core_id;
 };
 
 struct socket_map {
        uint16_t node_id;
+       unsigned int lcore_count;
 };
 
 struct cpu_map {
@@ -112,11 +126,15 @@ static bool
 eal_create_lcore_map(const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
 {
        const unsigned int node_id = info->NumaNode.NodeNumber;
-       const GROUP_AFFINITY *cores = &info->NumaNode.GroupMask;
+       const GROUP_AFFINITY *group_masks = 
EAL_NUMA_GROUP_MASKS(info->NumaNode);
        struct lcore_map *lcore;
        unsigned int socket_id;
+       unsigned int group_count;
+       unsigned int group_no;
        unsigned int i;
 
+       group_count = EAL_NUMA_GROUP_COUNT(info->NumaNode);
+
        /*
         * NUMA node may be reported multiple times if it includes
         * cores from different processor groups, e. g. 80 cores
@@ -132,20 +150,33 @@ eal_create_lcore_map(const 
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info)
                        return true;
 
                cpu_map.sockets[socket_id].node_id = node_id;
+               cpu_map.sockets[socket_id].lcore_count = 0;
                cpu_map.socket_count++;
        }
 
-       for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
-               if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
-                       continue;
+       /* Old Windows versions report NUMA nodes with GroupCount == 0 */
+       if (group_count == 0) {
+               group_count = 1;
+               group_masks = &info->NumaNode.GroupMask;
+       }
 
-               if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
-                       return true;
+       for (group_no = 0; group_no < group_count; group_no++) {
+               const GROUP_AFFINITY *cores = &group_masks[group_no];
+               for (i = 0; i < EAL_PROCESSOR_GROUP_SIZE; i++) {
+                       if ((cores->Mask & ((KAFFINITY)1 << i)) == 0)
+                               continue;
+
+                       if (cpu_map.lcore_count == RTE_DIM(cpu_map.lcores))
+                               return true;
 
-               lcore = &cpu_map.lcores[cpu_map.lcore_count];
-               lcore->socket_id = socket_id;
-               lcore->core_id = cores->Group * EAL_PROCESSOR_GROUP_SIZE + i;
-               cpu_map.lcore_count++;
+                       lcore = &cpu_map.lcores[cpu_map.lcore_count];
+                       lcore->socket_id = socket_id;
+
+                       /* core_id within the socket */
+                       lcore->core_id = cpu_map.sockets[socket_id].lcore_count;
+                       cpu_map.sockets[socket_id].lcore_count++;
+                       cpu_map.lcore_count++;
+               }
        }
        return false;
 }
@@ -160,8 +191,9 @@ eal_create_cpu_map(void)
 
        infos = NULL;
        infos_size = 0;
+       /* RelationAll is needed to get full multi-group NUMA affinity */
        if (!GetLogicalProcessorInformationEx(
-                       RelationNumaNode, NULL, &infos_size)) {
+                       RelationAll, NULL, &infos_size)) {
                DWORD error = GetLastError();
                if (error != ERROR_INSUFFICIENT_BUFFER) {
                        log_early("Cannot get NUMA node info size, error %lu\n",
@@ -181,7 +213,7 @@ eal_create_cpu_map(void)
        }
 
        if (!GetLogicalProcessorInformationEx(
-                       RelationNumaNode, infos, &infos_size)) {
+                       RelationAll, infos, &infos_size)) {
                log_early("Cannot get NUMA node information, error %lu\n",
                        GetLastError());
                rte_errno = EINVAL;
@@ -191,9 +223,11 @@ eal_create_cpu_map(void)
 
        info = infos;
        while ((uint8_t *)info - (uint8_t *)infos < infos_size) {
-               if (eal_create_lcore_map(info)) {
-                       full = true;
-                       break;
+               if (info->Relationship == RelationNumaNode) {
+                       if (eal_create_lcore_map(info)) {
+                               full = true;
+                               break;
+                       }
                }
 
                info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(
-- 
2.53.0.vfs.0.7

Reply via email to