|
30 | 30 | #include <sched.h> |
31 | 31 |
|
32 | 32 |
|
33 | | -/* |
34 | | - * This test will generate random numbers of calls to some getpid syscalls, |
35 | | - * then establish an mmap for a group of events that are created to monitor |
36 | | - * the syscalls. |
37 | | - * |
38 | | - * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated |
39 | | - * sample.id field to map back to its respective perf_evsel instance. |
40 | | - * |
41 | | - * Then it checks if the number of syscalls reported as perf events by |
42 | | - * the kernel corresponds to the number of syscalls made. |
43 | | - */ |
44 | | -static int test__basic_mmap(void) |
45 | | -{ |
46 | | - int err = -1; |
47 | | - union perf_event *event; |
48 | | - struct thread_map *threads; |
49 | | - struct cpu_map *cpus; |
50 | | - struct perf_evlist *evlist; |
51 | | - struct perf_event_attr attr = { |
52 | | - .type = PERF_TYPE_TRACEPOINT, |
53 | | - .read_format = PERF_FORMAT_ID, |
54 | | - .sample_type = PERF_SAMPLE_ID, |
55 | | - .watermark = 0, |
56 | | - }; |
57 | | - cpu_set_t cpu_set; |
58 | | - const char *syscall_names[] = { "getsid", "getppid", "getpgrp", |
59 | | - "getpgid", }; |
60 | | - pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp, |
61 | | - (void*)getpgid }; |
62 | | -#define nsyscalls ARRAY_SIZE(syscall_names) |
63 | | - int ids[nsyscalls]; |
64 | | - unsigned int nr_events[nsyscalls], |
65 | | - expected_nr_events[nsyscalls], i, j; |
66 | | - struct perf_evsel *evsels[nsyscalls], *evsel; |
67 | | - |
68 | | - for (i = 0; i < nsyscalls; ++i) { |
69 | | - char name[64]; |
70 | | - |
71 | | - snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); |
72 | | - ids[i] = trace_event__id(name); |
73 | | - if (ids[i] < 0) { |
74 | | - pr_debug("Is debugfs mounted on /sys/kernel/debug?\n"); |
75 | | - return -1; |
76 | | - } |
77 | | - nr_events[i] = 0; |
78 | | - expected_nr_events[i] = random() % 257; |
79 | | - } |
80 | | - |
81 | | - threads = thread_map__new(-1, getpid(), UINT_MAX); |
82 | | - if (threads == NULL) { |
83 | | - pr_debug("thread_map__new\n"); |
84 | | - return -1; |
85 | | - } |
86 | | - |
87 | | - cpus = cpu_map__new(NULL); |
88 | | - if (cpus == NULL) { |
89 | | - pr_debug("cpu_map__new\n"); |
90 | | - goto out_free_threads; |
91 | | - } |
92 | | - |
93 | | - CPU_ZERO(&cpu_set); |
94 | | - CPU_SET(cpus->map[0], &cpu_set); |
95 | | - sched_setaffinity(0, sizeof(cpu_set), &cpu_set); |
96 | | - if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { |
97 | | - pr_debug("sched_setaffinity() failed on CPU %d: %s ", |
98 | | - cpus->map[0], strerror(errno)); |
99 | | - goto out_free_cpus; |
100 | | - } |
101 | | - |
102 | | - evlist = perf_evlist__new(cpus, threads); |
103 | | - if (evlist == NULL) { |
104 | | - pr_debug("perf_evlist__new\n"); |
105 | | - goto out_free_cpus; |
106 | | - } |
107 | | - |
108 | | - /* anonymous union fields, can't be initialized above */ |
109 | | - attr.wakeup_events = 1; |
110 | | - attr.sample_period = 1; |
111 | | - |
112 | | - for (i = 0; i < nsyscalls; ++i) { |
113 | | - attr.config = ids[i]; |
114 | | - evsels[i] = perf_evsel__new(&attr, i); |
115 | | - if (evsels[i] == NULL) { |
116 | | - pr_debug("perf_evsel__new\n"); |
117 | | - goto out_free_evlist; |
118 | | - } |
119 | | - |
120 | | - perf_evlist__add(evlist, evsels[i]); |
121 | | - |
122 | | - if (perf_evsel__open(evsels[i], cpus, threads) < 0) { |
123 | | - pr_debug("failed to open counter: %s, " |
124 | | - "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
125 | | - strerror(errno)); |
126 | | - goto out_close_fd; |
127 | | - } |
128 | | - } |
129 | | - |
130 | | - if (perf_evlist__mmap(evlist, 128, true) < 0) { |
131 | | - pr_debug("failed to mmap events: %d (%s)\n", errno, |
132 | | - strerror(errno)); |
133 | | - goto out_close_fd; |
134 | | - } |
135 | | - |
136 | | - for (i = 0; i < nsyscalls; ++i) |
137 | | - for (j = 0; j < expected_nr_events[i]; ++j) { |
138 | | - int foo = syscalls[i](); |
139 | | - ++foo; |
140 | | - } |
141 | | - |
142 | | - while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { |
143 | | - struct perf_sample sample; |
144 | | - |
145 | | - if (event->header.type != PERF_RECORD_SAMPLE) { |
146 | | - pr_debug("unexpected %s event\n", |
147 | | - perf_event__name(event->header.type)); |
148 | | - goto out_munmap; |
149 | | - } |
150 | | - |
151 | | - err = perf_evlist__parse_sample(evlist, event, &sample); |
152 | | - if (err) { |
153 | | - pr_err("Can't parse sample, err = %d\n", err); |
154 | | - goto out_munmap; |
155 | | - } |
156 | | - |
157 | | - evsel = perf_evlist__id2evsel(evlist, sample.id); |
158 | | - if (evsel == NULL) { |
159 | | - pr_debug("event with id %" PRIu64 |
160 | | - " doesn't map to an evsel\n", sample.id); |
161 | | - goto out_munmap; |
162 | | - } |
163 | | - nr_events[evsel->idx]++; |
164 | | - } |
165 | | - |
166 | | - list_for_each_entry(evsel, &evlist->entries, node) { |
167 | | - if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { |
168 | | - pr_debug("expected %d %s events, got %d\n", |
169 | | - expected_nr_events[evsel->idx], |
170 | | - perf_evsel__name(evsel), nr_events[evsel->idx]); |
171 | | - goto out_munmap; |
172 | | - } |
173 | | - } |
174 | | - |
175 | | - err = 0; |
176 | | -out_munmap: |
177 | | - perf_evlist__munmap(evlist); |
178 | | -out_close_fd: |
179 | | - for (i = 0; i < nsyscalls; ++i) |
180 | | - perf_evsel__close_fd(evsels[i], 1, threads->nr); |
181 | | -out_free_evlist: |
182 | | - perf_evlist__delete(evlist); |
183 | | -out_free_cpus: |
184 | | - cpu_map__delete(cpus); |
185 | | -out_free_threads: |
186 | | - thread_map__delete(threads); |
187 | | - return err; |
188 | | -#undef nsyscalls |
189 | | -} |
190 | 33 |
|
191 | 34 | static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) |
192 | 35 | { |
|
0 commit comments