From 4740ef47cf753420244111df4878cd7128380f17 Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Fri, 27 Jun 2025 15:24:42 +0530 Subject: [PATCH 3/6] 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 --- 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 #include #include +#include #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); } -- 2.49.0