65
66
struct perf_tool tool;
66
67
struct perf_record_opts opts;
68
const char *output_name;
69
struct perf_data_file file;
69
70
struct perf_evlist *evlist;
70
71
struct perf_session *session;
71
72
const char *progname;
73
unsigned int page_size;
76
75
bool no_buildid_cache;
78
off_t post_processing_offset;
81
static void advance_output(struct perf_record *rec, size_t size)
79
static int do_write_output(struct perf_record *rec, void *buf, size_t size)
83
rec->bytes_written += size;
81
struct perf_data_file *file = &rec->file;
86
static int write_output(struct perf_record *rec, void *buf, size_t size)
89
int ret = write(rec->output, buf, size);
84
ssize_t ret = write(file->fd, buf, size);
92
pr_err("failed to write\n");
87
pr_err("failed to write perf data, error: %m\n");
100
static int write_output(struct perf_record *rec, void *buf, size_t size)
102
return do_write_output(rec, buf, size);
105
105
static int process_synthesized_event(struct perf_tool *tool,
106
106
union perf_event *event,
107
107
struct perf_sample *sample __maybe_unused,
234
234
"or try again with a smaller value of -m/--mmap_pages.\n"
235
235
"(current value: %d)\n", opts->mmap_pages);
237
} else if (!is_power_of_2(opts->mmap_pages) &&
238
(opts->mmap_pages != UINT_MAX)) {
239
pr_err("--mmap_pages/-m value must be a power of two.");
242
238
pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
254
250
static int process_buildids(struct perf_record *rec)
256
u64 size = lseek(rec->output, 0, SEEK_CUR);
252
struct perf_data_file *file = &rec->file;
253
struct perf_session *session = rec->session;
254
u64 start = session->header.data_offset;
256
u64 size = lseek(file->fd, 0, SEEK_CUR);
261
rec->session->fd = rec->output;
262
return __perf_session__process_events(rec->session, rec->post_processing_offset,
263
size - rec->post_processing_offset,
260
return __perf_session__process_events(session, start,
264
262
size, &build_id__mark_dso_hit_ops);
267
265
static void perf_record__exit(int status, void *arg)
269
267
struct perf_record *rec = arg;
268
struct perf_data_file *file = &rec->file;
274
if (!rec->opts.pipe_output) {
273
if (!file->is_pipe) {
275
274
rec->session->header.data_size += rec->bytes_written;
277
276
if (!rec->no_buildid)
278
277
process_buildids(rec);
279
278
perf_session__write_header(rec->session, rec->evlist,
281
280
perf_session__delete(rec->session);
282
281
perf_evlist__delete(rec->evlist);
345
static void perf_record__init_features(struct perf_record *rec)
347
struct perf_evlist *evsel_list = rec->evlist;
348
struct perf_session *session = rec->session;
351
for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
352
perf_header__set_feat(&session->header, feat);
355
perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
357
if (!have_tracepoints(&evsel_list->entries))
358
perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
360
if (!rec->opts.branch_stack)
361
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
346
364
static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
350
int err, output, feat;
351
367
unsigned long waking = 0;
352
368
const bool forks = argc > 0;
353
369
struct machine *machine;
354
370
struct perf_tool *tool = &rec->tool;
355
371
struct perf_record_opts *opts = &rec->opts;
356
372
struct perf_evlist *evsel_list = rec->evlist;
357
const char *output_name = rec->output_name;
373
struct perf_data_file *file = &rec->file;
358
374
struct perf_session *session;
359
375
bool disabled = false;
361
377
rec->progname = argv[0];
363
rec->page_size = sysconf(_SC_PAGE_SIZE);
365
379
on_exit(perf_record__sig_exit, rec);
366
380
signal(SIGCHLD, sig_handler);
367
381
signal(SIGINT, sig_handler);
368
382
signal(SIGUSR1, sig_handler);
369
383
signal(SIGTERM, sig_handler);
372
if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
373
opts->pipe_output = true;
375
rec->output_name = output_name = "perf.data";
378
if (!strcmp(output_name, "-"))
379
opts->pipe_output = true;
380
else if (!stat(output_name, &st) && st.st_size) {
381
char oldname[PATH_MAX];
382
snprintf(oldname, sizeof(oldname), "%s.old",
385
rename(output_name, oldname);
389
flags = O_CREAT|O_RDWR|O_TRUNC;
391
if (opts->pipe_output)
392
output = STDOUT_FILENO;
394
output = open(output_name, flags, S_IRUSR | S_IWUSR);
396
perror("failed to create output file");
400
rec->output = output;
402
session = perf_session__new(output_name, O_WRONLY,
385
session = perf_session__new(file, false, NULL);
404
386
if (session == NULL) {
405
387
pr_err("Not enough memory for reading perf file header\n");
409
391
rec->session = session;
411
for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
412
perf_header__set_feat(&session->header, feat);
415
perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
417
if (!have_tracepoints(&evsel_list->entries))
418
perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
420
if (!rec->opts.branch_stack)
421
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
393
perf_record__init_features(rec);
424
396
err = perf_evlist__prepare_workload(evsel_list, &opts->target,
425
argv, opts->pipe_output,
428
400
pr_err("Couldn't run the workload!\n");
483
453
* return this more properly and also
484
454
* propagate errors that now are calling die()
486
err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
456
err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list,
487
457
process_synthesized_event);
489
459
pr_err("Couldn't record tracing data.\n");
490
460
goto out_delete_session;
492
advance_output(rec, err);
462
rec->bytes_written += err;
515
485
perf_event__synthesize_guest_os, tool);
518
if (perf_target__has_task(&opts->target))
519
err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
520
process_synthesized_event,
522
else if (perf_target__has_cpu(&opts->target))
523
err = perf_event__synthesize_threads(tool, process_synthesized_event,
525
else /* command specified */
488
err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads,
489
process_synthesized_event, opts->sample_address);
529
491
goto out_delete_session;
618
580
BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
619
581
BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
620
582
BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
583
BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
584
BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
585
BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
875
840
OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
876
841
"list of cpus to monitor"),
877
842
OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
878
OPT_STRING('o', "output", &record.output_name, "file",
843
OPT_STRING('o', "output", &record.file.path, "file",
879
844
"output file name"),
880
845
OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
881
846
"child tasks do not inherit counters"),
882
847
OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
883
OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
884
"number of mmap data pages"),
848
OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
849
"number of mmap data pages",
850
perf_evlist__parse_mmap_pages),
885
851
OPT_BOOLEAN(0, "group", &record.opts.group,
886
852
"put the counters into a counter group"),
887
853
OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
920
886
parse_branch_stack),
921
887
OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
922
888
"sample by weight (on special events only)"),
889
OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
890
"sample transaction flags (special events only)"),
891
OPT_BOOLEAN(0, "force-per-cpu", &record.opts.target.force_per_cpu,
892
"force the use of per-cpu mmaps"),
939
909
argc = parse_options(argc, argv, record_options, record_usage,
940
910
PARSE_OPT_STOP_AT_NON_OPTION);
941
if (!argc && perf_target__none(&rec->opts.target))
911
if (!argc && target__none(&rec->opts.target))
942
912
usage_with_options(record_usage, record_options);
944
914
if (nr_cgroups && !rec->opts.target.system_wide) {
968
938
goto out_symbol_exit;
971
err = perf_target__validate(&rec->opts.target);
941
err = target__validate(&rec->opts.target);
973
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
943
target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
974
944
ui__warning("%s", errbuf);
977
err = perf_target__parse_uid(&rec->opts.target);
947
err = target__parse_uid(&rec->opts.target);
979
949
int saved_errno = errno;
981
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
951
target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
982
952
ui__error("%s", errbuf);
984
954
err = -saved_errno;
989
959
if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
990
960
usage_with_options(record_usage, record_options);
992
if (rec->opts.user_interval != ULLONG_MAX)
993
rec->opts.default_interval = rec->opts.user_interval;
994
if (rec->opts.user_freq != UINT_MAX)
995
rec->opts.freq = rec->opts.user_freq;
998
* User specified count overrides default frequency.
1000
if (rec->opts.default_interval)
1002
else if (rec->opts.freq) {
1003
rec->opts.default_interval = rec->opts.freq;
1005
ui__error("frequency and count are zero, aborting\n");
962
if (perf_record_opts__config(&rec->opts)) {
1007
964
goto out_free_fd;