1 // SPDX-License-Identifier: GPL-2.0
4 /* For the CPU_* macros */
10 #include <api/fs/fs.h>
11 #include <linux/err.h>
12 #include <linux/string.h>
13 #include <api/fs/tracing_path.h>
16 #include "thread_map.h"
17 #include <perf/cpumap.h>
20 #include "util/counts.h"
22 static int test__openat_syscall_event_on_all_cpus(struct test_suite
*test __maybe_unused
,
23 int subtest __maybe_unused
)
25 int err
= TEST_FAIL
, fd
, idx
;
27 struct perf_cpu_map
*cpus
;
29 unsigned int nr_openat_calls
= 111, i
;
31 struct perf_thread_map
*threads
= thread_map__new(-1, getpid(), UINT_MAX
);
32 char sbuf
[STRERR_BUFSIZE
];
35 if (threads
== NULL
) {
36 pr_debug("thread_map__new\n");
40 cpus
= perf_cpu_map__new_online_cpus();
42 pr_debug("perf_cpu_map__new\n");
43 goto out_thread_map_delete
;
48 evsel
= evsel__newtp("syscalls", "sys_enter_openat");
50 tracing_path__strerror_open_tp(errno
, errbuf
, sizeof(errbuf
), "syscalls", "sys_enter_openat");
51 pr_debug("%s\n", errbuf
);
53 goto out_cpu_map_delete
;
56 if (evsel__open(evsel
, cpus
, threads
) < 0) {
57 pr_debug("failed to open counter: %s, "
58 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
59 str_error_r(errno
, sbuf
, sizeof(sbuf
)));
61 goto out_evsel_delete
;
64 perf_cpu_map__for_each_cpu(cpu
, idx
, cpus
) {
65 unsigned int ncalls
= nr_openat_calls
+ idx
;
67 * XXX eventually lift this restriction in a way that
68 * keeps perf building on older glibc installations
69 * without CPU_ALLOC. 1024 cpus in 2010 still seems
70 * a reasonable upper limit tho :-)
72 if (cpu
.cpu
>= CPU_SETSIZE
) {
73 pr_debug("Ignoring CPU %d\n", cpu
.cpu
);
77 CPU_SET(cpu
.cpu
, &cpu_set
);
78 if (sched_setaffinity(0, sizeof(cpu_set
), &cpu_set
) < 0) {
79 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
81 str_error_r(errno
, sbuf
, sizeof(sbuf
)));
84 for (i
= 0; i
< ncalls
; ++i
) {
85 fd
= openat(0, "/etc/passwd", O_RDONLY
);
88 CPU_CLR(cpu
.cpu
, &cpu_set
);
91 evsel
->core
.cpus
= perf_cpu_map__get(cpus
);
95 perf_cpu_map__for_each_cpu(cpu
, idx
, cpus
) {
96 unsigned int expected
;
98 if (cpu
.cpu
>= CPU_SETSIZE
)
101 if (evsel__read_on_cpu(evsel
, idx
, 0) < 0) {
102 pr_debug("evsel__read_on_cpu\n");
107 expected
= nr_openat_calls
+ idx
;
108 if (perf_counts(evsel
->counts
, idx
, 0)->val
!= expected
) {
109 pr_debug("evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64
"\n",
110 expected
, cpu
.cpu
, perf_counts(evsel
->counts
, idx
, 0)->val
);
115 evsel__free_counts(evsel
);
117 perf_evsel__close_fd(&evsel
->core
);
119 evsel__delete(evsel
);
121 perf_cpu_map__put(cpus
);
122 out_thread_map_delete
:
123 perf_thread_map__put(threads
);
128 static struct test_case tests__openat_syscall_event_on_all_cpus
[] = {
129 TEST_CASE_REASON("Detect openat syscall event on all cpus",
130 openat_syscall_event_on_all_cpus
,
135 struct test_suite suite__openat_syscall_event_on_all_cpus
= {
136 .desc
= "Detect openat syscall event on all cpus",
137 .test_cases
= tests__openat_syscall_event_on_all_cpus
,