Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  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
 24static int libperf_print(enum libperf_print_level level,
 25			 const char *fmt, va_list ap)
 26{
 27	return vfprintf(stderr, fmt, ap);
 28}
 29
 30static 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, idx;
 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		for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
 74			struct perf_counts_values counts = { .val = 0 };
 75
 76			perf_evsel__read(evsel, idx, 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
 88static 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
143static 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
209static 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
320static 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
416int 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}