1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/types.h>
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <unistd.h>
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/prctl.h>
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "parse-events.h"
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "evlist.h"
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "evsel.h"
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread_map.h"
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "cpumap.h"
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "tests.h"
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define CHECK__(x) {				\
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while ((x) < 0) {			\
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug(#x " failed!\n");	\
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;			\
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}					\
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define CHECK_NOT_NULL__(x) {			\
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while ((x) == NULL) {			\
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug(#x " failed!\n");	\
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;			\
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}					\
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int find_comm(struct perf_evlist *evlist, const char *comm)
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	union perf_event *event;
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i, found;
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	found = 0;
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < evlist->nr_mmaps; i++) {
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (event->header.type == PERF_RECORD_COMM &&
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    (pid_t)event->comm.pid == getpid() &&
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    (pid_t)event->comm.tid == getpid() &&
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    strcmp(event->comm.comm, comm) == 0)
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				found += 1;
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			perf_evlist__mmap_consume(evlist, i);
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return found;
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/**
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * test__keep_tracking - test using a dummy software event to keep tracking.
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * This function implements a test that checks that tracking events continue
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * when an event is disabled but a dummy software event is not disabled.  If the
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * test passes %0 is returned, otherwise %-1 is returned.
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint test__keep_tracking(void)
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_record_opts opts = {
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.mmap_pages	     = UINT_MAX,
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.user_freq	     = UINT_MAX,
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.user_interval	     = ULLONG_MAX,
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.freq		     = 4000,
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.target		     = {
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			.uses_mmap   = true,
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		},
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct thread_map *threads = NULL;
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct cpu_map *cpus = NULL;
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evlist *evlist = NULL;
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evsel *evsel = NULL;
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int found, err = -1;
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *comm;
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	threads = thread_map__new(-1, getpid(), UINT_MAX);
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK_NOT_NULL__(threads);
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	cpus = cpu_map__new(NULL);
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK_NOT_NULL__(cpus);
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	evlist = perf_evlist__new();
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK_NOT_NULL__(evlist);
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__set_maps(evlist, cpus, threads);
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK__(parse_events(evlist, "dummy:u"));
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK__(parse_events(evlist, "cycles:u"));
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__config(evlist, &opts);
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	evsel = perf_evlist__first(evlist);
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	evsel->attr.comm = 1;
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	evsel->attr.disabled = 1;
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	evsel->attr.enable_on_exec = 0;
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (perf_evlist__open(evlist) < 0) {
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stderr, " (not supported)");
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		err = 0;
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK__(perf_evlist__mmap(evlist, UINT_MAX, false));
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/*
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * First, test that a 'comm' event can be found when the event is
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * enabled.
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 */
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__enable(evlist);
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	comm = "Test COMM 1";
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__disable(evlist);
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	found = find_comm(evlist, comm);
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (found != 1) {
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("First time, failed to find tracking event.\n");
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/*
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * Secondly, test that a 'comm' event can be found when the event is
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * disabled with the dummy event still enabled.
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 */
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__enable(evlist);
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	evsel = perf_evlist__last(evlist);
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK__(perf_evlist__disable_event(evlist, evsel));
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	comm = "Test COMM 2";
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__disable(evlist);
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	found = find_comm(evlist, comm);
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (found != 1) {
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("Seconf time, failed to find tracking event.\n");
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	err = 0;
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_err:
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (evlist) {
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__disable(evlist);
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__munmap(evlist);
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__close(evlist);
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__delete(evlist);
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (cpus)
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		cpu_map__delete(cpus);
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (threads)
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		thread_map__delete(threads);
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return err;
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
156