aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2019-02-19 04:58:14 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-02-19 10:21:06 -0500
commit48e6c5acd36873ff022cd97de866bfd0a36a3b99 (patch)
tree5c3dd2981a49b4b1b67a1813125a7cb1b35660a6
parent5135d5efcbb439c2acb20d6197dd57af3a456e76 (diff)
perf tools: Add numa_topology object
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>
-rw-r--r--tools/perf/util/cputopo.c118
-rw-r--r--tools/perf/util/cputopo.h16
-rw-r--r--tools/perf/util/header.c119
3 files changed, 160 insertions, 93 deletions
diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c
index 84470ed4e707..83ffca2ea9ee 100644
--- a/tools/perf/util/cputopo.c
+++ b/tools/perf/util/cputopo.c
@@ -1,9 +1,11 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <sys/param.h> 2#include <sys/param.h>
3#include <inttypes.h>
3 4
4#include "cputopo.h" 5#include "cputopo.h"
5#include "cpumap.h" 6#include "cpumap.h"
6#include "util.h" 7#include "util.h"
8#include "env.h"
7 9
8 10
9#define CORE_SIB_FMT \ 11#define CORE_SIB_FMT \
@@ -142,3 +144,119 @@ out_free:
142 } 144 }
143 return tp; 145 return tp;
144} 146}
147
148static int load_numa_node(struct numa_topology_node *node, int nr)
149{
150 char str[MAXPATHLEN];
151 char field[32];
152 char *buf = NULL, *p;
153 size_t len = 0;
154 int ret = -1;
155 FILE *fp;
156 u64 mem;
157
158 node->node = (u32) nr;
159
160 sprintf(str, "/sys/devices/system/node/node%d/meminfo", nr);
161 fp = fopen(str, "r");
162 if (!fp)
163 return -1;
164
165 while (getline(&buf, &len, fp) > 0) {
166 /* skip over invalid lines */
167 if (!strchr(buf, ':'))
168 continue;
169 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
170 goto err;
171 if (!strcmp(field, "MemTotal:"))
172 node->mem_total = mem;
173 if (!strcmp(field, "MemFree:"))
174 node->mem_free = mem;
175 if (node->mem_total && node->mem_free)
176 break;
177 }
178
179 fclose(fp);
180 fp = NULL;
181
182 sprintf(str, "/sys/devices/system/node/node%d/cpulist", nr);
183
184 fp = fopen(str, "r");
185 if (!fp)
186 return -1;
187
188 if (getline(&buf, &len, fp) <= 0)
189 goto err;
190
191 p = strchr(buf, '\n');
192 if (p)
193 *p = '\0';
194
195 node->cpus = buf;
196 fclose(fp);
197 return 0;
198
199err:
200 free(buf);
201 if (fp)
202 fclose(fp);
203 return ret;
204}
205
206struct numa_topology *numa_topology__new(void)
207{
208 struct cpu_map *node_map = NULL;
209 struct numa_topology *tp = NULL;
210 char *buf = NULL;
211 size_t len = 0;
212 u32 nr, i;
213 FILE *fp;
214 char *c;
215
216 fp = fopen("/sys/devices/system/node/online", "r");
217 if (!fp)
218 return NULL;
219
220 if (getline(&buf, &len, fp) <= 0)
221 goto out;
222
223 c = strchr(buf, '\n');
224 if (c)
225 *c = '\0';
226
227 node_map = cpu_map__new(buf);
228 if (!node_map)
229 goto out;
230
231 nr = (u32) node_map->nr;
232
233 tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0])*nr);
234 if (!tp)
235 goto out;
236
237 tp->nr = nr;
238
239 for (i = 0; i < nr; i++) {
240 if (load_numa_node(&tp->nodes[i], node_map->map[i])) {
241 numa_topology__delete(tp);
242 tp = NULL;
243 break;
244 }
245 }
246
247out:
248 free(buf);
249 fclose(fp);
250 cpu_map__put(node_map);
251 return tp;
252}
253
254void numa_topology__delete(struct numa_topology *tp)
255{
256 u32 i;
257
258 for (i = 0; i < tp->nr; i++)
259 free(tp->nodes[i].cpus);
260
261 free(tp);
262}
diff --git a/tools/perf/util/cputopo.h b/tools/perf/util/cputopo.h
index 4b5f4112b6f8..47a97e71acdf 100644
--- a/tools/perf/util/cputopo.h
+++ b/tools/perf/util/cputopo.h
@@ -3,6 +3,7 @@
3#define __PERF_CPUTOPO_H 3#define __PERF_CPUTOPO_H
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include "env.h"
6 7
7struct cpu_topology { 8struct cpu_topology {
8 u32 core_sib; 9 u32 core_sib;
@@ -11,7 +12,22 @@ struct cpu_topology {
11 char **thread_siblings; 12 char **thread_siblings;
12}; 13};
13 14
15struct numa_topology_node {
16 char *cpus;
17 u32 node;
18 u64 mem_total;
19 u64 mem_free;
20};
21
22struct numa_topology {
23 u32 nr;
24 struct numa_topology_node nodes[0];
25};
26
14struct cpu_topology *cpu_topology__new(void); 27struct cpu_topology *cpu_topology__new(void);
15void cpu_topology__delete(struct cpu_topology *tp); 28void cpu_topology__delete(struct cpu_topology *tp);
16 29
30struct numa_topology *numa_topology__new(void);
31void numa_topology__delete(struct numa_topology *tp);
32
17#endif /* __PERF_CPUTOPO_H */ 33#endif /* __PERF_CPUTOPO_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 80ac57e6d38f..a2323d777dae 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -639,112 +639,45 @@ static int write_total_mem(struct feat_fd *ff,
639 return ret; 639 return ret;
640} 640}
641 641
642static int write_topo_node(struct feat_fd *ff, int node)
643{
644 char str[MAXPATHLEN];
645 char field[32];
646 char *buf = NULL, *p;
647 size_t len = 0;
648 FILE *fp;
649 u64 mem_total, mem_free, mem;
650 int ret = -1;
651
652 sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
653 fp = fopen(str, "r");
654 if (!fp)
655 return -1;
656
657 while (getline(&buf, &len, fp) > 0) {
658 /* skip over invalid lines */
659 if (!strchr(buf, ':'))
660 continue;
661 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
662 goto done;
663 if (!strcmp(field, "MemTotal:"))
664 mem_total = mem;
665 if (!strcmp(field, "MemFree:"))
666 mem_free = mem;
667 }
668
669 fclose(fp);
670 fp = NULL;
671
672 ret = do_write(ff, &mem_total, sizeof(u64));
673 if (ret)
674 goto done;
675
676 ret = do_write(ff, &mem_free, sizeof(u64));
677 if (ret)
678 goto done;
679
680 ret = -1;
681 sprintf(str, "/sys/devices/system/node/node%d/cpulist", node);
682
683 fp = fopen(str, "r");
684 if (!fp)
685 goto done;
686
687 if (getline(&buf, &len, fp) <= 0)
688 goto done;
689
690 p = strchr(buf, '\n');
691 if (p)
692 *p = '\0';
693
694 ret = do_write_string(ff, buf);
695done:
696 free(buf);
697 if (fp)
698 fclose(fp);
699 return ret;
700}
701
702static int write_numa_topology(struct feat_fd *ff, 642static int write_numa_topology(struct feat_fd *ff,
703 struct perf_evlist *evlist __maybe_unused) 643 struct perf_evlist *evlist __maybe_unused)
704{ 644{
705 char *buf = NULL; 645 struct numa_topology *tp;
706 size_t len = 0;
707 FILE *fp;
708 struct cpu_map *node_map = NULL;
709 char *c;
710 u32 nr, i, j;
711 int ret = -1; 646 int ret = -1;
647 u32 i;
712 648
713 fp = fopen("/sys/devices/system/node/online", "r"); 649 tp = numa_topology__new();
714 if (!fp) 650 if (!tp)
715 return -1; 651 return -ENOMEM;
716 652
717 if (getline(&buf, &len, fp) <= 0) 653 ret = do_write(ff, &tp->nr, sizeof(u32));
718 goto done; 654 if (ret < 0)
655 goto err;
719 656
720 c = strchr(buf, '\n'); 657 for (i = 0; i < tp->nr; i++) {
721 if (c) 658 struct numa_topology_node *n = &tp->nodes[i];
722 *c = '\0';
723 659
724 node_map = cpu_map__new(buf); 660 ret = do_write(ff, &n->node, sizeof(u32));
725 if (!node_map) 661 if (ret < 0)
726 goto done; 662 goto err;
727
728 nr = (u32)node_map->nr;
729 663
730 ret = do_write(ff, &nr, sizeof(nr)); 664 ret = do_write(ff, &n->mem_total, sizeof(u64));
731 if (ret < 0) 665 if (ret)
732 goto done; 666 goto err;
733 667
734 for (i = 0; i < nr; i++) { 668 ret = do_write(ff, &n->mem_free, sizeof(u64));
735 j = (u32)node_map->map[i]; 669 if (ret)
736 ret = do_write(ff, &j, sizeof(j)); 670 goto err;
737 if (ret < 0)
738 break;
739 671
740 ret = write_topo_node(ff, j); 672 ret = do_write_string(ff, n->cpus);
741 if (ret < 0) 673 if (ret < 0)
742 break; 674 goto err;
743 } 675 }
744done: 676
745 free(buf); 677 ret = 0;
746 fclose(fp); 678
747 cpu_map__put(node_map); 679err:
680 numa_topology__delete(tp);
748 return ret; 681 return ret;
749} 682}
750 683