diff options
author | Jiri Olsa <jolsa@kernel.org> | 2019-07-21 07:24:30 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-07-29 17:34:45 -0400 |
commit | 9c3516d1b850ea938b074df33e4c86d721c77720 (patch) | |
tree | cb937368ee6d8048f465bcbe27d62709f871212c /tools/perf/lib | |
parent | 1fc632cef4ea137bc45fd0fc4cb902e374064163 (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.c | 184 | ||||
-rw-r--r-- | tools/perf/lib/include/internal/cpumap.h | 4 | ||||
-rw-r--r-- | tools/perf/lib/include/perf/cpumap.h | 3 | ||||
-rw-r--r-- | tools/perf/lib/libperf.map | 2 |
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 | ||
9 | struct perf_cpu_map *perf_cpu_map__dummy_new(void) | 13 | struct 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 | |||
48 | static 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 | |||
71 | static 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 | |||
85 | struct 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(); | ||
135 | out_free_tmp: | ||
136 | free(tmp_cpus); | ||
137 | return cpus; | ||
138 | } | ||
139 | |||
140 | static 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 | |||
154 | struct 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(); | ||
222 | invalid: | ||
223 | free(tmp_cpus); | ||
224 | out: | ||
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 | ||
7 | struct perf_cpu_map; | 8 | struct perf_cpu_map; |
8 | 9 | ||
9 | LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void); | 10 | LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void); |
11 | LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list); | ||
12 | LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file); | ||
10 | LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); | 13 | LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); |
11 | LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); | 14 | LIBPERF_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; |