Skip to content

Commit 6d18804

Browse files
captain5050acmel
authored andcommitted
perf cpumap: Give CPUs their own type
A common problem is confusing CPU map indices with the CPU, by wrapping the CPU with a struct then this is avoided. This approach is similar to atomic_t. Committer notes: To make it build with BUILD_BPF_SKEL=1 these files needed the conversions to 'struct perf_cpu' usage: tools/perf/util/bpf_counter.c tools/perf/util/bpf_counter_cgroup.c tools/perf/util/bpf_ftrace.c Also perf_env__get_cpu() was removed back in "perf cpumap: Switch cpu_map__build_map to cpu function". Additionally these needed to be fixed for the ARM builds to complete: tools/perf/arch/arm/util/cs-etm.c tools/perf/arch/arm64/util/pmu.c Suggested-by: John Garry <john.garry@huawei.com> Signed-off-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Mike Leach <mike.leach@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Clarke <pc@us.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Riccardo Mancini <rickyman7@gmail.com> Cc: Stephane Eranian <eranian@google.com> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Cc: Vineet Singh <vineet.singh@intel.com> Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Cc: zhengjun.xing@intel.com Link: https://lore.kernel.org/r/20220105061351.120843-49-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent ce37ab3 commit 6d18804

64 files changed

Lines changed: 431 additions & 356 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

tools/lib/perf/cpumap.c

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,24 @@
1010
#include <ctype.h>
1111
#include <limits.h>
1212

13-
struct perf_cpu_map *perf_cpu_map__dummy_new(void)
13+
static struct perf_cpu_map *perf_cpu_map__alloc(int nr_cpus)
1414
{
15-
struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
15+
struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(struct perf_cpu) * nr_cpus);
1616

1717
if (cpus != NULL) {
18-
cpus->nr = 1;
19-
cpus->map[0] = -1;
18+
cpus->nr = nr_cpus;
2019
refcount_set(&cpus->refcnt, 1);
20+
2121
}
22+
return cpus;
23+
}
24+
25+
struct perf_cpu_map *perf_cpu_map__dummy_new(void)
26+
{
27+
struct perf_cpu_map *cpus = perf_cpu_map__alloc(1);
28+
29+
if (cpus)
30+
cpus->map[0].cpu = -1;
2231

2332
return cpus;
2433
}
@@ -54,15 +63,12 @@ static struct perf_cpu_map *cpu_map__default_new(void)
5463
if (nr_cpus < 0)
5564
return NULL;
5665

57-
cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
66+
cpus = perf_cpu_map__alloc(nr_cpus);
5867
if (cpus != NULL) {
5968
int i;
6069

6170
for (i = 0; i < nr_cpus; ++i)
62-
cpus->map[i] = i;
63-
64-
cpus->nr = nr_cpus;
65-
refcount_set(&cpus->refcnt, 1);
71+
cpus->map[i].cpu = i;
6672
}
6773

6874
return cpus;
@@ -73,39 +79,40 @@ struct perf_cpu_map *perf_cpu_map__default_new(void)
7379
return cpu_map__default_new();
7480
}
7581

76-
static int cmp_int(const void *a, const void *b)
82+
83+
static int cmp_cpu(const void *a, const void *b)
7784
{
78-
return *(const int *)a - *(const int*)b;
85+
const struct perf_cpu *cpu_a = a, *cpu_b = b;
86+
87+
return cpu_a->cpu - cpu_b->cpu;
7988
}
8089

81-
static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
90+
static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, const struct perf_cpu *tmp_cpus)
8291
{
83-
size_t payload_size = nr_cpus * sizeof(int);
84-
struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
92+
size_t payload_size = nr_cpus * sizeof(struct perf_cpu);
93+
struct perf_cpu_map *cpus = perf_cpu_map__alloc(nr_cpus);
8594
int i, j;
8695

8796
if (cpus != NULL) {
8897
memcpy(cpus->map, tmp_cpus, payload_size);
89-
qsort(cpus->map, nr_cpus, sizeof(int), cmp_int);
98+
qsort(cpus->map, nr_cpus, sizeof(struct perf_cpu), cmp_cpu);
9099
/* Remove dups */
91100
j = 0;
92101
for (i = 0; i < nr_cpus; i++) {
93-
if (i == 0 || cpus->map[i] != cpus->map[i - 1])
94-
cpus->map[j++] = cpus->map[i];
102+
if (i == 0 || cpus->map[i].cpu != cpus->map[i - 1].cpu)
103+
cpus->map[j++].cpu = cpus->map[i].cpu;
95104
}
96105
cpus->nr = j;
97106
assert(j <= nr_cpus);
98-
refcount_set(&cpus->refcnt, 1);
99107
}
100-
101108
return cpus;
102109
}
103110

