]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
d944c4ee | 2 | #include <linux/types.h> |
f2a39fe8 | 3 | #include <limits.h> |
395c3070 AH |
4 | #include <unistd.h> |
5 | #include <sys/prctl.h> | |
9c3516d1 | 6 | #include <perf/cpumap.h> |
453fa030 | 7 | #include <perf/evlist.h> |
7728fa0c | 8 | #include <perf/mmap.h> |
395c3070 | 9 | |
b4209025 | 10 | #include "debug.h" |
395c3070 AH |
11 | #include "parse-events.h" |
12 | #include "evlist.h" | |
13 | #include "evsel.h" | |
aeb00b1a | 14 | #include "record.h" |
395c3070 | 15 | #include "thread_map.h" |
395c3070 | 16 | #include "tests.h" |
e0fcfb08 | 17 | #include "util/mmap.h" |
395c3070 AH |
18 | |
19 | #define CHECK__(x) { \ | |
20 | while ((x) < 0) { \ | |
21 | pr_debug(#x " failed!\n"); \ | |
22 | goto out_err; \ | |
23 | } \ | |
24 | } | |
25 | ||
26 | #define CHECK_NOT_NULL__(x) { \ | |
27 | while ((x) == NULL) { \ | |
28 | pr_debug(#x " failed!\n"); \ | |
29 | goto out_err; \ | |
30 | } \ | |
31 | } | |
32 | ||
63503dba | 33 | static int find_comm(struct evlist *evlist, const char *comm) |
395c3070 AH |
34 | { |
35 | union perf_event *event; | |
a5830532 | 36 | struct mmap *md; |
395c3070 AH |
37 | int i, found; |
38 | ||
39 | found = 0; | |
c976ee11 | 40 | for (i = 0; i < evlist->core.nr_mmaps; i++) { |
693d32ae | 41 | md = &evlist->mmap[i]; |
7c4d4182 | 42 | if (perf_mmap__read_init(&md->core) < 0) |
693d32ae | 43 | continue; |
151ed5d7 | 44 | while ((event = perf_mmap__read_event(&md->core)) != NULL) { |
395c3070 AH |
45 | if (event->header.type == PERF_RECORD_COMM && |
46 | (pid_t)event->comm.pid == getpid() && | |
47 | (pid_t)event->comm.tid == getpid() && | |
48 | strcmp(event->comm.comm, comm) == 0) | |
49 | found += 1; | |
7728fa0c | 50 | perf_mmap__consume(&md->core); |
395c3070 | 51 | } |
32fdc2ca | 52 | perf_mmap__read_done(&md->core); |
395c3070 AH |
53 | } |
54 | return found; | |
55 | } | |
56 | ||
57 | /** | |
58 | * test__keep_tracking - test using a dummy software event to keep tracking. | |
59 | * | |
60 | * This function implements a test that checks that tracking events continue | |
61 | * when an event is disabled but a dummy software event is not disabled. If the | |
62 | * test passes %0 is returned, otherwise %-1 is returned. | |
63 | */ | |
81f17c90 | 64 | int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_unused) |
395c3070 | 65 | { |
b4006796 | 66 | struct record_opts opts = { |
395c3070 AH |
67 | .mmap_pages = UINT_MAX, |
68 | .user_freq = UINT_MAX, | |
69 | .user_interval = ULLONG_MAX, | |
395c3070 AH |
70 | .target = { |
71 | .uses_mmap = true, | |
72 | }, | |
73 | }; | |
9749b90e | 74 | struct perf_thread_map *threads = NULL; |
f854839b | 75 | struct perf_cpu_map *cpus = NULL; |
63503dba | 76 | struct evlist *evlist = NULL; |
32dcd021 | 77 | struct evsel *evsel = NULL; |
395c3070 AH |
78 | int found, err = -1; |
79 | const char *comm; | |
80 | ||
81 | threads = thread_map__new(-1, getpid(), UINT_MAX); | |
82 | CHECK_NOT_NULL__(threads); | |
83 | ||
9c3516d1 | 84 | cpus = perf_cpu_map__new(NULL); |
395c3070 AH |
85 | CHECK_NOT_NULL__(cpus); |
86 | ||
0f98b11c | 87 | evlist = evlist__new(); |
395c3070 AH |
88 | CHECK_NOT_NULL__(evlist); |
89 | ||
453fa030 | 90 | perf_evlist__set_maps(&evlist->core, cpus, threads); |
395c3070 | 91 | |
b39b8393 JO |
92 | CHECK__(parse_events(evlist, "dummy:u", NULL)); |
93 | CHECK__(parse_events(evlist, "cycles:u", NULL)); | |
395c3070 | 94 | |
78e1bc25 | 95 | evlist__config(evlist, &opts, NULL); |
395c3070 | 96 | |
515dbe48 | 97 | evsel = evlist__first(evlist); |
395c3070 | 98 | |
1fc632ce JO |
99 | evsel->core.attr.comm = 1; |
100 | evsel->core.attr.disabled = 1; | |
101 | evsel->core.attr.enable_on_exec = 0; | |
395c3070 | 102 | |
474ddc4c | 103 | if (evlist__open(evlist) < 0) { |
597bdeb4 WN |
104 | pr_debug("Unable to open dummy and cycles event\n"); |
105 | err = TEST_SKIP; | |
395c3070 AH |
106 | goto out_err; |
107 | } | |
108 | ||
9521b5f2 | 109 | CHECK__(evlist__mmap(evlist, UINT_MAX)); |
395c3070 AH |
110 | |
111 | /* | |
112 | * First, test that a 'comm' event can be found when the event is | |
113 | * enabled. | |
114 | */ | |
115 | ||
1c87f165 | 116 | evlist__enable(evlist); |
395c3070 AH |
117 | |
118 | comm = "Test COMM 1"; | |
119 | CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); | |
120 | ||
e74676de | 121 | evlist__disable(evlist); |
395c3070 AH |
122 | |
123 | found = find_comm(evlist, comm); | |
124 | if (found != 1) { | |
125 | pr_debug("First time, failed to find tracking event.\n"); | |
126 | goto out_err; | |
127 | } | |
128 | ||
129 | /* | |
130 | * Secondly, test that a 'comm' event can be found when the event is | |
131 | * disabled with the dummy event still enabled. | |
132 | */ | |
133 | ||
1c87f165 | 134 | evlist__enable(evlist); |
395c3070 | 135 | |
515dbe48 | 136 | evsel = evlist__last(evlist); |
395c3070 | 137 | |
9a10bb22 | 138 | CHECK__(evsel__disable(evsel)); |
395c3070 AH |
139 | |
140 | comm = "Test COMM 2"; | |
141 | CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); | |
142 | ||
e74676de | 143 | evlist__disable(evlist); |
395c3070 AH |
144 | |
145 | found = find_comm(evlist, comm); | |
146 | if (found != 1) { | |
87ffb6c6 | 147 | pr_debug("Second time, failed to find tracking event.\n"); |
395c3070 AH |
148 | goto out_err; |
149 | } | |
150 | ||
151 | err = 0; | |
152 | ||
153 | out_err: | |
154 | if (evlist) { | |
e74676de | 155 | evlist__disable(evlist); |
c12995a5 | 156 | evlist__delete(evlist); |
03ad9747 | 157 | } |
f2c3202b NK |
158 | perf_cpu_map__put(cpus); |
159 | perf_thread_map__put(threads); | |
395c3070 AH |
160 | |
161 | return err; | |
162 | } |