aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/lib
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2019-07-21 07:24:30 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-07-29 17:34:45 -0400
commit9c3516d1b850ea938b074df33e4c86d721c77720 (patch)
treecb937368ee6d8048f465bcbe27d62709f871212c /tools/perf/lib
parent1fc632cef4ea137bc45fd0fc4cb902e374064163 (diff)
libperf: Add perf_cpu_map__new()/perf_cpu_map__read() functions
Moving the following functions from tools/perf: cpu_map__new() cpu_map__read() to libperf with the following names: perf_cpu_map__new() perf_cpu_map__read() Committer notes: Fixed up this one: tools/perf/arch/arm/util/cs-etm.c Signed-off-by: Jiri Olsa <jolsa@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Alexey Budankov <alexey.budankov@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20190721112506.12306-44-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/lib')
-rw-r--r--tools/perf/lib/cpumap.c184
-rw-r--r--tools/perf/lib/include/internal/cpumap.h4
-rw-r--r--tools/perf/lib/include/perf/cpumap.h3
-rw-r--r--tools/perf/lib/libperf.map2
4 files changed, 193 insertions, 0 deletions
diff --git a/tools/perf/lib/cpumap.c b/tools/perf/lib/cpumap.c
index f3cfb4c71106..a5d4f7ff7174 100644
--- a/tools/perf/lib/cpumap.c
+++ b/tools/perf/lib/cpumap.c
@@ -5,6 +5,10 @@
5#include <internal/cpumap.h> 5#include <internal/cpumap.h>
6#include <asm/bug.h> 6#include <asm/bug.h>
7#include <stdio.h> 7#include <stdio.h>
8#include <string.h>
9#include <unistd.h>
10#include <ctype.h>
11#include <limits.h>
8 12
9struct perf_cpu_map *perf_cpu_map__dummy_new(void) 13struct perf_cpu_map *perf_cpu_map__dummy_new(void)
10{ 14{
@@ -40,3 +44,183 @@ void perf_cpu_map__put(struct perf_cpu_map *map)
40 if (map && refcount_dec_and_test(&map->refcnt)) 44 if (map && refcount_dec_and_test(&map->refcnt))
41 cpu_map__delete(map); 45 cpu_map__delete(map);
42} 46}
47
48static struct perf_cpu_map *cpu_map__default_new(void)
49{
50 struct perf_cpu_map *cpus;
51 int nr_cpus;
52
53 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
54 if (nr_cpus < 0)
55 return NULL;
56
57 cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
58 if (cpus != NULL) {
59 int i;
60
61 for (i = 0; i < nr_cpus; ++i)
62 cpus->map[i] = i;
63
64 cpus->nr = nr_cpus;
65 refcount_set(&cpus->refcnt, 1);
66 }
67
68 return cpus;
69}
70
71static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
72{
73 size_t payload_size = nr_cpus * sizeof(int);
74 struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
75
76 if (cpus != NULL) {
77 cpus->nr = nr_cpus;
78 memcpy(cpus->map, tmp_cpus, payload_size);
79 refcount_set(&cpus->refcnt, 1);
80 }
81
82 return cpus;
83}
84
85struct perf_cpu_map *perf_cpu_map__read(FILE *file)
86{
87 struct perf_cpu_map *cpus = NULL;
88 int nr_cpus = 0;
89 int *tmp_cpus = NULL, *tmp;
90 int max_entries = 0;
91 int n, cpu, prev;
92 char sep;
93
94 sep = 0;
95 prev = -1;
96 for (;;) {
97 n = fscanf(file, "%u%c", &cpu, &sep);
98 if (n <= 0)
99 break;
100 if (prev >= 0) {
101 int new_max = nr_cpus + cpu - prev - 1;
102
103 if (new_max >= max_entries) {
104 max_entries = new_max + MAX_NR_CPUS / 2;
105 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
106 if (tmp == NULL)
107 goto out_free_tmp;
108 tmp_cpus = tmp;
109 }
110
111 while (++prev < cpu)
112 tmp_cpus[nr_cpus++] = prev;
113 }
114 if (nr_cpus == max_entries) {
115 max_entries += MAX_NR_CPUS;
116 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
117 if (tmp == NULL)
118 goto out_free_tmp;
119 tmp_cpus = tmp;
120 }
121
122 tmp_cpus[nr_cpus++] = cpu;
123 if (n == 2 && sep == '-')
124 prev = cpu;
125 else
126 prev = -1;
127 if (n == 1 || sep == '\n')
128 break;
129 }
130
131 if (nr_cpus > 0)
132 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
133 else
134 cpus = cpu_map__default_new();
135out_free_tmp:
136 free(tmp_cpus);
137 return cpus;
138}
139
140static struct perf_cpu_map *cpu_map__read_all_cpu_map(void)
141{
142 struct perf_cpu_map *cpus = NULL;
143 FILE *onlnf;
144
145 onlnf = fopen("/sys/devices/system/cpu/online", "r");
146 if (!onlnf)
147 return cpu_map__default_new();
148
149 cpus = perf_cpu_map__read(onlnf);
150 fclose(onlnf);
151 return cpus;
152}
153
154struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list)
155{
156 struct perf_cpu_map *cpus = NULL;
157 unsigned long start_cpu, end_cpu = 0;
158 char *p = NULL;
159 int i, nr_cpus = 0;
160 int *tmp_cpus = NULL, *tmp;
161 int max_entries = 0;
162
163 if (!cpu_list)
164 return cpu_map__read_all_cpu_map();
165
166 /*
167 * must handle the case of empty cpumap to cover
168 * TOPOLOGY header for NUMA nodes with no CPU
169 * ( e.g., because of CPU hotplug)
170 */
171 if (!isdigit(*cpu_list) && *cpu_list != '\0')
172 goto out;
173
174 while (isdigit(*cpu_list)) {
175 p = NULL;
176 start_cpu = strtoul(cpu_list, &p, 0);
177 if (start_cpu >= INT_MAX
178 || (*p != '\0' && *p != ',' && *p != '-'))
179 goto invalid;
180
181 if (*p == '-') {
182 cpu_list = ++p;
183 p = NULL;
184 end_cpu = strtoul(cpu_list, &p, 0);
185
186 if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
187 goto invalid;
188
189 if (end_cpu < start_cpu)
190 goto invalid;
191 } else {
192 end_cpu = start_cpu;
193 }
194
195 for (; start_cpu <= end_cpu; start_cpu++) {
196 /* check for duplicates */
197 for (i = 0; i < nr_cpus; i++)
198 if (tmp_cpus[i] == (int)start_cpu)
199 goto invalid;
200
201 if (nr_cpus == max_entries) {
202 max_entries += MAX_NR_CPUS;
203 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
204 if (tmp == NULL)
205 goto invalid;
206 tmp_cpus = tmp;
207 }
208 tmp_cpus[nr_cpus++] = (int)start_cpu;
209 }
210 if (*p)
211 ++p;
212
213 cpu_list = p;
214 }
215
216 if (nr_cpus > 0)
217 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
218 else if (*cpu_list != '\0')
219 cpus = cpu_map__default_new();
220 else
221 cpus = perf_cpu_map__dummy_new();
222invalid:
223 free(tmp_cpus);
224out:
225 return cpus;
226}
diff --git a/tools/perf/lib/include/internal/cpumap.h b/tools/perf/lib/include/internal/cpumap.h
index 53ce95374b05..3306319f7df8 100644
--- a/tools/perf/lib/include/internal/cpumap.h
+++ b/tools/perf/lib/include/internal/cpumap.h
@@ -10,4 +10,8 @@ struct perf_cpu_map {
10 int map[]; 10 int map[];
11}; 11};
12 12
13#ifndef MAX_NR_CPUS
14#define MAX_NR_CPUS 2048
15#endif
16
13#endif /* __LIBPERF_INTERNAL_CPUMAP_H */ 17#endif /* __LIBPERF_INTERNAL_CPUMAP_H */
diff --git a/tools/perf/lib/include/perf/cpumap.h b/tools/perf/lib/include/perf/cpumap.h
index e16c2515a499..b4a9283a5dfa 100644
--- a/tools/perf/lib/include/perf/cpumap.h
+++ b/tools/perf/lib/include/perf/cpumap.h
@@ -3,10 +3,13 @@
3#define __LIBPERF_CPUMAP_H 3#define __LIBPERF_CPUMAP_H
4 4
5#include <perf/core.h> 5#include <perf/core.h>
6#include <stdio.h>
6 7
7struct perf_cpu_map; 8struct perf_cpu_map;
8 9
9LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void); 10LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
11LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
12LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
10LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); 13LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
11LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); 14LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
12 15
diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map
index 168339f89a2e..e38473a8f32f 100644
--- a/tools/perf/lib/libperf.map
+++ b/tools/perf/lib/libperf.map
@@ -4,6 +4,8 @@ LIBPERF_0.0.1 {
4 perf_cpu_map__dummy_new; 4 perf_cpu_map__dummy_new;
5 perf_cpu_map__get; 5 perf_cpu_map__get;
6 perf_cpu_map__put; 6 perf_cpu_map__put;
7 perf_cpu_map__new;
8 perf_cpu_map__read;
7 perf_thread_map__new_dummy; 9 perf_thread_map__new_dummy;
8 perf_thread_map__set_pid; 10 perf_thread_map__set_pid;
9 perf_thread_map__comm; 11 perf_thread_map__comm;