104111
struct perf_cpu_map *perf_cpu_map__read(FILE *file)
105112
{
106113
struct perf_cpu_map *cpus = NULL;
107114
int nr_cpus = 0;
108-
int *tmp_cpus = NULL, *tmp;
115+
struct perf_cpu *tmp_cpus = NULL, *tmp;
109116
int max_entries = 0;
110117
int n, cpu, prev;
111118
char sep;
@@ -124,24 +131,24 @@ struct perf_cpu_map *perf_cpu_map__read(FILE *file)
124131

125132
if (new_max >= max_entries) {
126133
max_entries = new_max + MAX_NR_CPUS / 2;
127-
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
134+
tmp = realloc(tmp_cpus, max_entries * sizeof(struct perf_cpu));
128135
if (tmp == NULL)
129136
goto out_free_tmp;
130137
tmp_cpus = tmp;
131138
}
132139

133140
while (++prev < cpu)
134-
tmp_cpus[nr_cpus++] = prev;
141+
tmp_cpus[nr_cpus++].cpu = prev;
135142
}
136143
if (nr_cpus == max_entries) {
137144
max_entries += MAX_NR_CPUS;
138-
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
145+
tmp = realloc(tmp_cpus, max_entries * sizeof(struct perf_cpu));
139146
if (tmp == NULL)
140147
goto out_free_tmp;
141148
tmp_cpus = tmp;
142149
}
143150

144-
tmp_cpus[nr_cpus++] = cpu;
151+
tmp_cpus[nr_cpus++].cpu = cpu;
145152
if (n == 2 && sep == '-')
146153
prev = cpu;
147154
else
@@ -179,7 +186,7 @@ struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list)
179186
unsigned long start_cpu, end_cpu = 0;
180187
char *p = NULL;
181188
int i, nr_cpus = 0;
182-
int *tmp_cpus = NULL, *tmp;
189+
struct perf_cpu *tmp_cpus = NULL, *tmp;
183190
int max_entries = 0;
184191

185192
if (!cpu_list)
@@ -220,17 +227,17 @@ struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list)
220227
for (; start_cpu <= end_cpu; start_cpu++) {
221228
/* check for duplicates */
222229
for (i = 0; i < nr_cpus; i++)
223-
if (tmp_cpus[i] == (int)start_cpu)
230+
if (tmp_cpus[i].cpu == (int)start_cpu)
224231
goto invalid;
225232

226233
if (nr_cpus == max_entries) {
227234
max_entries += MAX_NR_CPUS;
228-
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
235+
tmp = realloc(tmp_cpus, max_entries * sizeof(struct perf_cpu));
229236
if (tmp == NULL)
230237
goto invalid;
231238
tmp_cpus = tmp;
232239
}
233-
tmp_cpus[nr_cpus++] = (int)start_cpu;
240+
tmp_cpus[nr_cpus++].cpu = (int)start_cpu;
234241
}
235242
if (*p)
236243
++p;
@@ -250,12 +257,16 @@ struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list)
250257
return cpus;
251258
}
252259

253-
int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx)
260+
struct perf_cpu perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx)
254261
{
262+
struct perf_cpu result = {
263+
.cpu = -1
264+
};
265+
255266
if (cpus && idx < cpus->nr)
256267
return cpus->map[idx];
257268

258-
return -1;
269+
return result;
259270
}
260271

261272
int perf_cpu_map__nr(const struct perf_cpu_map *cpus)
@@ -265,10 +276,10 @@ int perf_cpu_map__nr(const struct perf_cpu_map *cpus)
265276

266277
bool perf_cpu_map__empty(const struct perf_cpu_map *map)
267278
{
268-
return map ? map->map[0] == -1 : true;
279+
return map ? map->map[0].cpu == -1 : true;
269280
}
270281

