Merge branch 'for-linus' into for-next
[linux-2.6-microblaze.git] / tools / lib / perf / tests / test-evlist.c
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
3 #include <sched.h>
4 #include <stdio.h>
5 #include <stdarg.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <linux/perf_event.h>
9 #include <linux/limits.h>
10 #include <sys/types.h>
11 #include <sys/wait.h>
12 #include <sys/prctl.h>
13 #include <perf/cpumap.h>
14 #include <perf/threadmap.h>
15 #include <perf/evlist.h>
16 #include <perf/evsel.h>
17 #include <perf/mmap.h>
18 #include <perf/event.h>
19 #include <internal/tests.h>
20 #include <api/fs/fs.h>
21
22 static int libperf_print(enum libperf_print_level level,
23                          const char *fmt, va_list ap)
24 {
25         return vfprintf(stderr, fmt, ap);
26 }
27
28 static int test_stat_cpu(void)
29 {
30         struct perf_cpu_map *cpus;
31         struct perf_evlist *evlist;
32         struct perf_evsel *evsel;
33         struct perf_event_attr attr1 = {
34                 .type   = PERF_TYPE_SOFTWARE,
35                 .config = PERF_COUNT_SW_CPU_CLOCK,
36         };
37         struct perf_event_attr attr2 = {
38                 .type   = PERF_TYPE_SOFTWARE,
39                 .config = PERF_COUNT_SW_TASK_CLOCK,
40         };
41         int err, cpu, tmp;
42
43         cpus = perf_cpu_map__new(NULL);
44         __T("failed to create cpus", cpus);
45
46         evlist = perf_evlist__new();
47         __T("failed to create evlist", evlist);
48
49         evsel = perf_evsel__new(&attr1);
50         __T("failed to create evsel1", evsel);
51
52         perf_evlist__add(evlist, evsel);
53
54         evsel = perf_evsel__new(&attr2);
55         __T("failed to create evsel2", evsel);
56
57         perf_evlist__add(evlist, evsel);
58
59         perf_evlist__set_maps(evlist, cpus, NULL);
60
61         err = perf_evlist__open(evlist);
62         __T("failed to open evsel", err == 0);
63
64         perf_evlist__for_each_evsel(evlist, evsel) {
65                 cpus = perf_evsel__cpus(evsel);
66
67                 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
68                         struct perf_counts_values counts = { .val = 0 };
69
70                         perf_evsel__read(evsel, cpu, 0, &counts);
71                         __T("failed to read value for evsel", counts.val != 0);
72                 }
73         }
74
75         perf_evlist__close(evlist);
76         perf_evlist__delete(evlist);
77
78         perf_cpu_map__put(cpus);
79         return 0;
80 }
81
82 static int test_stat_thread(void)
83 {
84         struct perf_counts_values counts = { .val = 0 };
85         struct perf_thread_map *threads;
86         struct perf_evlist *evlist;
87         struct perf_evsel *evsel;
88         struct perf_event_attr attr1 = {
89                 .type   = PERF_TYPE_SOFTWARE,
90                 .config = PERF_COUNT_SW_CPU_CLOCK,
91         };
92         struct perf_event_attr attr2 = {
93                 .type   = PERF_TYPE_SOFTWARE,
94                 .config = PERF_COUNT_SW_TASK_CLOCK,
95         };
96         int err;
97
98         threads = perf_thread_map__new_dummy();
99         __T("failed to create threads", threads);
100
101         perf_thread_map__set_pid(threads, 0, 0);
102
103         evlist = perf_evlist__new();
104         __T("failed to create evlist", evlist);
105
106         evsel = perf_evsel__new(&attr1);
107         __T("failed to create evsel1", evsel);
108
109         perf_evlist__add(evlist, evsel);
110
111         evsel = perf_evsel__new(&attr2);
112         __T("failed to create evsel2", evsel);
113
114         perf_evlist__add(evlist, evsel);
115
116         perf_evlist__set_maps(evlist, NULL, threads);
117
118         err = perf_evlist__open(evlist);
119         __T("failed to open evsel", err == 0);
120
121         perf_evlist__for_each_evsel(evlist, evsel) {
122                 perf_evsel__read(evsel, 0, 0, &counts);
123                 __T("failed to read value for evsel", counts.val != 0);
124         }
125
126         perf_evlist__close(evlist);
127         perf_evlist__delete(evlist);
128
129         perf_thread_map__put(threads);
130         return 0;
131 }
132
133 static int test_stat_thread_enable(void)
134 {
135         struct perf_counts_values counts = { .val = 0 };
136         struct perf_thread_map *threads;
137         struct perf_evlist *evlist;
138         struct perf_evsel *evsel;
139         struct perf_event_attr attr1 = {
140                 .type     = PERF_TYPE_SOFTWARE,
141                 .config   = PERF_COUNT_SW_CPU_CLOCK,
142                 .disabled = 1,
143         };
144         struct perf_event_attr attr2 = {
145                 .type     = PERF_TYPE_SOFTWARE,
146                 .config   = PERF_COUNT_SW_TASK_CLOCK,
147                 .disabled = 1,
148         };
149         int err;
150
151         threads = perf_thread_map__new_dummy();
152         __T("failed to create threads", threads);
153
154         perf_thread_map__set_pid(threads, 0, 0);
155
156         evlist = perf_evlist__new();
157         __T("failed to create evlist", evlist);
158
159         evsel = perf_evsel__new(&attr1);
160         __T("failed to create evsel1", evsel);
161
162         perf_evlist__add(evlist, evsel);
163
164         evsel = perf_evsel__new(&attr2);
165         __T("failed to create evsel2", evsel);
166
167         perf_evlist__add(evlist, evsel);
168
169         perf_evlist__set_maps(evlist, NULL, threads);
170
171         err = perf_evlist__open(evlist);
172         __T("failed to open evsel", err == 0);
173
174         perf_evlist__for_each_evsel(evlist, evsel) {
175                 perf_evsel__read(evsel, 0, 0, &counts);
176                 __T("failed to read value for evsel", counts.val == 0);
177         }
178
179         perf_evlist__enable(evlist);
180
181         perf_evlist__for_each_evsel(evlist, evsel) {
182                 perf_evsel__read(evsel, 0, 0, &counts);
183                 __T("failed to read value for evsel", counts.val != 0);
184         }
185
186         perf_evlist__disable(evlist);
187
188         perf_evlist__close(evlist);
189         perf_evlist__delete(evlist);
190
191         perf_thread_map__put(threads);
192         return 0;
193 }
194
195 static int test_mmap_thread(void)
196 {
197         struct perf_evlist *evlist;
198         struct perf_evsel *evsel;
199         struct perf_mmap *map;
200         struct perf_cpu_map *cpus;
201         struct perf_thread_map *threads;
202         struct perf_event_attr attr = {
203                 .type             = PERF_TYPE_TRACEPOINT,
204                 .sample_period    = 1,
205                 .wakeup_watermark = 1,
206                 .disabled         = 1,
207         };
208         char path[PATH_MAX];
209         int id, err, pid, go_pipe[2];
210         union perf_event *event;
211         int count = 0;
212
213         snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
214                  sysfs__mountpoint());
215
216         if (filename__read_int(path, &id)) {
217                 tests_failed++;
218                 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
219                 return -1;
220         }
221
222         attr.config = id;
223
224         err = pipe(go_pipe);
225         __T("failed to create pipe", err == 0);
226
227         fflush(NULL);
228
229         pid = fork();
230         if (!pid) {
231                 int i;
232                 char bf;
233
234                 read(go_pipe[0], &bf, 1);
235
236                 /* Generate 100 prctl calls. */
237                 for (i = 0; i < 100; i++)
238                         prctl(0, 0, 0, 0, 0);
239
240                 exit(0);
241         }
242
243         threads = perf_thread_map__new_dummy();
244         __T("failed to create threads", threads);
245
246         cpus = perf_cpu_map__dummy_new();
247         __T("failed to create cpus", cpus);
248
249         perf_thread_map__set_pid(threads, 0, pid);
250
251         evlist = perf_evlist__new();
252         __T("failed to create evlist", evlist);
253
254         evsel = perf_evsel__new(&attr);
255         __T("failed to create evsel1", evsel);
256
257         perf_evlist__add(evlist, evsel);
258
259         perf_evlist__set_maps(evlist, cpus, threads);
260
261         err = perf_evlist__open(evlist);
262         __T("failed to open evlist", err == 0);
263
264         err = perf_evlist__mmap(evlist, 4);
265         __T("failed to mmap evlist", err == 0);
266
267         perf_evlist__enable(evlist);
268
269         /* kick the child and wait for it to finish */
270         write(go_pipe[1], "A", 1);
271         waitpid(pid, NULL, 0);
272
273         /*
274          * There's no need to call perf_evlist__disable,
275          * monitored process is dead now.
276          */
277
278         perf_evlist__for_each_mmap(evlist, map, false) {
279                 if (perf_mmap__read_init(map) < 0)
280                         continue;
281
282                 while ((event = perf_mmap__read_event(map)) != NULL) {
283                         count++;
284                         perf_mmap__consume(map);
285                 }
286
287                 perf_mmap__read_done(map);
288         }
289
290         /* calls perf_evlist__munmap/perf_evlist__close */
291         perf_evlist__delete(evlist);
292
293         perf_thread_map__put(threads);
294         perf_cpu_map__put(cpus);
295
296         /*
297          * The generated prctl calls should match the
298          * number of events in the buffer.
299          */
300         __T("failed count", count == 100);
301
302         return 0;
303 }
304
305 static int test_mmap_cpus(void)
306 {
307         struct perf_evlist *evlist;
308         struct perf_evsel *evsel;
309         struct perf_mmap *map;
310         struct perf_cpu_map *cpus;
311         struct perf_event_attr attr = {
312                 .type             = PERF_TYPE_TRACEPOINT,
313                 .sample_period    = 1,
314                 .wakeup_watermark = 1,
315                 .disabled         = 1,
316         };
317         cpu_set_t saved_mask;
318         char path[PATH_MAX];
319         int id, err, cpu, tmp;
320         union perf_event *event;
321         int count = 0;
322
323         snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
324                  sysfs__mountpoint());
325
326         if (filename__read_int(path, &id)) {
327                 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
328                 return -1;
329         }
330
331         attr.config = id;
332
333         cpus = perf_cpu_map__new(NULL);
334         __T("failed to create cpus", cpus);
335
336         evlist = perf_evlist__new();
337         __T("failed to create evlist", evlist);
338
339         evsel = perf_evsel__new(&attr);
340         __T("failed to create evsel1", evsel);
341
342         perf_evlist__add(evlist, evsel);
343
344         perf_evlist__set_maps(evlist, cpus, NULL);
345
346         err = perf_evlist__open(evlist);
347         __T("failed to open evlist", err == 0);
348
349         err = perf_evlist__mmap(evlist, 4);
350         __T("failed to mmap evlist", err == 0);
351
352         perf_evlist__enable(evlist);
353
354         err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
355         __T("sched_getaffinity failed", err == 0);
356
357         perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
358                 cpu_set_t mask;
359
360                 CPU_ZERO(&mask);
361                 CPU_SET(cpu, &mask);
362
363                 err = sched_setaffinity(0, sizeof(mask), &mask);
364                 __T("sched_setaffinity failed", err == 0);
365
366                 prctl(0, 0, 0, 0, 0);
367         }
368
369         err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
370         __T("sched_setaffinity failed", err == 0);
371
372         perf_evlist__disable(evlist);
373
374         perf_evlist__for_each_mmap(evlist, map, false) {
375                 if (perf_mmap__read_init(map) < 0)
376                         continue;
377
378                 while ((event = perf_mmap__read_event(map)) != NULL) {
379                         count++;
380                         perf_mmap__consume(map);
381                 }
382
383                 perf_mmap__read_done(map);
384         }
385
386         /* calls perf_evlist__munmap/perf_evlist__close */
387         perf_evlist__delete(evlist);
388
389         /*
390          * The generated prctl events should match the
391          * number of cpus or be bigger (we are system-wide).
392          */
393         __T("failed count", count >= perf_cpu_map__nr(cpus));
394
395         perf_cpu_map__put(cpus);
396
397         return 0;
398 }
399
400 int main(int argc, char **argv)
401 {
402         __T_START;
403
404         libperf_init(libperf_print);
405
406         test_stat_cpu();
407         test_stat_thread();
408         test_stat_thread_enable();
409         test_mmap_thread();
410         test_mmap_cpus();
411
412         __T_END;
413         return tests_failed == 0 ? 0 : -1;
414 }