1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
8 #include <linux/perf_event.h>
9 #include <linux/limits.h>
10 #include <sys/types.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>
22 static int libperf_print(enum libperf_print_level level
,
23 const char *fmt
, va_list ap
)
25 return vfprintf(stderr
, fmt
, ap
);
28 static int test_stat_cpu(void)
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
,
37 struct perf_event_attr attr2
= {
38 .type
= PERF_TYPE_SOFTWARE
,
39 .config
= PERF_COUNT_SW_TASK_CLOCK
,
43 cpus
= perf_cpu_map__new(NULL
);
44 __T("failed to create cpus", cpus
);
46 evlist
= perf_evlist__new();
47 __T("failed to create evlist", evlist
);
49 evsel
= perf_evsel__new(&attr1
);
50 __T("failed to create evsel1", evsel
);
52 perf_evlist__add(evlist
, evsel
);
54 evsel
= perf_evsel__new(&attr2
);
55 __T("failed to create evsel2", evsel
);
57 perf_evlist__add(evlist
, evsel
);
59 perf_evlist__set_maps(evlist
, cpus
, NULL
);
61 err
= perf_evlist__open(evlist
);
62 __T("failed to open evsel", err
== 0);
64 perf_evlist__for_each_evsel(evlist
, evsel
) {
65 cpus
= perf_evsel__cpus(evsel
);
67 perf_cpu_map__for_each_cpu(cpu
, tmp
, cpus
) {
68 struct perf_counts_values counts
= { .val
= 0 };
70 perf_evsel__read(evsel
, cpu
, 0, &counts
);
71 __T("failed to read value for evsel", counts
.val
!= 0);
75 perf_evlist__close(evlist
);
76 perf_evlist__delete(evlist
);
78 perf_cpu_map__put(cpus
);
82 static int test_stat_thread(void)
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
,
92 struct perf_event_attr attr2
= {
93 .type
= PERF_TYPE_SOFTWARE
,
94 .config
= PERF_COUNT_SW_TASK_CLOCK
,
98 threads
= perf_thread_map__new_dummy();
99 __T("failed to create threads", threads
);
101 perf_thread_map__set_pid(threads
, 0, 0);
103 evlist
= perf_evlist__new();
104 __T("failed to create evlist", evlist
);
106 evsel
= perf_evsel__new(&attr1
);
107 __T("failed to create evsel1", evsel
);
109 perf_evlist__add(evlist
, evsel
);
111 evsel
= perf_evsel__new(&attr2
);
112 __T("failed to create evsel2", evsel
);
114 perf_evlist__add(evlist
, evsel
);
116 perf_evlist__set_maps(evlist
, NULL
, threads
);
118 err
= perf_evlist__open(evlist
);
119 __T("failed to open evsel", err
== 0);
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);
126 perf_evlist__close(evlist
);
127 perf_evlist__delete(evlist
);
129 perf_thread_map__put(threads
);
133 static int test_stat_thread_enable(void)
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
,
144 struct perf_event_attr attr2
= {
145 .type
= PERF_TYPE_SOFTWARE
,
146 .config
= PERF_COUNT_SW_TASK_CLOCK
,
151 threads
= perf_thread_map__new_dummy();
152 __T("failed to create threads", threads
);
154 perf_thread_map__set_pid(threads
, 0, 0);
156 evlist
= perf_evlist__new();
157 __T("failed to create evlist", evlist
);
159 evsel
= perf_evsel__new(&attr1
);
160 __T("failed to create evsel1", evsel
);
162 perf_evlist__add(evlist
, evsel
);
164 evsel
= perf_evsel__new(&attr2
);
165 __T("failed to create evsel2", evsel
);
167 perf_evlist__add(evlist
, evsel
);
169 perf_evlist__set_maps(evlist
, NULL
, threads
);
171 err
= perf_evlist__open(evlist
);
172 __T("failed to open evsel", err
== 0);
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);
179 perf_evlist__enable(evlist
);
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);
186 perf_evlist__disable(evlist
);
188 perf_evlist__close(evlist
);
189 perf_evlist__delete(evlist
);
191 perf_thread_map__put(threads
);
195 static int test_mmap_thread(void)
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
,
205 .wakeup_watermark
= 1,
209 int id
, err
, pid
, go_pipe
[2];
210 union perf_event
*event
;
214 snprintf(path
, PATH_MAX
, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
215 sysfs__mountpoint());
217 if (filename__read_int(path
, &id
)) {
218 fprintf(stderr
, "error: failed to get tracepoint id: %s\n", path
);
225 __T("failed to create pipe", err
== 0);
233 read(go_pipe
[0], &bf
, 1);
235 /* Generate 100 prctl calls. */
236 for (i
= 0; i
< 100; i
++)
237 prctl(0, 0, 0, 0, 0);
242 threads
= perf_thread_map__new_dummy();
243 __T("failed to create threads", threads
);
245 cpus
= perf_cpu_map__dummy_new();
246 __T("failed to create cpus", cpus
);
248 perf_thread_map__set_pid(threads
, 0, pid
);
250 evlist
= perf_evlist__new();
251 __T("failed to create evlist", evlist
);
253 evsel
= perf_evsel__new(&attr
);
254 __T("failed to create evsel1", evsel
);
256 perf_evlist__add(evlist
, evsel
);
258 perf_evlist__set_maps(evlist
, cpus
, threads
);
260 err
= perf_evlist__open(evlist
);
261 __T("failed to open evlist", err
== 0);
263 err
= perf_evlist__mmap(evlist
, 4);
264 __T("failed to mmap evlist", err
== 0);
266 perf_evlist__enable(evlist
);
268 /* kick the child and wait for it to finish */
269 write(go_pipe
[1], &bf
, 1);
270 waitpid(pid
, NULL
, 0);
273 * There's no need to call perf_evlist__disable,
274 * monitored process is dead now.
277 perf_evlist__for_each_mmap(evlist
, map
, false) {
278 if (perf_mmap__read_init(map
) < 0)
281 while ((event
= perf_mmap__read_event(map
)) != NULL
) {
283 perf_mmap__consume(map
);
286 perf_mmap__read_done(map
);
289 /* calls perf_evlist__munmap/perf_evlist__close */
290 perf_evlist__delete(evlist
);
292 perf_thread_map__put(threads
);
293 perf_cpu_map__put(cpus
);
296 * The generated prctl calls should match the
297 * number of events in the buffer.
299 __T("failed count", count
== 100);
304 static int test_mmap_cpus(void)
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
,
313 .wakeup_watermark
= 1,
316 cpu_set_t saved_mask
;
318 int id
, err
, cpu
, tmp
;
319 union perf_event
*event
;
322 snprintf(path
, PATH_MAX
, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
323 sysfs__mountpoint());
325 if (filename__read_int(path
, &id
)) {
326 fprintf(stderr
, "error: failed to get tracepoint id: %s\n", path
);
332 cpus
= perf_cpu_map__new(NULL
);
333 __T("failed to create cpus", cpus
);
335 evlist
= perf_evlist__new();
336 __T("failed to create evlist", evlist
);
338 evsel
= perf_evsel__new(&attr
);
339 __T("failed to create evsel1", evsel
);
341 perf_evlist__add(evlist
, evsel
);
343 perf_evlist__set_maps(evlist
, cpus
, NULL
);
345 err
= perf_evlist__open(evlist
);
346 __T("failed to open evlist", err
== 0);
348 err
= perf_evlist__mmap(evlist
, 4);
349 __T("failed to mmap evlist", err
== 0);
351 perf_evlist__enable(evlist
);
353 err
= sched_getaffinity(0, sizeof(saved_mask
), &saved_mask
);
354 __T("sched_getaffinity failed", err
== 0);
356 perf_cpu_map__for_each_cpu(cpu
, tmp
, cpus
) {
362 err
= sched_setaffinity(0, sizeof(mask
), &mask
);
363 __T("sched_setaffinity failed", err
== 0);
365 prctl(0, 0, 0, 0, 0);
368 err
= sched_setaffinity(0, sizeof(saved_mask
), &saved_mask
);
369 __T("sched_setaffinity failed", err
== 0);
371 perf_evlist__disable(evlist
);
373 perf_evlist__for_each_mmap(evlist
, map
, false) {
374 if (perf_mmap__read_init(map
) < 0)
377 while ((event
= perf_mmap__read_event(map
)) != NULL
) {
379 perf_mmap__consume(map
);
382 perf_mmap__read_done(map
);
385 /* calls perf_evlist__munmap/perf_evlist__close */
386 perf_evlist__delete(evlist
);
389 * The generated prctl events should match the
390 * number of cpus or be bigger (we are system-wide).
392 __T("failed count", count
>= perf_cpu_map__nr(cpus
));
394 perf_cpu_map__put(cpus
);
399 int main(int argc
, char **argv
)
403 libperf_init(libperf_print
);
407 test_stat_thread_enable();