diff options
author | Tom Zanussi <tzanussi@gmail.com> | 2010-05-01 02:41:20 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-05-02 12:36:56 -0400 |
commit | 454c407ec17a0c63e4023ac0877d687945a7df4a (patch) | |
tree | 1271299a59a89419c0dd4dcbf29b4492b63555ca /tools/perf/util | |
parent | 789688faef5b3ba78065beaf2f3d6f1c839f74a3 (diff) |
perf: add perf-inject builtin
Currently, perf 'live mode' writes build-ids at the end of the
session, which isn't actually useful for processing live mode events.
What would be better would be to have the build-ids sent before any of
the samples that reference them, which can be done by processing the
event stream and retrieving the build-ids on the first hit. Doing
that in perf-record itself, however, is off-limits.
This patch introduces perf-inject, which does the same job while
leaving perf-record untouched. Normal mode perf still records the
build-ids at the end of the session as it should, but for live mode,
perf-inject can be injected in between the record and report steps
e.g.:
perf record -o - ./hackbench 10 | perf inject -v -b | perf report -v -i -
perf-inject reads a perf-record event stream and repipes it to stdout.
At any point the processing code can inject other events into the
event stream - in this case build-ids (-b option) are read and
injected as needed into the event stream.
Build-ids are just the first user of perf-inject - potentially
anything that needs userspace processing to augment the trace stream
with additional information could make use of this facility.
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
LKML-Reference: <1272696080-16435-3-git-send-email-tzanussi@gmail.com>
Signed-off-by: Tom Zanussi <tzanussi@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/header.c | 35 | ||||
-rw-r--r-- | tools/perf/util/session.c | 3 | ||||
-rw-r--r-- | tools/perf/util/session.h | 3 | ||||
-rw-r--r-- | tools/perf/util/trace-event-read.c | 19 | ||||
-rw-r--r-- | tools/perf/util/trace-event.h | 2 |
5 files changed, 50 insertions, 12 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2d1d97e0746d..79da0e50ef8f 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -713,10 +713,18 @@ static int __event_process_build_id(struct build_id_event *bev, | |||
713 | 713 | ||
714 | dso = __dsos__findnew(head, filename); | 714 | dso = __dsos__findnew(head, filename); |
715 | if (dso != NULL) { | 715 | if (dso != NULL) { |
716 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
717 | |||
716 | dso__set_build_id(dso, &bev->build_id); | 718 | dso__set_build_id(dso, &bev->build_id); |
717 | if (filename[0] == '[') | 719 | |
718 | dso->kernel = dso_type; | 720 | if (filename[0] == '[') |
719 | } | 721 | dso->kernel = dso_type; |
722 | |||
723 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), | ||
724 | sbuild_id); | ||
725 | pr_debug("build id event received for %s: %s\n", | ||
726 | dso->long_name, sbuild_id); | ||
727 | } | ||
720 | 728 | ||
721 | err = 0; | 729 | err = 0; |
722 | out: | 730 | out: |
@@ -767,7 +775,7 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
767 | 775 | ||
768 | switch (feat) { | 776 | switch (feat) { |
769 | case HEADER_TRACE_INFO: | 777 | case HEADER_TRACE_INFO: |
770 | trace_report(fd); | 778 | trace_report(fd, false); |
771 | break; | 779 | break; |
772 | 780 | ||
773 | case HEADER_BUILD_ID: | 781 | case HEADER_BUILD_ID: |
@@ -782,12 +790,16 @@ static int perf_file_section__process(struct perf_file_section *self, | |||
782 | } | 790 | } |
783 | 791 | ||
784 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, | 792 | static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, |
785 | struct perf_header *ph, int fd) | 793 | struct perf_header *ph, int fd, |
794 | bool repipe) | ||
786 | { | 795 | { |
787 | if (do_read(fd, self, sizeof(*self)) <= 0 || | 796 | if (do_read(fd, self, sizeof(*self)) <= 0 || |
788 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 797 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
789 | return -1; | 798 | return -1; |
790 | 799 | ||
800 | if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0) | ||
801 | return -1; | ||
802 | |||
791 | if (self->size != sizeof(*self)) { | 803 | if (self->size != sizeof(*self)) { |
792 | u64 size = bswap_64(self->size); | 804 | u64 size = bswap_64(self->size); |
793 | 805 | ||
@@ -805,7 +817,8 @@ static int perf_header__read_pipe(struct perf_session *session, int fd) | |||
805 | struct perf_header *self = &session->header; | 817 | struct perf_header *self = &session->header; |
806 | struct perf_pipe_file_header f_header; | 818 | struct perf_pipe_file_header f_header; |
807 | 819 | ||
808 | if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { | 820 | if (perf_file_header__read_pipe(&f_header, self, fd, |
821 | session->repipe) < 0) { | ||
809 | pr_debug("incompatible file format\n"); | 822 | pr_debug("incompatible file format\n"); |
810 | return -EINVAL; | 823 | return -EINVAL; |
811 | } | 824 | } |
@@ -1096,12 +1109,17 @@ int event__process_tracing_data(event_t *self, | |||
1096 | lseek(session->fd, offset + sizeof(struct tracing_data_event), | 1109 | lseek(session->fd, offset + sizeof(struct tracing_data_event), |
1097 | SEEK_SET); | 1110 | SEEK_SET); |
1098 | 1111 | ||
1099 | size_read = trace_report(session->fd); | 1112 | size_read = trace_report(session->fd, session->repipe); |
1100 | 1113 | ||
1101 | padding = ALIGN(size_read, sizeof(u64)) - size_read; | 1114 | padding = ALIGN(size_read, sizeof(u64)) - size_read; |
1102 | 1115 | ||
1103 | if (read(session->fd, buf, padding) < 0) | 1116 | if (read(session->fd, buf, padding) < 0) |
1104 | die("reading input file"); | 1117 | die("reading input file"); |
1118 | if (session->repipe) { | ||
1119 | int retw = write(STDOUT_FILENO, buf, padding); | ||
1120 | if (retw <= 0 || retw != padding) | ||
1121 | die("repiping tracing data padding"); | ||
1122 | } | ||
1105 | 1123 | ||
1106 | if (size_read + padding != size) | 1124 | if (size_read + padding != size) |
1107 | die("tracing data size mismatch"); | 1125 | die("tracing data size mismatch"); |
@@ -1110,7 +1128,8 @@ int event__process_tracing_data(event_t *self, | |||
1110 | } | 1128 | } |
1111 | 1129 | ||
1112 | int event__synthesize_build_id(struct dso *pos, u16 misc, | 1130 | int event__synthesize_build_id(struct dso *pos, u16 misc, |
1113 | event__handler_t process, struct machine *machine, | 1131 | event__handler_t process, |
1132 | struct machine *machine, | ||
1114 | struct perf_session *session) | 1133 | struct perf_session *session) |
1115 | { | 1134 | { |
1116 | event_t ev; | 1135 | event_t ev; |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index a8dd73ed1581..5d353e70fe26 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -77,7 +77,7 @@ int perf_session__create_kernel_maps(struct perf_session *self) | |||
77 | return ret; | 77 | return ret; |
78 | } | 78 | } |
79 | 79 | ||
80 | struct perf_session *perf_session__new(const char *filename, int mode, bool force) | 80 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) |
81 | { | 81 | { |
82 | size_t len = filename ? strlen(filename) + 1 : 0; | 82 | size_t len = filename ? strlen(filename) + 1 : 0; |
83 | struct perf_session *self = zalloc(sizeof(*self) + len); | 83 | struct perf_session *self = zalloc(sizeof(*self) + len); |
@@ -97,6 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc | |||
97 | self->cwdlen = 0; | 97 | self->cwdlen = 0; |
98 | self->unknown_events = 0; | 98 | self->unknown_events = 0; |
99 | self->machines = RB_ROOT; | 99 | self->machines = RB_ROOT; |
100 | self->repipe = repipe; | ||
100 | self->ordered_samples.flush_limit = ULLONG_MAX; | 101 | self->ordered_samples.flush_limit = ULLONG_MAX; |
101 | INIT_LIST_HEAD(&self->ordered_samples.samples_head); | 102 | INIT_LIST_HEAD(&self->ordered_samples.samples_head); |
102 | 103 | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 61ca92e58ad4..f2b2c6a3a49d 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -34,6 +34,7 @@ struct perf_session { | |||
34 | u64 sample_type; | 34 | u64 sample_type; |
35 | int fd; | 35 | int fd; |
36 | bool fd_pipe; | 36 | bool fd_pipe; |
37 | bool repipe; | ||
37 | int cwdlen; | 38 | int cwdlen; |
38 | char *cwd; | 39 | char *cwd; |
39 | struct ordered_samples ordered_samples; | 40 | struct ordered_samples ordered_samples; |
@@ -59,7 +60,7 @@ struct perf_event_ops { | |||
59 | bool ordered_samples; | 60 | bool ordered_samples; |
60 | }; | 61 | }; |
61 | 62 | ||
62 | struct perf_session *perf_session__new(const char *filename, int mode, bool force); | 63 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); |
63 | void perf_session__delete(struct perf_session *self); | 64 | void perf_session__delete(struct perf_session *self); |
64 | 65 | ||
65 | void perf_event_header__bswap(struct perf_event_header *self); | 66 | void perf_event_header__bswap(struct perf_event_header *self); |
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 44889c9b5630..43f19c1fed3a 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c | |||
@@ -51,6 +51,7 @@ static int long_size; | |||
51 | static unsigned long page_size; | 51 | static unsigned long page_size; |
52 | 52 | ||
53 | static ssize_t calc_data_size; | 53 | static ssize_t calc_data_size; |
54 | static bool repipe; | ||
54 | 55 | ||
55 | static int do_read(int fd, void *buf, int size) | 56 | static int do_read(int fd, void *buf, int size) |
56 | { | 57 | { |
@@ -62,6 +63,13 @@ static int do_read(int fd, void *buf, int size) | |||
62 | if (ret <= 0) | 63 | if (ret <= 0) |
63 | return -1; | 64 | return -1; |
64 | 65 | ||
66 | if (repipe) { | ||
67 | int retw = write(STDOUT_FILENO, buf, ret); | ||
68 | |||
69 | if (retw <= 0 || retw != ret) | ||
70 | die("repiping input file"); | ||
71 | } | ||
72 | |||
65 | size -= ret; | 73 | size -= ret; |
66 | buf += ret; | 74 | buf += ret; |
67 | } | 75 | } |
@@ -116,6 +124,13 @@ static char *read_string(void) | |||
116 | if (!r) | 124 | if (!r) |
117 | die("no data"); | 125 | die("no data"); |
118 | 126 | ||
127 | if (repipe) { | ||
128 | int retw = write(STDOUT_FILENO, &c, 1); | ||
129 | |||
130 | if (retw <= 0 || retw != r) | ||
131 | die("repiping input file string"); | ||
132 | } | ||
133 | |||
119 | buf[size++] = c; | 134 | buf[size++] = c; |
120 | 135 | ||
121 | if (!c) | 136 | if (!c) |
@@ -454,7 +469,7 @@ struct record *trace_read_data(int cpu) | |||
454 | return data; | 469 | return data; |
455 | } | 470 | } |
456 | 471 | ||
457 | ssize_t trace_report(int fd) | 472 | ssize_t trace_report(int fd, bool __repipe) |
458 | { | 473 | { |
459 | char buf[BUFSIZ]; | 474 | char buf[BUFSIZ]; |
460 | char test[] = { 23, 8, 68 }; | 475 | char test[] = { 23, 8, 68 }; |
@@ -465,6 +480,7 @@ ssize_t trace_report(int fd) | |||
465 | ssize_t size; | 480 | ssize_t size; |
466 | 481 | ||
467 | calc_data_size = 1; | 482 | calc_data_size = 1; |
483 | repipe = __repipe; | ||
468 | 484 | ||
469 | input_fd = fd; | 485 | input_fd = fd; |
470 | 486 | ||
@@ -499,6 +515,7 @@ ssize_t trace_report(int fd) | |||
499 | 515 | ||
500 | size = calc_data_size - 1; | 516 | size = calc_data_size - 1; |
501 | calc_data_size = 0; | 517 | calc_data_size = 0; |
518 | repipe = false; | ||
502 | 519 | ||
503 | if (show_funcs) { | 520 | if (show_funcs) { |
504 | print_funcs(); | 521 | print_funcs(); |
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 1f45d468fd9a..ebfee80e4a07 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
@@ -163,7 +163,7 @@ struct record *trace_read_data(int cpu); | |||
163 | 163 | ||
164 | void parse_set_info(int nr_cpus, int long_sz); | 164 | void parse_set_info(int nr_cpus, int long_sz); |
165 | 165 | ||
166 | ssize_t trace_report(int fd); | 166 | ssize_t trace_report(int fd, bool repipe); |
167 | 167 | ||
168 | void *malloc_or_die(unsigned int size); | 168 | void *malloc_or_die(unsigned int size); |
169 | 169 | ||