File 05-Resolve-max-count-of-CPUs-per-node-at-runtime.patch of Package numatop

From 00128bb30fb1b88bf2c7421b2a5a759dcffacb32 Mon Sep 17 00:00:00 2001
From: Sandipan Das <sandipan.das@amd.com>
Date: Mon, 30 Jun 2025 18:42:33 +0530
Subject: [PATCH] common: Resolve max count of CPUs per node at runtime

Replace statically defined NCPUS_NODE_MAX with the previously introduced
ncpus_max. Technically, ncpus_max denotes the maximum possible number of
CPUs in a system but it can also serve as the maximum possible number of
CPUs per NUMA node because of the following reasons.
 * CPUs may not be uniformly distributed across NUMA nodes.
 * Some NUMA nodes may not have any CPUs associated with them.

Signed-off-by: Sandipan Das <sandipan.das@amd.com>
---
 common/include/os/node.h |  2 +-
 common/include/types.h   |  1 -
 common/os/node.c         | 72 ++++++++++++++++++++++++++++------------
 common/os/os_win.c       |  2 +-
 4 files changed, 53 insertions(+), 24 deletions(-)

diff --git a/common/include/os/node.h b/common/include/os/node.h
index 2c21556..0b3c362 100644
--- a/common/include/os/node.h
+++ b/common/include/os/node.h
@@ -90,7 +90,7 @@ typedef struct _node_imc {
 typedef struct _node {
 	int nid;
 	int ncpus;
-	perf_cpu_t cpus[NCPUS_NODE_MAX];
+	perf_cpu_t *cpus;
 	count_value_t countval;
 	node_meminfo_t meminfo;
 	node_qpi_t qpi;
diff --git a/common/include/types.h b/common/include/types.h
index eb64fb1..1d1545d 100644
--- a/common/include/types.h
+++ b/common/include/types.h
@@ -115,7 +115,6 @@ typedef enum {
 
 #define UI_COUNT_NUM		5
 
-#define NCPUS_NODE_MAX		256
 #define NPROCS_NAX		4096
 #define	LL_THRESH		128
 #define LL_PERIOD		1000
diff --git a/common/os/node.c b/common/os/node.c
index f79bcdf..cb8c38a 100644
--- a/common/os/node.c
+++ b/common/os/node.c
@@ -50,20 +50,34 @@ int g_ncpus;
 int nnodes_max;
 int ncpus_max;
 
-static void
+static int
 node_init(node_t *node, int nid, boolean_t hotadd)
 {
 	memset(node, 0, sizeof (node_t));
-	os_perf_cpuarr_init(node->cpus, NCPUS_NODE_MAX, hotadd);
 	node->nid = nid;
 	node->hotadd = hotadd;
+	if (!NODE_VALID(node)) {
+		return 0;
+	}
+
+	if ((node->cpus = zalloc(ncpus_max * sizeof(perf_cpu_t))) == NULL) {
+		return (-1);
+	}
+
+	os_perf_cpuarr_init(node->cpus, ncpus_max, hotadd);
+	return 0;
 }
 
 static void
 node_fini(node_t *node)
 {
-	os_perf_cpuarr_fini(node->cpus, NCPUS_NODE_MAX, B_FALSE);
+	if (!NODE_VALID(node)) {
+		return;
+	}
+
+	os_perf_cpuarr_fini(node->cpus, ncpus_max, B_FALSE);
 	node->ncpus = 0;
+	free(node->cpus);
 	node->nid = INVALID_NID;
 }
 
@@ -71,7 +85,7 @@ static void
 node_hotremove(node_t *node)
 {
 	node->hotremove = B_TRUE;
-	os_perf_cpuarr_fini(node->cpus, NCPUS_NODE_MAX, B_TRUE);
+	os_perf_cpuarr_fini(node->cpus, ncpus_max, B_TRUE);
 }
 
 /*
@@ -101,10 +115,20 @@ node_group_init(void)
 	s_node_group.inited = B_TRUE;
 	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
-		node_init(node, INVALID_NID, B_FALSE);
+		if (node_init(node, INVALID_NID, B_FALSE)) {
+			goto L_EXIT;
+		}
 	}
 
 	return (node_group_refresh(B_TRUE));
+
+L_EXIT:
+	for (i = i - 1; i >= 0; i--) {
+		node = node_get(i);
+		node_fini(node);
+	}
+
+	return (-1);
 }
 
 /*
@@ -172,23 +196,27 @@ cpuid_max_get(int *cpu_arr, int num)
 static int
 cpu_refresh(boolean_t init)
 {
-	int i, j, num, cpuid_max = -1;
-	int cpu_arr[NCPUS_NODE_MAX];
+	int i, j, num, cpuid_max = -1, ret = -1;
+	int *cpu_arr;
 	node_t *node;
 
+	if ((cpu_arr = zalloc(ncpus_max * sizeof(int))) == NULL) {
+		return (-1);
+	}
+
 	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (NODE_VALID(node)) {
-			if (!os_sysfs_cpu_enum(node->nid, cpu_arr, NCPUS_NODE_MAX, &num)) {
-				return (-1);
+			if (!os_sysfs_cpu_enum(node->nid, cpu_arr, ncpus_max, &num)) {
+				goto L_EXIT;
 			}
-			if (num < 0 || num > NCPUS_NODE_MAX) {
-				return (-1);
+			if (num < 0 || num > ncpus_max) {
+				goto L_EXIT;
 			}
 
-			if (os_perf_cpuarr_refresh(node->cpus, NCPUS_NODE_MAX, cpu_arr,
+			if (os_perf_cpuarr_refresh(node->cpus, ncpus_max, cpu_arr,
 				num, init) != 0) {
-				return (-1);
+				goto L_EXIT;
 			}
 
 			node->ncpus = num;
@@ -205,7 +233,11 @@ cpu_refresh(boolean_t init)
 
 	/* Refresh the number of online CPUs */
 	g_ncpus = os_sysfs_online_ncpus();
-	return (0);
+	ret = 0;
+
+L_EXIT:
+	free(cpu_arr);
+	return (ret);
 }
 
 static int
@@ -268,10 +300,8 @@ node_group_refresh(boolean_t init)
 		if (!NODE_VALID(node)) {
 			if ((j = nid_find(i, node_arr, num)) >= 0) {
 				ASSERT(node_arr[j] == i);
-				if (init) {
-					node_init(node, i, B_FALSE);
-				} else {				
-					node_init(node, i, B_TRUE);
+				if (node_init(node, i, init ? B_FALSE : B_TRUE)) {
+					goto L_EXIT;
 				}
 
 				s_node_group.nnodes++;
@@ -339,7 +369,7 @@ node_by_cpu(int cpuid)
 			continue;
 		}
 
-		for (j = 0; j < NCPUS_NODE_MAX; j++) {
+		for (j = 0; j < ncpus_max; j++) {
 			if (cpuid == node->cpus[j].cpuid) {
 				return (node);
 			}
@@ -412,7 +442,7 @@ node_cpu_traverse(pfn_perf_cpu_op_t func, void *arg, boolean_t err_ret,
 			continue;
 		}
 
-		for (j = 0; j < NCPUS_NODE_MAX; j++) {
+		for (j = 0; j < ncpus_max; j++) {
 			cpu = &node->cpus[j];
 			if (cpu->hotremove) {
 				pf_resource_free(cpu);
@@ -455,7 +485,7 @@ countval_sum(count_value_t *countval_arr, int nid,
 		return (0);
 	}
 
-	for (i = 0; i < NCPUS_NODE_MAX; i++) {
+	for (i = 0; i < ncpus_max; i++) {
 		if (num >= node->ncpus) {
 			break;
 		}
diff --git a/common/os/os_win.c b/common/os/os_win.c
index 9aaefae..bd34388 100644
--- a/common/os/os_win.c
+++ b/common/os/os_win.c
@@ -152,7 +152,7 @@ node_cpu_string(node_t *node, char *s1, int size)
 	}
 
 	j = 0;
-	for (i = 0; (i < NCPUS_NODE_MAX) && (j < ncpus); i++) {
+	for (i = 0; (i < ncpus_max) && (j < ncpus); i++) {
 		if ((cpus[i].cpuid != INVALID_CPUID) && (!cpus[i].hotremove)) {
 			cpuid_arr[j++] = cpus[i].cpuid;
 		}
openSUSE Build Service is sponsored by