1b225fe34a722280c25d42c8959496a76cbf7e44
[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                 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
218                 return -1;
219         }
220
221         attr.config = id;
222
223         err = pipe(go_pipe);
224         __T("failed to create pipe", err == 0);
225
226         fflush(NULL);
227
228         pid = fork();
229         if (!pid) {
230                 int i;
231                 char bf;
232
233                 read(go_pipe[0], &bf, 1);
234
235                 /* Generate 100 prctl calls. */
236                 for (i = 0; i < 100; i++)
237                         prctl(0, 0, 0, 0, 0);
238
239                 exit(0);
240         }
241
242         threads = perf_thread_map__new_dummy();
243         __T("failed to create threads", threads);
244
245         cpus = perf_cpu_map__dummy_new();
246         __T("failed to create cpus", cpus);
247
248         perf_thread_map__set_pid(threads, 0, pid);
249
250         evlist = perf_evlist__new();
251         __T("failed to create evlist", evlist);
252
253         evsel = perf_evsel__new(&attr);
254         __T("failed to create evsel1", evsel);
255
256         perf_evlist__add(evlist, evsel);
257
258         perf_evlist__set_maps(evlist, cpus, threads);
259
260         err = perf_evlist__open(evlist);
261         __T("failed to open evlist", err == 0);
262
263         err = perf_evlist__mmap(evlist, 4);
264         __T("failed to mmap evlist", err == 0);
265
266         perf_evlist__enable(evlist);
267
268         /* kick the child and wait for it to finish */
269         write(go_pipe[1], "A", 1);
270         waitpid(pid, NULL, 0);
271
272         /*
273          * There's no need to call perf_evlist__disable,
274          * monitored process is dead now.
275          */
276
277         perf_evlist__for_each_mmap(evlist, map, false) {
278                 if (perf_mmap__read_init(map) < 0)
279                         continue;
280
281                 while ((event = perf_mmap__read_event(map)) != NULL) {
282                         count++;
283                         perf_mmap__consume(map);
284                 }
285
286                 perf_mmap__read_done(map);
287         }
288
289         /* calls perf_evlist__munmap/perf_evlist__close */
290         perf_evlist__delete(evlist);
291
292         perf_thread_map__put(threads);
293         perf_cpu_map__put(cpus);
294
295         /*
296          * The generated prctl calls should match the
297          * number of events in the buffer.
298          */
299         __T("failed count", count == 100);
300
301         return 0;
302 }
303
304 static int test_mmap_cpus(void)
305 {
306         struct perf_evlist *evlist;
307         struct perf_evsel *evsel;
308         struct perf_mmap *map;
309         struct perf_cpu_map *cpus;
310         struct perf_event_attr attr = {
311                 .type             = PERF_TYPE_TRACEPOINT,
312                 .sample_period    = 1,
313                 .wakeup_watermark = 1,
314                 .disabled         = 1,
315         };
316         cpu_set_t saved_mask;
317         char path[PATH_MAX];
318         int id, err, cpu, tmp;
319         union perf_event *event;
320         int count = 0;
321
322         snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
323                  sysfs__mountpoint());
324
325         if (filename__read_int(path, &id)) {
326                 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
327                 return -1;
328         }
329
330         attr.config = id;
331
332         cpus = perf_cpu_map__new(NULL);
333         __T("failed to create cpus", cpus);
334
335         evlist = perf_evlist__new();
336         __T("failed to create evlist", evlist);
337
338         evsel = perf_evsel__new(&attr);
339         __T("failed to create evsel1", evsel);
340
341         perf_evlist__add(evlist, evsel);
342
343         perf_evlist__set_maps(evlist, cpus, NULL);
344
345         err = perf_evlist__open(evlist);
346         __T("failed to open evlist", err == 0);
347
348         err = perf_evlist__mmap(evlist, 4);
349         __T("failed to mmap evlist", err == 0);
350
351         perf_evlist__enable(evlist);
352
353         err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
354         __T("sched_getaffinity failed", err == 0);
355
356         perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
357                 cpu_set_t mask;
358
359                 CPU_ZERO(&mask);
360                 CPU_SET(cpu, &mask);
361
362                 err = sched_setaffinity(0, sizeof(mask), &mask);
363                 __T("sched_setaffinity failed", err == 0);
364
365                 prctl(0, 0, 0, 0, 0);
366         }
367
368         err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
369         __T("sched_setaffinity failed", err == 0);
370
371         perf_evlist__disable(evlist);
372
373         perf_evlist__for_each_mmap(evlist, map, false) {
374                 if (perf_mmap__read_init(map) < 0)
375                         continue;
376
377                 while ((event = perf_mmap__read_event(map)) != NULL) {
378                         count++;
379                         perf_mmap__consume(map);
380                 }
381
382                 perf_mmap__read_done(map);
383         }
384
385         /* calls perf_evlist__munmap/perf_evlist__close */
386         perf_evlist__delete(evlist);
387
388         /*
389          * The generated prctl events should match the
390          * number of cpus or be bigger (we are system-wide).
391          */
392         __T("failed count", count >= perf_cpu_map__nr(cpus));
393
394         perf_cpu_map__put(cpus);
395
396         return 0;
397 }
398
399 int main(int argc, char **argv)
400 {
401         __T_START;
402
403         libperf_init(libperf_print);
404
405         test_stat_cpu();
406         test_stat_thread();
407         test_stat_thread_enable();
408         test_mmap_thread();
409         test_mmap_cpus();
410
411         __T_END;
412         return 0;
413 }