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
 22static int libperf_print(enum libperf_print_level level,
 23			 const char *fmt, va_list ap)
 24{
 25	return vfprintf(stderr, fmt, ap);
 26}
 27
 28static 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
 82static 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
133static 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
195static 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	char bf;
212	int count = 0;
213
214	snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
215		 sysfs__mountpoint());
216
217	if (filename__read_int(path, &id)) {
218		fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
219		return -1;
220	}
221
222	attr.config = id;
223
224	err = pipe(go_pipe);
225	__T("failed to create pipe", err == 0);
226
227	fflush(NULL);
228
229	pid = fork();
230	if (!pid) {
231		int i;
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], &bf, 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
304static 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
399int 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}