File 03-Resolve-max-count-of-nodes-at-runtime.patch of Package numatop

From 4740ef47cf753420244111df4878cd7128380f17 Mon Sep 17 00:00:00 2001
From: Sandipan Das <sandipan.das@amd.com>
Date: Fri, 27 Jun 2025 15:24:42 +0530
Subject: [PATCH] common: Resolve max count of nodes at runtime

Replace statically defined NNODES_MAX with a variable which is set at
runtime. Use libnuma helpers to determine the OS-defined limits for the
maximum possible number of NUMA nodes in the the system.

Signed-off-by: Sandipan Das <sandipan.das@amd.com>
---
 common/include/os/node.h |  2 +-
 common/include/types.h   |  5 ++--
 common/numatop.c         |  2 +-
 common/os/node.c         | 52 +++++++++++++++++++++++++++-------------
 common/os/os_perf.c      |  4 ++--
 common/os/os_util.c      |  2 +-
 common/win.c             | 15 ++++++++----
 7 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/common/include/os/node.h b/common/include/os/node.h
index da1ba7c..2c21556 100644
--- a/common/include/os/node.h
+++ b/common/include/os/node.h
@@ -101,7 +101,7 @@ typedef struct _node {
 
 typedef struct _node_group {
 	pthread_mutex_t mutex;
-	node_t nodes[NNODES_MAX];
+	node_t *nodes;
 	int nnodes;
 	int cpuid_max;
 	int intval_ms;
diff --git a/common/include/types.h b/common/include/types.h
index 05b411a..e688225 100644
--- a/common/include/types.h
+++ b/common/include/types.h
@@ -115,13 +115,14 @@ typedef enum {
 
 #define UI_COUNT_NUM		5
 
-#define	NNODES_MAX		64
 #define NCPUS_NODE_MAX		256
-#define	NCPUS_MAX		(NNODES_MAX * NCPUS_NODE_MAX)
+#define	NCPUS_MAX		(nnodes_max * NCPUS_NODE_MAX)
 #define NPROCS_NAX		4096
 #define	LL_THRESH		128
 #define LL_PERIOD		1000
 
+extern int nnodes_max;
+
 typedef struct _count_value {
 	uint64_t counts[PERF_COUNT_NUM];
 } count_value_t;
diff --git a/common/numatop.c b/common/numatop.c
index 122c187..c5c0580 100644
--- a/common/numatop.c
+++ b/common/numatop.c
@@ -236,7 +236,7 @@ main(int argc, char *argv[])
 	if (node_group_init() != 0) {
 		stderr_print("The node/cpu number is out of range, \n"
 		    "numatop supports up to %d nodes and %d CPUs\n",
-		    NNODES_MAX, NCPUS_MAX);
+		    nnodes_max, NCPUS_MAX);
 		goto L_EXIT5;
 	}
 
diff --git a/common/os/node.c b/common/os/node.c
index ab0c90d..c2ca7a7 100644
--- a/common/os/node.c
+++ b/common/os/node.c
@@ -36,6 +36,7 @@
 #include <pthread.h>
 #include <string.h>
 #include <assert.h>
+#include <numa.h>
 #include "../include/types.h"
 #include "../include/util.h"
 #include "../include/ui_perf_map.h"
@@ -46,6 +47,8 @@
 static node_group_t s_node_group;
 int g_ncpus;
 
+int nnodes_max;
+
 static void
 node_init(node_t *node, int nid, boolean_t hotadd)
 {
@@ -79,13 +82,22 @@ node_group_init(void)
 	int i;
 	node_t *node;
 
+	if (numa_available() < 0)
+		return (-1);
+
+	nnodes_max = numa_num_possible_nodes();
+
 	(void) memset(&s_node_group, 0, sizeof (node_group_t));
 	if (pthread_mutex_init(&s_node_group.mutex, NULL) != 0) {
 		return (-1);
 	}
 
+	if ((s_node_group.nodes = zalloc(nnodes_max  * sizeof(node_t))) == NULL) {
+		return (-1);
+	}
+
 	s_node_group.inited = B_TRUE;
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		node_init(node, INVALID_NID, B_FALSE);
 	}
@@ -102,12 +114,13 @@ node_group_reset(void)
 	node_t *node;
 	int i;
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		node_fini(node);
 	}
 
 	s_node_group.nnodes = 0;
+	free(s_node_group.nodes);
 }
 
 /*
@@ -161,7 +174,7 @@ cpu_refresh(boolean_t init)
 	int cpu_arr[NCPUS_NODE_MAX];
 	node_t *node;
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	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)) {
@@ -199,7 +212,7 @@ meminfo_refresh(void)
 	int i;
 	node_t *node;
 	
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (NODE_VALID(node)) {
 			if (!os_sysfs_meminfo(node->nid, &node->meminfo)) {
@@ -220,19 +233,23 @@ meminfo_refresh(void)
 int
 node_group_refresh(boolean_t init)
 {
-	int node_arr[NNODES_MAX];
-	int num, i, j, ret = -1;
+	int *node_arr, num, i, j, ret = -1;
 	node_t *node;
 
 	node_group_lock();
-	if (!os_sysfs_node_enum(node_arr, NNODES_MAX, &num)) {
+
+	if ((node_arr = zalloc(nnodes_max * sizeof(int))) == NULL) {
+		goto L_EXIT;
+	}
+
+	if (!os_sysfs_node_enum(node_arr, nnodes_max, &num)) {
 		goto L_EXIT;
 	}
-	if (num < 0 || num > NNODES_MAX) {
+	if (num < 0 || num > nnodes_max) {
 		goto L_EXIT;
 	}
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (NODE_VALID(node)) {
 			if ((j = nid_find(node->nid, node_arr, num)) == -1) {
@@ -244,7 +261,7 @@ node_group_refresh(boolean_t init)
 		}
 	}
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (!NODE_VALID(node)) {
 			if ((j = nid_find(i, node_arr, num)) >= 0) {
@@ -272,6 +289,7 @@ node_group_refresh(boolean_t init)
 	ret = 0;
 
 L_EXIT:
+	free(node_arr);
 	node_group_unlock();
 	return (ret);
 }
@@ -313,7 +331,7 @@ node_by_cpu(int cpuid)
 		return (NULL);
 	}
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (!NODE_VALID(node)) {
 			continue;
@@ -386,7 +404,7 @@ node_cpu_traverse(pfn_perf_cpu_op_t func, void *arg, boolean_t err_ret,
 	perf_cpu_t *cpu;
 	int i, j, ret;
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (!NODE_VALID(node)) {
 			continue;
@@ -461,7 +479,7 @@ node_countval_sum(count_value_t *countval_arr, int nid,
 		return (countval_sum(countval_arr, nid, ui_count_id));
 	}
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		value += countval_sum(countval_arr, i, ui_count_id);
 	}
 
@@ -486,7 +504,7 @@ node_profiling_clear(void)
 	node_t *node;
 	int i;
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		(void) memset(&node->countval, 0, sizeof (count_value_t));
 	}	
@@ -498,7 +516,7 @@ node_valid_get(int node_idx)
 	int i, nvalid = 0;
 	node_t *node;
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (NODE_VALID(node)) {
 			if (node_idx == nvalid) {
@@ -537,7 +555,7 @@ node_qpi_init(void)
 
 	node_group_lock();
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (NODE_VALID(node) && (qpi_num > 0)) {
 			memcpy(node->qpi.qpi_info, qpi_tmp,
@@ -566,7 +584,7 @@ node_imc_init(void)
 
 	node_group_lock();
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (NODE_VALID(node) && (imc_num > 0)) {
 			memcpy(node->imc.imc_info, imc_tmp,
diff --git a/common/os/os_perf.c b/common/os/os_perf.c
index d8d634f..9ea93ea 100644
--- a/common/os/os_perf.c
+++ b/common/os/os_perf.c
@@ -1025,7 +1025,7 @@ uncore_stop_all(void)
 	node_t *node;
 	int i;
 
-	for (i = 0; i < NNODES_MAX; i++) {
+	for (i = 0; i < nnodes_max; i++) {
 		node = node_get(i);
 		if (NODE_VALID(node)) {
 			if (node->qpi.qpi_num > 0)
@@ -1455,7 +1455,7 @@ int os_uncore_stop(perf_ctl_t *ctl __attribute__((unused)),
 				pf_uncoreimc_free(node);
 		}
 	} else {
-		for (i = 0; i < NNODES_MAX; i++) {
+		for (i = 0; i < nnodes_max; i++) {
 			node = node_get(i);
 			if (NODE_VALID(node)) {
 				if (node->qpi.qpi_num > 0)
diff --git a/common/os/os_util.c b/common/os/os_util.c
index 0b862c2..ec3f6e5 100644
--- a/common/os/os_util.c
+++ b/common/os/os_util.c
@@ -863,7 +863,7 @@ static uint64_t cmt_field_value(char *dir, const char *field, int nid)
 	int i;
 
 	if (nid == -1) {
-		for (i = 0; i < NNODES_MAX; i++) {
+		for (i = 0; i < nnodes_max; i++) {
 			if (cmt_task_node_value(dir, i, field,
 				&tmp) == 0)
 				val += tmp;
diff --git a/common/win.c b/common/win.c
index 03d096d..dad13d1 100644
--- a/common/win.c
+++ b/common/win.c
@@ -2714,7 +2714,7 @@ accdst_data_show(track_proc_t *proc, dyn_accdst_t *dyn, boolean_t *note_out)
 	void **addr_arr = NULL;
 	int *lat_arr = NULL;
 	int addr_num, i, nnodes, naccess_total = 0;
-	map_nodedst_t nodedst_arr[NNODES_MAX];
+	map_nodedst_t *nodedst_arr;
 	accdst_line_t *lines;
 	char content[WIN_LINECHAR_MAX], intval_buf[16];
 	boolean_t ret = B_FALSE;
@@ -2728,14 +2728,19 @@ accdst_data_show(track_proc_t *proc, dyn_accdst_t *dyn, boolean_t *note_out)
 		return (B_FALSE);
 	}
 
+	nodedst_arr = (map_nodedst_t *) malloc(sizeof (map_nodedst_t) * nnodes_max);
+	if (!nodedst_arr) {
+		goto L_EXIT;
+	}
+
 	if (llrec2addr(proc, lwp, &addr_arr, &lat_arr, &addr_num) != 0) {
 		goto L_EXIT;
 	}
 
-	(void) memset(nodedst_arr, 0, sizeof (map_nodedst_t) * NNODES_MAX);
+	(void) memset(nodedst_arr, 0, sizeof (map_nodedst_t) * nnodes_max);
 	if (addr_num > 0) {
 		if (map_addr2nodedst(proc->pid, addr_arr, lat_arr, addr_num,
-		    nodedst_arr, NNODES_MAX, &naccess_total) != 0) {
+		    nodedst_arr, nnodes_max, &naccess_total) != 0) {
 			goto L_EXIT;
 		}
 	}
@@ -2784,7 +2789,7 @@ accdst_data_show(track_proc_t *proc, dyn_accdst_t *dyn, boolean_t *note_out)
 	 * Save the per-node data with metrics in scrolling buffer.
 	 */
 	for (i = 0; i < nnodes; i++) {
-		accdst_data_save(nodedst_arr, NNODES_MAX, naccess_total, i,
+		accdst_data_save(nodedst_arr, nnodes_max, naccess_total, i,
 		    &lines[i]);
 	}
 
@@ -2799,6 +2804,8 @@ accdst_data_show(track_proc_t *proc, dyn_accdst_t *dyn, boolean_t *note_out)
 	reg_refresh_nout(r);
 
 L_EXIT:
+	free(nodedst_arr);
+
 	if (lwp != NULL) {
 		lwp_refcount_dec(lwp);
 	}
openSUSE Build Service is sponsored by