perf tools: Add fprintf methods for thread_map and cpu_map classes
[linux-2.6-block.git] / tools / perf / builtin-record.c
CommitLineData
abaff32a 1/*
bf9e1876
IM
2 * builtin-record.c
3 *
4 * Builtin record command: Record the profile of a workload
5 * (or a CPU, or a PID) into the perf.data output file - for
6 * later analysis via perf report.
abaff32a 7 */
b8f46c5a
XG
8#define _FILE_OFFSET_BITS 64
9
16f762a2 10#include "builtin.h"
bf9e1876
IM
11
12#include "perf.h"
13
6122e4e4 14#include "util/build-id.h"
6eda5838 15#include "util/util.h"
0e9b20b8 16#include "util/parse-options.h"
8ad8db37 17#include "util/parse-events.h"
6eda5838 18
7c6a1c65 19#include "util/header.h"
66e274f3 20#include "util/event.h"
361c99a6 21#include "util/evlist.h"
69aad6f1 22#include "util/evsel.h"
8f28827a 23#include "util/debug.h"
94c744b6 24#include "util/session.h"
45694aa7 25#include "util/tool.h"
8d06367f 26#include "util/symbol.h"
a12b51c4 27#include "util/cpumap.h"
fd78260b 28#include "util/thread_map.h"
7c6a1c65 29
97124d5e 30#include <unistd.h>
de9ac07b 31#include <sched.h>
a41794cd 32#include <sys/mman.h>
de9ac07b 33
7865e817
FW
34enum write_mode_t {
35 WRITE_FORCE,
36 WRITE_APPEND
37};
38
d20deb64 39struct perf_record {
45694aa7 40 struct perf_tool tool;
d20deb64
ACM
41 struct perf_record_opts opts;
42 u64 bytes_written;
43 const char *output_name;
44 struct perf_evlist *evlist;
45 struct perf_session *session;
46 const char *progname;
47 int output;
48 unsigned int page_size;
49 int realtime_prio;
50 enum write_mode_t write_mode;
51 bool no_buildid;
52 bool no_buildid_cache;
53 bool force;
54 bool file_new;
55 bool append_file;
56 long samples;
57 off_t post_processing_offset;
0f82ebc4 58};
a21ca2ca 59
d20deb64 60static void advance_output(struct perf_record *rec, size_t size)
9215545e 61{
d20deb64 62 rec->bytes_written += size;
9215545e
TZ
63}
64
d20deb64 65static void write_output(struct perf_record *rec, void *buf, size_t size)
f5970550
PZ
66{
67 while (size) {
d20deb64 68 int ret = write(rec->output, buf, size);
f5970550
PZ
69
70 if (ret < 0)
71 die("failed to write");
72
73 size -= ret;
74 buf += ret;
75
d20deb64 76 rec->bytes_written += ret;
f5970550
PZ
77 }
78}
79
45694aa7 80static int process_synthesized_event(struct perf_tool *tool,
d20deb64 81 union perf_event *event,
8d50e5b4 82 struct perf_sample *sample __used,
743eb868 83 struct machine *machine __used)
234fbbf5 84{
45694aa7 85 struct perf_record *rec = container_of(tool, struct perf_record, tool);
d20deb64 86 write_output(rec, event, event->header.size);
234fbbf5
ACM
87 return 0;
88}
89
d20deb64
ACM
90static void perf_record__mmap_read(struct perf_record *rec,
91 struct perf_mmap *md)
de9ac07b 92{
744bd8aa 93 unsigned int head = perf_mmap__read_head(md);
de9ac07b 94 unsigned int old = md->prev;
d20deb64 95 unsigned char *data = md->base + rec->page_size;
de9ac07b
PZ
96 unsigned long size;
97 void *buf;
de9ac07b 98
dc82009a
ACM
99 if (old == head)
100 return;
101
d20deb64 102 rec->samples++;
de9ac07b
PZ
103
104 size = head - old;
105
106 if ((old & md->mask) + size != (head & md->mask)) {
107 buf = &data[old & md->mask];
108 size = md->mask + 1 - (old & md->mask);
109 old += size;
021e9f47 110
d20deb64 111 write_output(rec, buf, size);
de9ac07b
PZ
112 }
113
114 buf = &data[old & md->mask];
115 size = head - old;
116 old += size;
021e9f47 117
d20deb64 118 write_output(rec, buf, size);
de9ac07b
PZ
119
120 md->prev = old;
115d2d89 121 perf_mmap__write_tail(md, old);
de9ac07b
PZ
122}
123
124static volatile int done = 0;
f7b7c26e 125static volatile int signr = -1;
33e49ea7 126static volatile int child_finished = 0;
de9ac07b 127
16c8a109 128static void sig_handler(int sig)
de9ac07b 129{
33e49ea7
AK
130 if (sig == SIGCHLD)
131 child_finished = 1;
132
16c8a109 133 done = 1;
f7b7c26e
PZ
134 signr = sig;
135}
136
d20deb64 137static void perf_record__sig_exit(int exit_status __used, void *arg)
f7b7c26e 138{
d20deb64 139 struct perf_record *rec = arg;
33e49ea7
AK
140 int status;
141
d20deb64 142 if (rec->evlist->workload.pid > 0) {
33e49ea7 143 if (!child_finished)
d20deb64 144 kill(rec->evlist->workload.pid, SIGTERM);
33e49ea7
AK
145
146 wait(&status);
147 if (WIFSIGNALED(status))
d20deb64 148 psignal(WTERMSIG(status), rec->progname);
33e49ea7 149 }
933da83a 150
18483b81 151 if (signr == -1 || signr == SIGUSR1)
f7b7c26e
PZ
152 return;
153
154 signal(signr, SIG_DFL);
155 kill(getpid(), signr);
de9ac07b
PZ
156}
157
a91e5431
ACM
158static bool perf_evlist__equal(struct perf_evlist *evlist,
159 struct perf_evlist *other)
160{
161 struct perf_evsel *pos, *pair;
162
163 if (evlist->nr_entries != other->nr_entries)
164 return false;
165
166 pair = list_entry(other->entries.next, struct perf_evsel, node);
167
168 list_for_each_entry(pos, &evlist->entries, node) {
169 if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
170 return false;
171 pair = list_entry(pair->node.next, struct perf_evsel, node);
172 }
173
174 return true;
175}
176
d20deb64 177static void perf_record__open(struct perf_record *rec)
dd7927f4 178{
727ab04e 179 struct perf_evsel *pos, *first;
d20deb64
ACM
180 struct perf_evlist *evlist = rec->evlist;
181 struct perf_session *session = rec->session;
182 struct perf_record_opts *opts = &rec->opts;
dd7927f4 183
727ab04e
ACM
184 first = list_entry(evlist->entries.next, struct perf_evsel, node);
185
d20deb64 186 perf_evlist__config_attrs(evlist, opts);
0f82ebc4 187
dd7927f4
ACM
188 list_for_each_entry(pos, &evlist->entries, node) {
189 struct perf_event_attr *attr = &pos->attr;
727ab04e 190 struct xyarray *group_fd = NULL;
dd7927f4
ACM
191 /*
192 * Check if parse_single_tracepoint_event has already asked for
193 * PERF_SAMPLE_TIME.
194 *
195 * XXX this is kludgy but short term fix for problems introduced by
196 * eac23d1c that broke 'perf script' by having different sample_types
197 * when using multiple tracepoint events when we use a perf binary
198 * that tries to use sample_id_all on an older kernel.
199 *
200 * We need to move counter creation to perf_session, support
201 * different sample_types, etc.
202 */
203 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
d6d901c2 204
d20deb64 205 if (opts->group && pos != first)
727ab04e 206 group_fd = first->fd;
dd7927f4 207retry_sample_id:
d20deb64 208 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
dd7927f4 209try_again:
ed80f581 210 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
d20deb64 211 opts->group, group_fd) < 0) {
d6d901c2
ZY
212 int err = errno;
213
c286c419 214 if (err == EPERM || err == EACCES) {
b8631e6e 215 ui__error_paranoid();
c286c419 216 exit(EXIT_FAILURE);
d20deb64 217 } else if (err == ENODEV && opts->cpu_list) {
d6d901c2
ZY
218 die("No such device - did you specify"
219 " an out-of-range profile CPU?\n");
d20deb64 220 } else if (err == EINVAL && opts->sample_id_all_avail) {
9c90a61c
ACM
221 /*
222 * Old kernel, no attr->sample_id_type_all field
223 */
d20deb64
ACM
224 opts->sample_id_all_avail = false;
225 if (!opts->sample_time && !opts->raw_samples && !time_needed)
eac23d1c
IM
226 attr->sample_type &= ~PERF_SAMPLE_TIME;
227
9c90a61c 228 goto retry_sample_id;
d6d901c2 229 }
3da297a6 230
d6d901c2
ZY
231 /*
232 * If it's cycles then fall back to hrtimer
233 * based cpu-clock-tick sw counter, which
234 * is always available even if no PMU support:
235 */
236 if (attr->type == PERF_TYPE_HARDWARE
237 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
238
239 if (verbose)
ca6a4258
DA
240 ui__warning("The cycles event is not supported, "
241 "trying to fall back to cpu-clock-ticks\n");
d6d901c2
ZY
242 attr->type = PERF_TYPE_SOFTWARE;
243 attr->config = PERF_COUNT_SW_CPU_CLOCK;
244 goto try_again;
245 }
ca6a4258
DA
246
247 if (err == ENOENT) {
248 ui__warning("The %s event is not supported.\n",
249 event_name(pos));
250 exit(EXIT_FAILURE);
251 }
252
d6d901c2 253 printf("\n");
d9cf837e 254 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
dd7927f4 255 err, strerror(err));
bfd45118
SK
256
257#if defined(__i386__) || defined(__x86_64__)
d6d901c2
ZY
258 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
259 die("No hardware sampling interrupt available."
260 " No APIC? If so then you can boot the kernel"
261 " with the \"lapic\" boot parameter to"
262 " force-enable it.\n");
bfd45118
SK
263#endif
264
d6d901c2 265 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
c171b552
LZ
266 }
267 }
a43d3f08 268
0a102479
FW
269 if (perf_evlist__set_filters(evlist)) {
270 error("failed to set filter with %d (%s)\n", errno,
271 strerror(errno));
272 exit(-1);
273 }
274
18e60939
NE
275 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
276 if (errno == EPERM)
277 die("Permission error mapping pages.\n"
278 "Consider increasing "
279 "/proc/sys/kernel/perf_event_mlock_kb,\n"
280 "or try again with a smaller value of -m/--mmap_pages.\n"
281 "(current value: %d)\n", opts->mmap_pages);
41d0d933
NE
282 else if (!is_power_of_2(opts->mmap_pages))
283 die("--mmap_pages/-m value must be a power of two.");
284
0a27d7f9 285 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
18e60939 286 }
0a27d7f9 287
d20deb64 288 if (rec->file_new)
a91e5431
ACM
289 session->evlist = evlist;
290 else {
291 if (!perf_evlist__equal(session->evlist, evlist)) {
292 fprintf(stderr, "incompatible append\n");
293 exit(-1);
294 }
295 }
296
297 perf_session__update_sample_type(session);
16c8a109
PZ
298}
299
d20deb64 300static int process_buildids(struct perf_record *rec)
6122e4e4 301{
d20deb64 302 u64 size = lseek(rec->output, 0, SEEK_CUR);
6122e4e4 303
9f591fd7
ACM
304 if (size == 0)
305 return 0;
306
d20deb64
ACM
307 rec->session->fd = rec->output;
308 return __perf_session__process_events(rec->session, rec->post_processing_offset,
309 size - rec->post_processing_offset,
6122e4e4
ACM
310 size, &build_id__mark_dso_hit_ops);
311}
312
d20deb64 313static void perf_record__exit(int status __used, void *arg)
f5970550 314{
d20deb64
ACM
315 struct perf_record *rec = arg;
316
317 if (!rec->opts.pipe_output) {
318 rec->session->header.data_size += rec->bytes_written;
319
320 if (!rec->no_buildid)
321 process_buildids(rec);
322 perf_session__write_header(rec->session, rec->evlist,
323 rec->output, true);
324 perf_session__delete(rec->session);
325 perf_evlist__delete(rec->evlist);
d65a458b 326 symbol__exit();
c7929e47 327 }
f5970550
PZ
328}
329
8115d60c 330static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
a1645ce1
ZY
331{
332 int err;
45694aa7 333 struct perf_tool *tool = data;
a1645ce1 334
23346f21 335 if (machine__is_host(machine))
a1645ce1
ZY
336 return;
337
338 /*
339 *As for guest kernel when processing subcommand record&report,
340 *we arrange module mmap prior to guest kernel mmap and trigger
341 *a preload dso because default guest module symbols are loaded
342 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
343 *method is used to avoid symbol missing when the first addr is
344 *in module instead of in guest kernel.
345 */
45694aa7 346 err = perf_event__synthesize_modules(tool, process_synthesized_event,
743eb868 347 machine);
a1645ce1
ZY
348 if (err < 0)
349 pr_err("Couldn't record guest kernel [%d]'s reference"
23346f21 350 " relocation symbol.\n", machine->pid);
a1645ce1 351
a1645ce1
ZY
352 /*
353 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
354 * have no _text sometimes.
355 */
45694aa7 356 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
743eb868 357 machine, "_text");
a1645ce1 358 if (err < 0)
45694aa7 359 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
743eb868 360 machine, "_stext");
a1645ce1
ZY
361 if (err < 0)
362 pr_err("Couldn't record guest kernel [%d]'s reference"
23346f21 363 " relocation symbol.\n", machine->pid);
a1645ce1
ZY
364}
365
98402807
FW
366static struct perf_event_header finished_round_event = {
367 .size = sizeof(struct perf_event_header),
368 .type = PERF_RECORD_FINISHED_ROUND,
369};
370
d20deb64 371static void perf_record__mmap_read_all(struct perf_record *rec)
98402807 372{
0e2e63dd 373 int i;
98402807 374
d20deb64
ACM
375 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
376 if (rec->evlist->mmap[i].base)
377 perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
98402807
FW
378 }
379
d20deb64
ACM
380 if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
381 write_output(rec, &finished_round_event, sizeof(finished_round_event));
98402807
FW
382}
383
d20deb64 384static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
16c8a109 385{
abaff32a 386 struct stat st;
abaff32a 387 int flags;
d20deb64 388 int err, output;
8b412664 389 unsigned long waking = 0;
46be604b 390 const bool forks = argc > 0;
23346f21 391 struct machine *machine;
45694aa7 392 struct perf_tool *tool = &rec->tool;
d20deb64
ACM
393 struct perf_record_opts *opts = &rec->opts;
394 struct perf_evlist *evsel_list = rec->evlist;
395 const char *output_name = rec->output_name;
396 struct perf_session *session;
de9ac07b 397
d20deb64 398 rec->progname = argv[0];
33e49ea7 399
d20deb64 400 rec->page_size = sysconf(_SC_PAGE_SIZE);
de9ac07b 401
d20deb64 402 on_exit(perf_record__sig_exit, rec);
f5970550
PZ
403 signal(SIGCHLD, sig_handler);
404 signal(SIGINT, sig_handler);
18483b81 405 signal(SIGUSR1, sig_handler);
f5970550 406
d7065adb
FBH
407 if (!output_name) {
408 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
d20deb64 409 opts->pipe_output = true;
d7065adb 410 else
d20deb64 411 rec->output_name = output_name = "perf.data";
d7065adb
FBH
412 }
413 if (output_name) {
414 if (!strcmp(output_name, "-"))
d20deb64 415 opts->pipe_output = true;
d7065adb 416 else if (!stat(output_name, &st) && st.st_size) {
d20deb64 417 if (rec->write_mode == WRITE_FORCE) {
d7065adb
FBH
418 char oldname[PATH_MAX];
419 snprintf(oldname, sizeof(oldname), "%s.old",
420 output_name);
421 unlink(oldname);
422 rename(output_name, oldname);
423 }
d20deb64
ACM
424 } else if (rec->write_mode == WRITE_APPEND) {
425 rec->write_mode = WRITE_FORCE;
266e0e21 426 }
97124d5e
PZ
427 }
428
f887f301 429 flags = O_CREAT|O_RDWR;
d20deb64
ACM
430 if (rec->write_mode == WRITE_APPEND)
431 rec->file_new = 0;
abaff32a
IM
432 else
433 flags |= O_TRUNC;
434
d20deb64 435 if (opts->pipe_output)
529870e3
TZ
436 output = STDOUT_FILENO;
437 else
438 output = open(output_name, flags, S_IRUSR | S_IWUSR);
de9ac07b
PZ
439 if (output < 0) {
440 perror("failed to create output file");
441 exit(-1);
442 }
443
d20deb64
ACM
444 rec->output = output;
445
7865e817 446 session = perf_session__new(output_name, O_WRONLY,
d20deb64 447 rec->write_mode == WRITE_FORCE, false, NULL);
94c744b6 448 if (session == NULL) {
a9a70bbc
ACM
449 pr_err("Not enough memory for reading perf file header\n");
450 return -1;
451 }
452
d20deb64
ACM
453 rec->session = session;
454
455 if (!rec->no_buildid)
baa2f6ce
ACM
456 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
457
d20deb64 458 if (!rec->file_new) {
a91e5431 459 err = perf_session__read_header(session, output);
4dc0a04b 460 if (err < 0)
39d17dac 461 goto out_delete_session;
4dc0a04b
ACM
462 }
463
361c99a6 464 if (have_tracepoints(&evsel_list->entries))
94c744b6 465 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
03456a15 466
fbe96f29
SE
467 perf_header__set_feat(&session->header, HEADER_HOSTNAME);
468 perf_header__set_feat(&session->header, HEADER_OSRELEASE);
469 perf_header__set_feat(&session->header, HEADER_ARCH);
470 perf_header__set_feat(&session->header, HEADER_CPUDESC);
471 perf_header__set_feat(&session->header, HEADER_NRCPUS);
472 perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
473 perf_header__set_feat(&session->header, HEADER_CMDLINE);
474 perf_header__set_feat(&session->header, HEADER_VERSION);
475 perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
476 perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
477 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
478 perf_header__set_feat(&session->header, HEADER_CPUID);
479
d4db3f16 480 if (forks) {
d20deb64 481 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
35b9d88e
ACM
482 if (err < 0) {
483 pr_err("Couldn't run the workload!\n");
484 goto out_delete_session;
856e9660 485 }
856e9660
PZ
486 }
487
d20deb64 488 perf_record__open(rec);
de9ac07b 489
712a4b60 490 /*
d20deb64 491 * perf_session__delete(session) will be called at perf_record__exit()
712a4b60 492 */
d20deb64 493 on_exit(perf_record__exit, rec);
712a4b60 494
d20deb64 495 if (opts->pipe_output) {
529870e3
TZ
496 err = perf_header__write_pipe(output);
497 if (err < 0)
498 return err;
d20deb64 499 } else if (rec->file_new) {
a91e5431
ACM
500 err = perf_session__write_header(session, evsel_list,
501 output, false);
d5eed904
ACM
502 if (err < 0)
503 return err;
56b03f3c
ACM
504 }
505
e20960c0
RR
506 if (!!rec->no_buildid
507 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
508 pr_err("Couldn't generating buildids. "
509 "Use --no-buildid to profile anyway.\n");
510 return -1;
511 }
512
d20deb64 513 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
6122e4e4 514
743eb868
ACM
515 machine = perf_session__find_host_machine(session);
516 if (!machine) {
517 pr_err("Couldn't find native kernel information.\n");
518 return -1;
519 }
520
d20deb64 521 if (opts->pipe_output) {
45694aa7 522 err = perf_event__synthesize_attrs(tool, session,
d20deb64 523 process_synthesized_event);
2c46dbb5
TZ
524 if (err < 0) {
525 pr_err("Couldn't synthesize attrs.\n");
526 return err;
527 }
cd19a035 528
45694aa7 529 err = perf_event__synthesize_event_types(tool, process_synthesized_event,
743eb868 530 machine);
cd19a035
TZ
531 if (err < 0) {
532 pr_err("Couldn't synthesize event_types.\n");
533 return err;
534 }
9215545e 535
361c99a6 536 if (have_tracepoints(&evsel_list->entries)) {
63e0c771
TZ
537 /*
538 * FIXME err <= 0 here actually means that
539 * there were no tracepoints so its not really
540 * an error, just that we don't need to
541 * synthesize anything. We really have to
542 * return this more properly and also
543 * propagate errors that now are calling die()
544 */
45694aa7 545 err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
743eb868 546 process_synthesized_event);
63e0c771
TZ
547 if (err <= 0) {
548 pr_err("Couldn't record tracing data.\n");
549 return err;
550 }
d20deb64 551 advance_output(rec, err);
63e0c771 552 }
2c46dbb5
TZ
553 }
554
45694aa7 555 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
743eb868 556 machine, "_text");
70162138 557 if (err < 0)
45694aa7 558 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
743eb868 559 machine, "_stext");
c1a3a4b9
ACM
560 if (err < 0)
561 pr_err("Couldn't record kernel reference relocation symbol\n"
562 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
563 "Check /proc/kallsyms permission or run as root.\n");
b7cece76 564
45694aa7 565 err = perf_event__synthesize_modules(tool, process_synthesized_event,
743eb868 566 machine);
c1a3a4b9
ACM
567 if (err < 0)
568 pr_err("Couldn't record kernel module information.\n"
569 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
570 "Check /proc/modules permission or run as root.\n");
571
a1645ce1 572 if (perf_guest)
45694aa7 573 perf_session__process_machines(session, tool,
8115d60c 574 perf_event__synthesize_guest_os);
7c6a1c65 575
d20deb64 576 if (!opts->system_wide)
45694aa7 577 perf_event__synthesize_thread_map(tool, evsel_list->threads,
7c940c18 578 process_synthesized_event,
743eb868 579 machine);
234fbbf5 580 else
45694aa7 581 perf_event__synthesize_threads(tool, process_synthesized_event,
743eb868 582 machine);
7c6a1c65 583
d20deb64 584 if (rec->realtime_prio) {
de9ac07b
PZ
585 struct sched_param param;
586
d20deb64 587 param.sched_priority = rec->realtime_prio;
de9ac07b 588 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6beba7ad 589 pr_err("Could not set realtime priority.\n");
de9ac07b
PZ
590 exit(-1);
591 }
592 }
593
764e16a3
DA
594 perf_evlist__enable(evsel_list);
595
856e9660
PZ
596 /*
597 * Let the child rip
598 */
d4db3f16 599 if (forks)
35b9d88e 600 perf_evlist__start_workload(evsel_list);
856e9660 601
649c48a9 602 for (;;) {
d20deb64 603 int hits = rec->samples;
de9ac07b 604
d20deb64 605 perf_record__mmap_read_all(rec);
de9ac07b 606
d20deb64 607 if (hits == rec->samples) {
649c48a9
PZ
608 if (done)
609 break;
5c581041 610 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
8b412664
PZ
611 waking++;
612 }
613
4152ab37
ACM
614 if (done)
615 perf_evlist__disable(evsel_list);
de9ac07b
PZ
616 }
617
18483b81 618 if (quiet || signr == SIGUSR1)
b44308f5
ACM
619 return 0;
620
8b412664
PZ
621 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
622
021e9f47
IM
623 /*
624 * Approximate RIP event size: 24 bytes.
625 */
626 fprintf(stderr,
9486aa38 627 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
d20deb64 628 (double)rec->bytes_written / 1024.0 / 1024.0,
021e9f47 629 output_name,
d20deb64 630 rec->bytes_written / 24);
addc2785 631
de9ac07b 632 return 0;
39d17dac
ACM
633
634out_delete_session:
635 perf_session__delete(session);
636 return err;
de9ac07b 637}
0e9b20b8 638
0e9b20b8 639static const char * const record_usage[] = {
9e096753
MG
640 "perf record [<options>] [<command>]",
641 "perf record [<options>] -- <command> [<options>]",
0e9b20b8
IM
642 NULL
643};
644
d20deb64
ACM
645/*
646 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
647 * because we need to have access to it in perf_record__exit, that is called
648 * after cmd_record() exits, but since record_options need to be accessible to
649 * builtin-script, leave it here.
650 *
651 * At least we don't ouch it in all the other functions here directly.
652 *
653 * Just say no to tons of global variables, sigh.
654 */
655static struct perf_record record = {
656 .opts = {
657 .target_pid = -1,
658 .target_tid = -1,
659 .mmap_pages = UINT_MAX,
660 .user_freq = UINT_MAX,
661 .user_interval = ULLONG_MAX,
662 .freq = 1000,
663 .sample_id_all_avail = true,
664 },
665 .write_mode = WRITE_FORCE,
666 .file_new = true,
667};
7865e817 668
d20deb64
ACM
669/*
670 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
671 * with it and switch to use the library functions in perf_evlist that came
672 * from builtin-record.c, i.e. use perf_record_opts,
673 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
674 * using pipes, etc.
675 */
bca647aa 676const struct option record_options[] = {
d20deb64 677 OPT_CALLBACK('e', "event", &record.evlist, "event",
86847b62 678 "event selector. use 'perf list' to list available events",
f120f9d5 679 parse_events_option),
d20deb64 680 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
c171b552 681 "event filter", parse_filter),
d20deb64 682 OPT_INTEGER('p', "pid", &record.opts.target_pid,
d6d901c2 683 "record events on existing process id"),
d20deb64 684 OPT_INTEGER('t', "tid", &record.opts.target_tid,
d6d901c2 685 "record events on existing thread id"),
d20deb64 686 OPT_INTEGER('r', "realtime", &record.realtime_prio,
0e9b20b8 687 "collect data with this RT SCHED_FIFO priority"),
d20deb64 688 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
acac03fa 689 "collect data without buffering"),
d20deb64 690 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
daac07b2 691 "collect raw sample records from all opened counters"),
d20deb64 692 OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
0e9b20b8 693 "system-wide collection from all CPUs"),
d20deb64 694 OPT_BOOLEAN('A', "append", &record.append_file,
abaff32a 695 "append to the output file to do incremental profiling"),
d20deb64 696 OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
c45c6ea2 697 "list of cpus to monitor"),
d20deb64 698 OPT_BOOLEAN('f', "force", &record.force,
7865e817 699 "overwrite existing data file (deprecated)"),
d20deb64
ACM
700 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
701 OPT_STRING('o', "output", &record.output_name, "file",
abaff32a 702 "output file name"),
d20deb64 703 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
2e6cdf99 704 "child tasks do not inherit counters"),
d20deb64
ACM
705 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
706 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
01c2d99b 707 "number of mmap data pages"),
d20deb64 708 OPT_BOOLEAN(0, "group", &record.opts.group,
43bece79 709 "put the counters into a counter group"),
d20deb64 710 OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph,
3efa1cc9 711 "do call-graph (stack chain/backtrace) recording"),
c0555642 712 OPT_INCR('v', "verbose", &verbose,
3da297a6 713 "be more verbose (show counter open errors, etc)"),
b44308f5 714 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
d20deb64 715 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
649c48a9 716 "per thread counts"),
d20deb64 717 OPT_BOOLEAN('d', "data", &record.opts.sample_address,
4bba828d 718 "Sample addresses"),
d20deb64 719 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
3e76ac78 720 OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
d20deb64 721 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
649c48a9 722 "don't sample"),
d20deb64 723 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
a1ac1d3c 724 "do not update the buildid cache"),
d20deb64 725 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
baa2f6ce 726 "do not collect buildids in perf.data"),
d20deb64 727 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
023695d9
SE
728 "monitor event in cgroup name only",
729 parse_cgroups),
0e9b20b8
IM
730 OPT_END()
731};
732
f37a291c 733int cmd_record(int argc, const char **argv, const char *prefix __used)
0e9b20b8 734{
69aad6f1
ACM
735 int err = -ENOMEM;
736 struct perf_evsel *pos;
d20deb64
ACM
737 struct perf_evlist *evsel_list;
738 struct perf_record *rec = &record;
0e9b20b8 739
fbe96f29
SE
740 perf_header__set_cmdline(argc, argv);
741
7e2ed097 742 evsel_list = perf_evlist__new(NULL, NULL);
361c99a6
ACM
743 if (evsel_list == NULL)
744 return -ENOMEM;
745
d20deb64
ACM
746 rec->evlist = evsel_list;
747
bca647aa 748 argc = parse_options(argc, argv, record_options, record_usage,
655000e7 749 PARSE_OPT_STOP_AT_NON_OPTION);
d20deb64
ACM
750 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 &&
751 !rec->opts.system_wide && !rec->opts.cpu_list)
bca647aa 752 usage_with_options(record_usage, record_options);
0e9b20b8 753
d20deb64 754 if (rec->force && rec->append_file) {
7865e817
FW
755 fprintf(stderr, "Can't overwrite and append at the same time."
756 " You need to choose between -f and -A");
bca647aa 757 usage_with_options(record_usage, record_options);
d20deb64
ACM
758 } else if (rec->append_file) {
759 rec->write_mode = WRITE_APPEND;
7865e817 760 } else {
d20deb64 761 rec->write_mode = WRITE_FORCE;
7865e817
FW
762 }
763
d20deb64 764 if (nr_cgroups && !rec->opts.system_wide) {
023695d9
SE
765 fprintf(stderr, "cgroup monitoring only available in"
766 " system-wide mode\n");
767 usage_with_options(record_usage, record_options);
768 }
769
655000e7 770 symbol__init();
baa2f6ce 771
ec80fde7 772 if (symbol_conf.kptr_restrict)
646aaea6
ACM
773 pr_warning(
774"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
775"check /proc/sys/kernel/kptr_restrict.\n\n"
776"Samples in kernel functions may not be resolved if a suitable vmlinux\n"
777"file is not found in the buildid cache or in the vmlinux path.\n\n"
778"Samples in kernel modules won't be resolved at all.\n\n"
779"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
780"even with a suitable vmlinux or kallsyms file.\n\n");
ec80fde7 781
d20deb64 782 if (rec->no_buildid_cache || rec->no_buildid)
a1ac1d3c 783 disable_buildid_cache();
655000e7 784
361c99a6
ACM
785 if (evsel_list->nr_entries == 0 &&
786 perf_evlist__add_default(evsel_list) < 0) {
69aad6f1
ACM
787 pr_err("Not enough memory for event selector list\n");
788 goto out_symbol_exit;
bbd36e5e 789 }
0e9b20b8 790
d20deb64
ACM
791 if (rec->opts.target_pid != -1)
792 rec->opts.target_tid = rec->opts.target_pid;
d6d901c2 793
d20deb64
ACM
794 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
795 rec->opts.target_tid, rec->opts.cpu_list) < 0)
dd7927f4 796 usage_with_options(record_usage, record_options);
69aad6f1 797
361c99a6 798 list_for_each_entry(pos, &evsel_list->entries, node) {
ad7f4e3f
ACM
799 if (perf_header__push_event(pos->attr.config, event_name(pos)))
800 goto out_free_fd;
d6d901c2 801 }
5c581041 802
d20deb64
ACM
803 if (rec->opts.user_interval != ULLONG_MAX)
804 rec->opts.default_interval = rec->opts.user_interval;
805 if (rec->opts.user_freq != UINT_MAX)
806 rec->opts.freq = rec->opts.user_freq;
f9212819 807
7e4ff9e3
MG
808 /*
809 * User specified count overrides default frequency.
810 */
d20deb64
ACM
811 if (rec->opts.default_interval)
812 rec->opts.freq = 0;
813 else if (rec->opts.freq) {
814 rec->opts.default_interval = rec->opts.freq;
7e4ff9e3
MG
815 } else {
816 fprintf(stderr, "frequency and count are zero, aborting\n");
39d17dac 817 err = -EINVAL;
5c581041 818 goto out_free_fd;
7e4ff9e3
MG
819 }
820
d20deb64 821 err = __cmd_record(&record, argc, argv);
39d17dac 822out_free_fd:
7e2ed097 823 perf_evlist__delete_maps(evsel_list);
d65a458b
ACM
824out_symbol_exit:
825 symbol__exit();
39d17dac 826 return err;
0e9b20b8 827}