diff options
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 003255910c05..bf4ca749d1ac 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <signal.h> | 51 | #include <signal.h> |
52 | #include <sys/mman.h> | 52 | #include <sys/mman.h> |
53 | #include <sys/wait.h> | 53 | #include <sys/wait.h> |
54 | #include <asm/bug.h> | ||
55 | #include <linux/time64.h> | 54 | #include <linux/time64.h> |
56 | 55 | ||
57 | struct switch_output { | 56 | struct switch_output { |
@@ -79,6 +78,7 @@ struct record { | |||
79 | bool no_buildid_cache_set; | 78 | bool no_buildid_cache_set; |
80 | bool buildid_all; | 79 | bool buildid_all; |
81 | bool timestamp_filename; | 80 | bool timestamp_filename; |
81 | bool timestamp_boundary; | ||
82 | struct switch_output switch_output; | 82 | struct switch_output switch_output; |
83 | unsigned long long samples; | 83 | unsigned long long samples; |
84 | }; | 84 | }; |
@@ -301,7 +301,7 @@ static int record__mmap_evlist(struct record *rec, | |||
301 | struct record_opts *opts = &rec->opts; | 301 | struct record_opts *opts = &rec->opts; |
302 | char msg[512]; | 302 | char msg[512]; |
303 | 303 | ||
304 | if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, | 304 | if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, |
305 | opts->auxtrace_mmap_pages, | 305 | opts->auxtrace_mmap_pages, |
306 | opts->auxtrace_snapshot_mode) < 0) { | 306 | opts->auxtrace_snapshot_mode) < 0) { |
307 | if (errno == EPERM) { | 307 | if (errno == EPERM) { |
@@ -372,6 +372,8 @@ try_again: | |||
372 | ui__error("%s\n", msg); | 372 | ui__error("%s\n", msg); |
373 | goto out; | 373 | goto out; |
374 | } | 374 | } |
375 | |||
376 | pos->supported = true; | ||
375 | } | 377 | } |
376 | 378 | ||
377 | if (perf_evlist__apply_filters(evlist, &pos)) { | 379 | if (perf_evlist__apply_filters(evlist, &pos)) { |
@@ -408,8 +410,15 @@ static int process_sample_event(struct perf_tool *tool, | |||
408 | { | 410 | { |
409 | struct record *rec = container_of(tool, struct record, tool); | 411 | struct record *rec = container_of(tool, struct record, tool); |
410 | 412 | ||
411 | rec->samples++; | 413 | if (rec->evlist->first_sample_time == 0) |
414 | rec->evlist->first_sample_time = sample->time; | ||
415 | |||
416 | rec->evlist->last_sample_time = sample->time; | ||
412 | 417 | ||
418 | if (rec->buildid_all) | ||
419 | return 0; | ||
420 | |||
421 | rec->samples++; | ||
413 | return build_id__mark_dso_hit(tool, event, sample, evsel, machine); | 422 | return build_id__mark_dso_hit(tool, event, sample, evsel, machine); |
414 | } | 423 | } |
415 | 424 | ||
@@ -434,9 +443,11 @@ static int process_buildids(struct record *rec) | |||
434 | 443 | ||
435 | /* | 444 | /* |
436 | * If --buildid-all is given, it marks all DSO regardless of hits, | 445 | * If --buildid-all is given, it marks all DSO regardless of hits, |
437 | * so no need to process samples. | 446 | * so no need to process samples. But if timestamp_boundary is enabled, |
447 | * it still needs to walk on all samples to get the timestamps of | ||
448 | * first/last samples. | ||
438 | */ | 449 | */ |
439 | if (rec->buildid_all) | 450 | if (rec->buildid_all && !rec->timestamp_boundary) |
440 | rec->tool.sample = NULL; | 451 | rec->tool.sample = NULL; |
441 | 452 | ||
442 | return perf_session__process_events(session); | 453 | return perf_session__process_events(session); |
@@ -477,7 +488,7 @@ static struct perf_event_header finished_round_event = { | |||
477 | }; | 488 | }; |
478 | 489 | ||
479 | static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, | 490 | static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, |
480 | bool backward) | 491 | bool overwrite) |
481 | { | 492 | { |
482 | u64 bytes_written = rec->bytes_written; | 493 | u64 bytes_written = rec->bytes_written; |
483 | int i; | 494 | int i; |
@@ -487,18 +498,18 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli | |||
487 | if (!evlist) | 498 | if (!evlist) |
488 | return 0; | 499 | return 0; |
489 | 500 | ||
490 | maps = backward ? evlist->backward_mmap : evlist->mmap; | 501 | maps = overwrite ? evlist->overwrite_mmap : evlist->mmap; |
491 | if (!maps) | 502 | if (!maps) |
492 | return 0; | 503 | return 0; |
493 | 504 | ||
494 | if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) | 505 | if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) |
495 | return 0; | 506 | return 0; |
496 | 507 | ||
497 | for (i = 0; i < evlist->nr_mmaps; i++) { | 508 | for (i = 0; i < evlist->nr_mmaps; i++) { |
498 | struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; | 509 | struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; |
499 | 510 | ||
500 | if (maps[i].base) { | 511 | if (maps[i].base) { |
501 | if (perf_mmap__push(&maps[i], evlist->overwrite, backward, rec, record__pushfn) != 0) { | 512 | if (perf_mmap__push(&maps[i], overwrite, rec, record__pushfn) != 0) { |
502 | rc = -1; | 513 | rc = -1; |
503 | goto out; | 514 | goto out; |
504 | } | 515 | } |
@@ -518,7 +529,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli | |||
518 | if (bytes_written != rec->bytes_written) | 529 | if (bytes_written != rec->bytes_written) |
519 | rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); | 530 | rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); |
520 | 531 | ||
521 | if (backward) | 532 | if (overwrite) |
522 | perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); | 533 | perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); |
523 | out: | 534 | out: |
524 | return rc; | 535 | return rc; |
@@ -690,8 +701,8 @@ perf_evlist__pick_pc(struct perf_evlist *evlist) | |||
690 | if (evlist) { | 701 | if (evlist) { |
691 | if (evlist->mmap && evlist->mmap[0].base) | 702 | if (evlist->mmap && evlist->mmap[0].base) |
692 | return evlist->mmap[0].base; | 703 | return evlist->mmap[0].base; |
693 | if (evlist->backward_mmap && evlist->backward_mmap[0].base) | 704 | if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base) |
694 | return evlist->backward_mmap[0].base; | 705 | return evlist->overwrite_mmap[0].base; |
695 | } | 706 | } |
696 | return NULL; | 707 | return NULL; |
697 | } | 708 | } |
@@ -784,6 +795,28 @@ static int record__synthesize(struct record *rec, bool tail) | |||
784 | perf_event__synthesize_guest_os, tool); | 795 | perf_event__synthesize_guest_os, tool); |
785 | } | 796 | } |
786 | 797 | ||
798 | err = perf_event__synthesize_extra_attr(&rec->tool, | ||
799 | rec->evlist, | ||
800 | process_synthesized_event, | ||
801 | data->is_pipe); | ||
802 | if (err) | ||
803 | goto out; | ||
804 | |||
805 | err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads, | ||
806 | process_synthesized_event, | ||
807 | NULL); | ||
808 | if (err < 0) { | ||
809 | pr_err("Couldn't synthesize thread map.\n"); | ||
810 | return err; | ||
811 | } | ||
812 | |||
813 | err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus, | ||
814 | process_synthesized_event, NULL); | ||
815 | if (err < 0) { | ||
816 | pr_err("Couldn't synthesize cpu map.\n"); | ||
817 | return err; | ||
818 | } | ||
819 | |||
787 | err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, | 820 | err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, |
788 | process_synthesized_event, opts->sample_address, | 821 | process_synthesized_event, opts->sample_address, |
789 | opts->proc_map_timeout, 1); | 822 | opts->proc_map_timeout, 1); |
@@ -1533,7 +1566,8 @@ static struct option __record_options[] = { | |||
1533 | OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, | 1566 | OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, |
1534 | &record.opts.sample_time_set, | 1567 | &record.opts.sample_time_set, |
1535 | "Record the sample timestamps"), | 1568 | "Record the sample timestamps"), |
1536 | OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), | 1569 | OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set, |
1570 | "Record the sample period"), | ||
1537 | OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, | 1571 | OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, |
1538 | "don't sample"), | 1572 | "don't sample"), |
1539 | OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, | 1573 | OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, |
@@ -1598,6 +1632,8 @@ static struct option __record_options[] = { | |||
1598 | "Record build-id of all DSOs regardless of hits"), | 1632 | "Record build-id of all DSOs regardless of hits"), |
1599 | OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, | 1633 | OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, |
1600 | "append timestamp to output filename"), | 1634 | "append timestamp to output filename"), |
1635 | OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, | ||
1636 | "Record timestamp boundary (time of first/last samples)"), | ||
1601 | OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, | 1637 | OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, |
1602 | &record.switch_output.set, "signal,size,time", | 1638 | &record.switch_output.set, "signal,size,time", |
1603 | "Switch output when receive SIGUSR2 or cross size,time threshold", | 1639 | "Switch output when receive SIGUSR2 or cross size,time threshold", |
@@ -1781,8 +1817,8 @@ int cmd_record(int argc, const char **argv) | |||
1781 | goto out; | 1817 | goto out; |
1782 | } | 1818 | } |
1783 | 1819 | ||
1784 | /* Enable ignoring missing threads when -u option is defined. */ | 1820 | /* Enable ignoring missing threads when -u/-p option is defined. */ |
1785 | rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX; | 1821 | rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; |
1786 | 1822 | ||
1787 | err = -ENOMEM; | 1823 | err = -ENOMEM; |
1788 | if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) | 1824 | if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) |