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