perf tools: Add numa_topology object
authorJiri Olsa <jolsa@kernel.org>
Tue, 19 Feb 2019 09:58:14 +0000 (10:58 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 19 Feb 2019 15:21:06 +0000 (12:21 -0300)
Add the numa_topology object to return the list of numa nodes together
with their cpus. It will replace the numa code in header.c and will be
used from 'perf record' in the following patches.

Add the following interface functions to load numa details:

  struct numa_topology *numa_topology__new(void);
  void numa_topology__delete(struct numa_topology *tp);

And replace the current (copied) local interface, with no functional
changes.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20190219095815.15931-4-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/cputopo.c
tools/perf/util/cputopo.h
tools/perf/util/header.c

index 84470ed4e70759bf467459118513b8b168103a46..83ffca2ea9ee3b9f6152a14c8c31055f61d9e958 100644 (file)
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <sys/param.h>
+#include <inttypes.h>
 
 #include "cputopo.h"
 #include "cpumap.h"
 #include "util.h"
+#include "env.h"
 
 
 #define CORE_SIB_FMT \
@@ -142,3 +144,119 @@ out_free:
        }
        return tp;
 }
+
+static int load_numa_node(struct numa_topology_node *node, int nr)
+{
+       char str[MAXPATHLEN];
+       char field[32];
+       char *buf = NULL, *p;
+       size_t len = 0;
+       int ret = -1;
+       FILE *fp;
+       u64 mem;
+
+       node->node = (u32) nr;
+
+       sprintf(str, "/sys/devices/system/node/node%d/meminfo", nr);
+       fp = fopen(str, "r");
+       if (!fp)
+               return -1;
+
+       while (getline(&buf, &len, fp) > 0) {
+               /* skip over invalid lines */
+               if (!strchr(buf, ':'))
+                       continue;
+               if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
+                       goto err;
+               if (!strcmp(field, "MemTotal:"))
+                       node->mem_total = mem;
+               if (!strcmp(field, "MemFree:"))
+                       node->mem_free = mem;
+               if (node->mem_total && node->mem_free)
+                       break;
+       }
+
+       fclose(fp);
+       fp = NULL;
+
+       sprintf(str, "/sys/devices/system/node/node%d/cpulist", nr);
+
+       fp = fopen(str, "r");
+       if (!fp)
+               return -1;
+
+       if (getline(&buf, &len, fp) <= 0)
+               goto err;
+
+       p = strchr(buf, '\n');
+       if (p)
+               *p = '\0';
+
+       node->cpus = buf;
+       fclose(fp);
+       return 0;
+
+err:
+       free(buf);
+       if (fp)
+               fclose(fp);
+       return ret;
+}
+
+struct numa_topology *numa_topology__new(void)
+{
+       struct cpu_map *node_map = NULL;
+       struct numa_topology *tp = NULL;
+       char *buf = NULL;
+       size_t len = 0;
+       u32 nr, i;
+       FILE *fp;
+       char *c;
+
+       fp = fopen("/sys/devices/system/node/online", "r");
+       if (!fp)
+               return NULL;
+
+       if (getline(&buf, &len, fp) <= 0)
+               goto out;
+
+       c = strchr(buf, '\n');
+       if (c)
+               *c = '\0';
+
+       node_map = cpu_map__new(buf);
+       if (!node_map)
+               goto out;
+
+       nr = (u32) node_map->nr;
+
+       tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0])*nr);
+       if (!tp)
+               goto out;
+
+       tp->nr = nr;
+
+       for (i = 0; i < nr; i++) {
+               if (load_numa_node(&tp->nodes[i], node_map->map[i])) {
+                       numa_topology__delete(tp);
+                       tp = NULL;
+                       break;
+               }
+       }
+
+out:
+       free(buf);
+       fclose(fp);
+       cpu_map__put(node_map);
+       return tp;
+}
+
+void numa_topology__delete(struct numa_topology *tp)
+{
+       u32 i;
+
+       for (i = 0; i < tp->nr; i++)
+               free(tp->nodes[i].cpus);
+
+       free(tp);
+}
index 4b5f4112b6f88aa65756b7da51c75c2a6baf2ec5..47a97e71acdff059174a97582c0f7ee889195763 100644 (file)
@@ -3,6 +3,7 @@
 #define __PERF_CPUTOPO_H
 
 #include <linux/types.h>