271-
int perf_cpu_map__idx(const struct perf_cpu_map *cpus, int cpu)
282+
int perf_cpu_map__idx(const struct perf_cpu_map *cpus, struct perf_cpu cpu)
272283
{
273284
int low, high;
274285

@@ -278,13 +289,13 @@ int perf_cpu_map__idx(const struct perf_cpu_map *cpus, int cpu)
278289
low = 0;
279290
high = cpus->nr;
280291
while (low < high) {
281-
int idx = (low + high) / 2,
282-
cpu_at_idx = cpus->map[idx];
292+
int idx = (low + high) / 2;
293+
struct perf_cpu cpu_at_idx = cpus->map[idx];
283294

284-
if (cpu_at_idx == cpu)
295+
if (cpu_at_idx.cpu == cpu.cpu)
285296
return idx;
286297

287-
if (cpu_at_idx > cpu)
298+
if (cpu_at_idx.cpu > cpu.cpu)
288299
high = idx;
289300
else
290301
low = idx + 1;
@@ -293,15 +304,19 @@ int perf_cpu_map__idx(const struct perf_cpu_map *cpus, int cpu)
293304
return -1;
294305
}
295306

296-
bool perf_cpu_map__has(const struct perf_cpu_map *cpus, int cpu)
307+
bool perf_cpu_map__has(const struct perf_cpu_map *cpus, struct perf_cpu cpu)
297308
{
298309
return perf_cpu_map__idx(cpus, cpu) != -1;
299310
}
300311

301-
int perf_cpu_map__max(struct perf_cpu_map *map)
312+
struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *map)
302313
{
314+
struct perf_cpu result = {
315+
.cpu = -1
316+
};
317+
303318
// cpu_map__trim_new() qsort()s it, cpu_map__default_new() sorts it as well.
304-
return map->nr > 0 ? map->map[map->nr - 1] : -1;
319+
return map->nr > 0 ? map->map[map->nr - 1] : result;
305320
}
306321

