aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c66
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
57struct switch_output { 56struct 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
479static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, 490static 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);
523out: 534out:
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)