]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - tools/perf/util/record.c
perf evsel: Ditch perf_evsel__cmp(), not used for quite a while
[mirror_ubuntu-jammy-kernel.git] / tools / perf / util / record.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
b4209025 2#include "debug.h"
faf96706
AH
3#include "evlist.h"
4#include "evsel.h"
75562573 5#include "parse-events.h"
a43783ae 6#include <errno.h>
f2a39fe8
ACM
7#include <limits.h>
8#include <stdlib.h>
cd0cfad7 9#include <api/fs/fs.h>
67230479 10#include <subcmd/parse-options.h>
9c3516d1 11#include <perf/cpumap.h>
57480d2c 12#include "cloexec.h"
40c7d246 13#include "util/perf_api_probe.h"
aeb00b1a 14#include "record.h"
91854f9a 15#include "../perf-sys.h"
75562573 16
e3459979 17/*
6ec17b4e 18 * evsel__config_leader_sampling() uses special rules for leader sampling.
e3459979
AH
19 * However, if the leader is an AUX area event, then assume the event to sample
20 * is the next event.
21 */
22static struct evsel *perf_evsel__read_sampler(struct evsel *evsel,
23 struct evlist *evlist)
24{
25 struct evsel *leader = evsel->leader;
26
39453ed5 27 if (evsel__is_aux_event(leader)) {
e3459979
AH
28 evlist__for_each_entry(evlist, evsel) {
29 if (evsel->leader == leader && evsel != evsel->leader)
30 return evsel;
31 }
32 }
33
34 return leader;
35}
36
6ec17b4e 37static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *evlist)
5f342788
AH
38{
39 struct perf_event_attr *attr = &evsel->core.attr;
40 struct evsel *leader = evsel->leader;
e3459979
AH
41 struct evsel *read_sampler;
42
43 if (!leader->sample_read)
44 return;
45
46 read_sampler = perf_evsel__read_sampler(evsel, evlist);
5f342788 47
e3459979 48 if (evsel == read_sampler)
3713eb37
AH
49 return;
50
5f342788 51 /*
e3459979
AH
52 * Disable sampling for all group members other than the leader in
53 * case the leader 'leads' the sampling, except when the leader is an
54 * AUX area event, in which case the 2nd event in the group is the one
55 * that 'leads' the sampling.
5f342788 56 */
3713eb37
AH
57 attr->freq = 0;
58 attr->sample_freq = 0;
59 attr->sample_period = 0;
60 attr->write_backward = 0;
5f342788 61
3713eb37
AH
62 /*
63 * We don't get a sample for slave events, we make them when delivering
64 * the group leader sample. Set the slave event to follow the master
65 * sample_type to ease up reporting.
e3459979
AH
66 * An AUX area event also has sample_type requirements, so also include
67 * the sample type bits from the leader's sample_type to cover that
68 * case.
3713eb37 69 */
e3459979
AH
70 attr->sample_type = read_sampler->core.attr.sample_type |
71 leader->core.attr.sample_type;
5f342788
AH
72}
73
63503dba 74void perf_evlist__config(struct evlist *evlist, struct record_opts *opts,
e68ae9cf 75 struct callchain_param *callchain)
faf96706 76{
32dcd021 77 struct evsel *evsel;
75562573 78 bool use_sample_identifier = false;
39e09d40 79 bool use_comm_exec;
ad46e48c 80 bool sample_id = opts->sample_id;
75562573 81
faf96706
AH
82 /*
83 * Set the evsel leader links before we configure attributes,
84 * since some might depend on this info.
85 */
86 if (opts->group)
87 perf_evlist__set_leader(evlist);
88
f72f901d 89 if (evlist->core.cpus->map[0] < 0)
faf96706
AH
90 opts->no_inherit = true;
91
39e09d40
AH
92 use_comm_exec = perf_can_comm_exec();
93
e5cadb93 94 evlist__for_each_entry(evlist, evsel) {
6ec17b4e 95 evsel__config(evsel, opts, callchain);
60b0896c 96 if (evsel->tracking && use_comm_exec)
1fc632ce 97 evsel->core.attr.comm_exec = 1;
39e09d40 98 }
faf96706 99
5f342788
AH
100 /* Configure leader sampling here now that the sample type is known */
101 evlist__for_each_entry(evlist, evsel)
6ec17b4e 102 evsel__config_leader_sampling(evsel, evlist);
5f342788 103
9e0cc4fe
AH
104 if (opts->full_auxtrace) {
105 /*
106 * Need to be able to synthesize and parse selected events with
107 * arbitrary sample types, which requires always being able to
108 * match the id.
109 */
110 use_sample_identifier = perf_can_sample_identifier();
ad46e48c 111 sample_id = true;
6484d2f9 112 } else if (evlist->core.nr_entries > 1) {
515dbe48 113 struct evsel *first = evlist__first(evlist);
75562573 114
e5cadb93 115 evlist__for_each_entry(evlist, evsel) {
1fc632ce 116 if (evsel->core.attr.sample_type == first->core.attr.sample_type)
75562573
AH
117 continue;
118 use_sample_identifier = perf_can_sample_identifier();
119 break;
120 }
ad46e48c
JO
121 sample_id = true;
122 }
123
124 if (sample_id) {
e5cadb93 125 evlist__for_each_entry(evlist, evsel)
862b2f8f 126 evsel__set_sample_id(evsel, use_sample_identifier);
faf96706 127 }
75562573
AH
128
129 perf_evlist__set_id_pos(evlist);
faf96706 130}
714647bd
JO
131
132static int get_max_rate(unsigned int *rate)
133{
ce27309f 134 return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate);
714647bd
JO
135}
136
b4006796 137static int record_opts__config_freq(struct record_opts *opts)
714647bd
JO
138{
139 bool user_freq = opts->user_freq != UINT_MAX;
140 unsigned int max_rate;
141
142 if (opts->user_interval != ULLONG_MAX)
143 opts->default_interval = opts->user_interval;
144 if (user_freq)
145 opts->freq = opts->user_freq;
146
147 /*
148 * User specified count overrides default frequency.
149 */
150 if (opts->default_interval)
151 opts->freq = 0;
152 else if (opts->freq) {
153 opts->default_interval = opts->freq;
154 } else {
155 pr_err("frequency and count are zero, aborting\n");
156 return -1;
157 }
158
159 if (get_max_rate(&max_rate))
160 return 0;
161
162 /*
163 * User specified frequency is over current maximum.
164 */
165 if (user_freq && (max_rate < opts->freq)) {
b09c2364
ACM
166 if (opts->strict_freq) {
167 pr_err("error: Maximum frequency rate (%'u Hz) exceeded.\n"
168 " Please use -F freq option with a lower value or consider\n"
169 " tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
170 max_rate);
171 return -1;
172 } else {
173 pr_warning("warning: Maximum frequency rate (%'u Hz) exceeded, throttling from %'u Hz to %'u Hz.\n"
174 " The limit can be raised via /proc/sys/kernel/perf_event_max_sample_rate.\n"
175 " The kernel will lower it when perf's interrupts take too long.\n"
176 " Use --strict-freq to disable this throttling, refusing to record.\n",
177 max_rate, opts->freq, max_rate);
178
179 opts->freq = max_rate;
180 }
714647bd
JO
181 }
182
183 /*
184 * Default frequency is over current maximum.
185 */
186 if (max_rate < opts->freq) {
187 pr_warning("Lowering default frequency rate to %u.\n"
188 "Please consider tweaking "
189 "/proc/sys/kernel/perf_event_max_sample_rate.\n",
190 max_rate);
191 opts->freq = max_rate;
192 }
193
194 return 0;
195}
196
b4006796 197int record_opts__config(struct record_opts *opts)
714647bd 198{
b4006796 199 return record_opts__config_freq(opts);
714647bd 200}
c09ec622 201
63503dba 202bool perf_evlist__can_select_event(struct evlist *evlist, const char *str)
c09ec622 203{
63503dba 204 struct evlist *temp_evlist;
32dcd021 205 struct evsel *evsel;
c09ec622
AH
206 int err, fd, cpu;
207 bool ret = false;
46ec69ad 208 pid_t pid = -1;
c09ec622 209
0f98b11c 210 temp_evlist = evlist__new();
c09ec622
AH
211 if (!temp_evlist)
212 return false;
213
b39b8393 214 err = parse_events(temp_evlist, str, NULL);
c09ec622
AH
215 if (err)
216 goto out_delete;
217
515dbe48 218 evsel = evlist__last(temp_evlist);
c09ec622 219
315c0a1f 220 if (!evlist || perf_cpu_map__empty(evlist->core.cpus)) {
9c3516d1 221 struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
c09ec622
AH
222
223 cpu = cpus ? cpus->map[0] : 0;
38f01d8d 224 perf_cpu_map__put(cpus);
c09ec622 225 } else {
f72f901d 226 cpu = evlist->core.cpus->map[0];
c09ec622
AH
227 }
228
46ec69ad 229 while (1) {
1fc632ce 230 fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1,
46ec69ad
AH
231 perf_event_open_cloexec_flag());
232 if (fd < 0) {
233 if (pid == -1 && errno == EACCES) {
234 pid = 0;
235 continue;
236 }
237 goto out_delete;
238 }
239 break;
c09ec622 240 }
46ec69ad
AH
241 close(fd);
242 ret = true;
c09ec622
AH
243
244out_delete:
c12995a5 245 evlist__delete(temp_evlist);
c09ec622
AH
246 return ret;
247}
67230479
ACM
248
249int record__parse_freq(const struct option *opt, const char *str, int unset __maybe_unused)
250{
251 unsigned int freq;
252 struct record_opts *opts = opt->value;
253
254 if (!str)
255 return -EINVAL;
256
257 if (strcasecmp(str, "max") == 0) {
258 if (get_max_rate(&freq)) {
259 pr_err("couldn't read /proc/sys/kernel/perf_event_max_sample_rate\n");
260 return -1;
261 }
262 pr_info("info: Using a maximum frequency rate of %'d Hz\n", freq);
263 } else {
264 freq = atoi(str);
265 }
266
267 opts->user_freq = freq;
268 return 0;
269}