307322
/*
@@ -315,7 +330,7 @@ int perf_cpu_map__max(struct perf_cpu_map *map)
315330
struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
316331
struct perf_cpu_map *other)
317332
{
318-
int *tmp_cpus;
333+
struct perf_cpu *tmp_cpus;
319334
int tmp_len;
320335
int i, j, k;
321336
struct perf_cpu_map *merged;
@@ -329,19 +344,19 @@ struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
329344
if (!other)
330345
return orig;
331346
if (orig->nr == other->nr &&
332-
!memcmp(orig->map, other->map, orig->nr * sizeof(int)))
347+
!memcmp(orig->map, other->map, orig->nr * sizeof(struct perf_cpu)))
333348
return orig;
334349

335350
tmp_len = orig->nr + other->nr;
336-
tmp_cpus = malloc(tmp_len * sizeof(int));
351+
tmp_cpus = malloc(tmp_len * sizeof(struct perf_cpu));
337352
if (!tmp_cpus)
338353
return NULL;
339354

340355
/* Standard merge algorithm from wikipedia */
341356
i = j = k = 0;
342357
while (i < orig->nr && j < other->nr) {
343-
if (orig->map[i] <= other->map[j]) {
344-
if (orig->map[i] == other->map[j])
358+
if (orig->map[i].cpu <= other->map[j].cpu) {
359+
if (orig->map[i].cpu == other->map[j].cpu)
345360
j++;
346361
tmp_cpus[k++] = orig->map[i++];
347362
} else

tools/lib/perf/evlist.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ perf_evlist__mmap_cb_get(struct perf_evlist *evlist, bool overwrite, int idx)
407407

408408
static int
409409
perf_evlist__mmap_cb_mmap(struct perf_mmap *map, struct perf_mmap_param *mp,
410-
int output, int cpu)
410+
int output, struct perf_cpu cpu)
411411
{
412412
return perf_mmap__mmap(map, mp, output, cpu);
413413
}
@@ -426,7 +426,7 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
426426
int idx, struct perf_mmap_param *mp, int cpu_idx,
427427
int thread, int *_output, int *_output_overwrite)
428428
{
429-
int evlist_cpu = perf_cpu_map__cpu(evlist->cpus, cpu_idx);
429+
struct perf_cpu evlist_cpu = perf_cpu_map__cpu(evlist->cpus, cpu_idx);
430430
struct perf_evsel *evsel;
431431
int revent;
432432

tools/lib/perf/evsel.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ static int perf_evsel__alloc_mmap(struct perf_evsel *evsel, int ncpus, int nthre
7878

7979
static int
8080
sys_perf_event_open(struct perf_event_attr *attr,
81-
pid_t pid, int cpu, int group_fd,
81+
pid_t pid, struct perf_cpu cpu, int group_fd,
8282
unsigned long flags)
8383
{
84-
return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
84+
return syscall(__NR_perf_event_open, attr, pid, cpu.cpu, group_fd, flags);
8585
}
8686

8787
static int get_group_fd(struct perf_evsel *evsel, int cpu_map_idx, int thread, int *group_fd)
@@ -113,7 +113,8 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu_map_idx, int thread, i
113113
int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
114114
struct perf_thread_map *threads)
115115
{
116-
int cpu, idx, thread, err = 0;
116+
struct perf_cpu cpu;
117+
int idx, thread, err = 0;
117118

118119
if (cpus == NULL) {
119120
static struct perf_cpu_map *empty_cpu_map;
@@ -252,7 +253,7 @@ int perf_evsel__mmap(struct perf_evsel *evsel, int pages)
252253
for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
253254
int *fd = FD(evsel, idx, thread);
254255
struct perf_mmap *map;
255-
int cpu = perf_cpu_map__cpu(evsel->cpus, idx);
256+
struct perf_cpu cpu = perf_cpu_map__cpu(evsel->cpus, idx);
256257

257258
if (fd == NULL || *fd < 0)
258259
continue;

tools/lib/perf/include/internal/cpumap.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
#include <linux/refcount.h>
66

7+
/** A wrapper around a CPU to avoid confusion with the perf_cpu_map's map's indices. */
8+
struct perf_cpu {
9+
int cpu;
10+
};
11+
712
/**
813
* A sized, reference counted, sorted array of integers representing CPU
914
* numbers. This is commonly used to capture which CPUs a PMU is associated
@@ -16,13 +21,13 @@ struct perf_cpu_map {
1621
/** Length of the map array. */
1722
int nr;
1823
/** The CPU values. */
19-
int map[];
24+
struct perf_cpu map[];
2025
};
2126

2227
#ifndef MAX_NR_CPUS
2328
#define MAX_NR_CPUS 2048
2429
#endif
2530

26-
int perf_cpu_map__idx(const struct perf_cpu_map *cpus, int cpu);
31+
int perf_cpu_map__idx(const struct perf_cpu_map *cpus, struct perf_cpu cpu);
2732

2833
#endif /* __LIBPERF_INTERNAL_CPUMAP_H */

tools/lib/perf/include/internal/evlist.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <linux/list.h>
66
#include <api/fd/array.h>
7+
#include <internal/cpumap.h>
78
#include <internal/evsel.h>
89

910
#define PERF_EVLIST__HLIST_BITS 8
@@ -36,7 +37,7 @@ typedef void
3637
typedef struct perf_mmap*
3738
(*perf_evlist_mmap__cb_get_t)(struct perf_evlist*, bool, int);
3839
typedef int
39-
(*perf_evlist_mmap__cb_mmap_t)(struct perf_mmap*, struct perf_mmap_param*, int, int);
40+
(*perf_evlist_mmap__cb_mmap_t)(struct perf_mmap*, struct perf_mmap_param*, int, struct perf_cpu);
4041

4142
struct perf_evlist_mmap_ops {
4243
perf_evlist_mmap__cb_idx_t idx;

tools/lib/perf/include/internal/evsel.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#include <linux/perf_event.h>
77
#include <stdbool.h>
88
#include <sys/types.h>
9+
#include <internal/cpumap.h>
910

10-
struct perf_cpu_map;
1111
struct perf_thread_map;
1212
struct xyarray;
1313

@@ -27,7 +27,7 @@ struct perf_sample_id {
2727
* queue number.
2828
*/
2929
int idx;
30-
int cpu;
30+
struct perf_cpu cpu;
3131
pid_t tid;
3232

3333
/* Holds total ID period value for PERF_SAMPLE_READ processing. */

0 commit comments

Comments
 (0)