+#include "env.h"
 
 struct cpu_topology {
        u32       core_sib;
@@ -11,7 +12,22 @@ struct cpu_topology {
        char    **thread_siblings;
 };
 
+struct numa_topology_node {
+       char            *cpus;
+       u32              node;
+       u64              mem_total;
+       u64              mem_free;
+};
+
+struct numa_topology {
+       u32                             nr;
+       struct numa_topology_node       nodes[0];
+};
+
 struct cpu_topology *cpu_topology__new(void);
 void cpu_topology__delete(struct cpu_topology *tp);
 
+struct numa_topology *numa_topology__new(void);
+void numa_topology__delete(struct numa_topology *tp);
+
 #endif /* __PERF_CPUTOPO_H */
index 80ac57e6d38f9bdf7c97f127aa5cf0a18a586fac..a2323d777dae274885ed92daae1b5d2174dc79d0 100644 (file)
@@ -639,112 +639,45 @@ static int write_total_mem(struct feat_fd *ff,
        return ret;
 }
 
-static int write_topo_node(struct feat_fd *ff, int node)
-{
-       char str[MAXPATHLEN];
-       char field[32];
-       char *buf = NULL, *p;
-       size_t len = 0;
-       FILE *fp;
-       u64 mem_total, mem_free, mem;
-       int ret = -1;
-
-       sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
-       fp = fopen(str, "r");
-       if (!fp)
-               return -1;
-
-       while (getline(&buf, &len, fp) > 0) {
-               /* skip over invalid lines */
-               if (!strchr(buf, ':'))
-                       continue;
-               if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
-                       goto done;
-               if (!strcmp(field, "MemTotal:"))
-                       mem_total = mem;
-               if (!strcmp(field, "MemFree:"))
-                       mem_free = mem;
-       }
-
-       fclose(fp);
-       fp = NULL;
-
-       ret = do_write(ff, &mem_total, sizeof(u64));
-       if (ret)
-               goto done;
-
-       ret = do_write(ff, &mem_free, sizeof(u64));
-       if (ret)
-               goto done;
-
-       ret = -1;
-       sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
-
-       fp = fopen(str, "r");
-       if (!fp)
-               goto done;
-
-       if (getline(&buf, &len, fp) <= 0)
-               goto done;
-
-       p = strchr(buf, '\n');
-       if (p)
-               *p = '\0';
-
-       ret = do_write_string(ff, buf);
-done:
-       free(buf);
-       if (fp)
-               fclose(fp);
-       return ret;
-}
-
 static int write_numa_topology(struct feat_fd *ff,
                               struct perf_evlist *evlist __maybe_unused)
 {
-       char *buf = NULL;
-       size_t len = 0;
-       FILE *fp;
-       struct cpu_map *node_map = NULL;
-       char *c;
-       u32 nr, i, j;
+       struct numa_topology *tp;
        int ret = -1;
+       u32 i;
 
-       fp = fopen("/sys/devices/system/node/online", "r");
-       if (!fp)
-               return -1;
+       tp = numa_topology__new();
+       if (!tp)
+               return -ENOMEM;
 
-       if (getline(&buf, &len, fp) <= 0)
-               goto done;
+       ret = do_write(ff, &tp->nr, sizeof(u32));
+       if (ret < 0)
+               goto err;
 
-       c = strchr(buf, '\n');
-       if (c)
-               *c = '\0';
+       for (i = 0; i < tp->nr; i++) {
+               struct numa_topology_node *n = &tp->nodes[i];
 
-       node_map = cpu_map__new(buf);
-       if (!node_map)
-               goto done;
-
-       nr = (u32)node_map->nr;
+               ret = do_write(ff, &n->node, sizeof(u32));
+               if (ret < 0)
+                       goto err;
 
-       ret = do_write(ff, &nr, sizeof(nr));
-       if (ret < 0)
-               goto done;
+               ret = do_write(ff, &n->mem_total, sizeof(u64));
+               if (ret)
+                       goto err;
 
-       for (i = 0; i < nr; i++) {
-               j = (u32)node_map->map[i];
-               ret = do_write(ff, &j, sizeof(j));
-               if (ret < 0)
-                       break;
+               ret = do_write(ff, &n->mem_free, sizeof(u64));
+               if (ret)
+                       goto err;
 
-               ret = write_topo_node(ff, j);
+               ret = do_write_string(ff, n->cpus);
                if (ret < 0)
-                       break;
+                       goto err;
        }
-done:
-       free(buf);
-       fclose(fp);
-       cpu_map__put(node_map);
+
+       ret = 0;
+
+err:
+       numa_topology__delete(tp);
        return ret;
 }