aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Zanussi <tzanussi@gmail.com>2010-04-02 00:59:21 -0400
committerIngo Molnar <mingo@elte.hu>2010-04-14 05:56:07 -0400
commit9215545e99d8c0b27323df2de504f4294bf5e407 (patch)
treeb53dde70374d2f8a8cd12c44c3637665e559cb16
parentcd19a035f3b63fee6dcbdb5371c4b22276f7dc8c (diff)
perf: Convert perf tracing data into a tracing_data event
Bypasses the tracing_data perf header code and replaces it with a synthesized event and processing function that accomplishes the same thing, used when reading/writing perf data to/from a pipe. The tracing data is pretty large, and this patch doesn't attempt to break it down into component events. The tracing_data event itself doesn't actually contain the tracing data, rather it arranges for the event processing code to skip over it after it's read, using the skip return value added to the event processing loop in a previous patch. Signed-off-by: Tom Zanussi <tzanussi@gmail.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-8-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-record.c16
-rw-r--r--tools/perf/builtin-report.c1
-rw-r--r--tools/perf/builtin-trace.c1
-rw-r--r--tools/perf/util/event.h7
-rw-r--r--tools/perf/util/header.c52
-rw-r--r--tools/perf/util/header.h6
-rw-r--r--tools/perf/util/session.c13
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/trace-event-info.c24
-rw-r--r--tools/perf/util/trace-event-read.c89
-rw-r--r--tools/perf/util/trace-event.h4
11 files changed, 170 insertions, 46 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c4c132205ed6..3775abe2af78 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -104,6 +104,11 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
104 pc->data_tail = tail; 104 pc->data_tail = tail;
105} 105}
106 106
107static void advance_output(size_t size)
108{
109 bytes_written += size;
110}
111
107static void write_output(void *buf, size_t size) 112static void write_output(void *buf, size_t size)
108{ 113{
109 while (size) { 114 while (size) {
@@ -599,6 +604,17 @@ static int __cmd_record(int argc, const char **argv)
599 pr_err("Couldn't synthesize event_types.\n"); 604 pr_err("Couldn't synthesize event_types.\n");
600 return err; 605 return err;
601 } 606 }
607
608 err = event__synthesize_tracing_data(output, attrs,
609 nr_counters,
610 process_synthesized_event,
611 session);
612 if (err <= 0) {
613 pr_err("Couldn't record tracing data.\n");
614 return err;
615 }
616
617 advance_output(err);
602 } 618 }
603 619
604 err = event__synthesize_kernel_mmap(process_synthesized_event, 620 err = event__synthesize_kernel_mmap(process_synthesized_event,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e59d0127d5e3..76f03a70aaca 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -269,6 +269,7 @@ static struct perf_event_ops event_ops = {
269 .read = process_read_event, 269 .read = process_read_event,
270 .attr = event__process_attr, 270 .attr = event__process_attr,
271 .event_type = event__process_event_type, 271 .event_type = event__process_event_type,
272 .tracing_data = event__process_tracing_data,
272}; 273};
273 274
274extern volatile int session_done; 275extern volatile int session_done;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index eb884a7dc24b..1509744429c8 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -106,6 +106,7 @@ static struct perf_event_ops event_ops = {
106 .comm = event__process_comm, 106 .comm = event__process_comm,
107 .attr = event__process_attr, 107 .attr = event__process_attr,
108 .event_type = event__process_event_type, 108 .event_type = event__process_event_type,
109 .tracing_data = event__process_tracing_data,
109}; 110};
110 111
111extern volatile int session_done; 112extern volatile int session_done;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c720fe06f8d7..b896a177ea41 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -86,6 +86,7 @@ struct build_id_event {
86enum perf_header_event_type { /* above any possible kernel type */ 86enum perf_header_event_type { /* above any possible kernel type */
87 PERF_RECORD_HEADER_ATTR = 64, 87 PERF_RECORD_HEADER_ATTR = 64,
88 PERF_RECORD_HEADER_EVENT_TYPE = 65, 88 PERF_RECORD_HEADER_EVENT_TYPE = 65,
89 PERF_RECORD_HEADER_TRACING_DATA = 66,
89 PERF_RECORD_HEADER_MAX 90 PERF_RECORD_HEADER_MAX
90}; 91};
91 92
@@ -107,6 +108,11 @@ struct event_type_event {
107 struct perf_trace_event_type event_type; 108 struct perf_trace_event_type event_type;
108}; 109};
109 110
111struct tracing_data_event {
112 struct perf_event_header header;
113 u32 size;
114};
115
110typedef union event_union { 116typedef union event_union {
111 struct perf_event_header header; 117 struct perf_event_header header;
112 struct ip_event ip; 118 struct ip_event ip;
@@ -118,6 +124,7 @@ typedef union event_union {
118 struct sample_event sample; 124 struct sample_event sample;
119 struct attr_event attr; 125 struct attr_event attr;
120 struct event_type_event event_type; 126 struct event_type_event event_type;
127 struct tracing_data_event tracing_data;
121} event_t; 128} event_t;
122 129
123struct events_stats { 130struct events_stats {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 44637999dbc1..c6874ecc90b8 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -934,3 +934,55 @@ int event__process_event_type(event_t *self,
934 934
935 return 0; 935 return 0;
936} 936}
937
938int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
939 int nb_events,
940 event__handler_t process,
941 struct perf_session *session __unused)
942{
943 event_t ev;
944 ssize_t size = 0, aligned_size = 0, padding;
945 int err = 0;
946
947 memset(&ev, 0, sizeof(ev));
948
949 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
950 size = read_tracing_data_size(fd, pattrs, nb_events);
951 if (size <= 0)
952 return size;
953 aligned_size = ALIGN(size, sizeof(u64));
954 padding = aligned_size - size;
955 ev.tracing_data.header.size = sizeof(ev.tracing_data);
956 ev.tracing_data.size = aligned_size;
957
958 process(&ev, session);
959
960 err = read_tracing_data(fd, pattrs, nb_events);
961 write_padded(fd, NULL, 0, padding);
962
963 return aligned_size;
964}
965
966int event__process_tracing_data(event_t *self,
967 struct perf_session *session)
968{
969 ssize_t size_read, padding, size = self->tracing_data.size;
970 off_t offset = lseek(session->fd, 0, SEEK_CUR);
971 char buf[BUFSIZ];
972
973 /* setup for reading amidst mmap */
974 lseek(session->fd, offset + sizeof(struct tracing_data_event),
975 SEEK_SET);
976
977 size_read = trace_report(session->fd);
978
979 padding = ALIGN(size_read, sizeof(u64)) - size_read;
980
981 if (read(session->fd, buf, padding) < 0)
982 die("reading input file");
983
984 if (size_read + padding != size)
985 die("tracing data size mismatch");
986
987 return size_read + padding;
988}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index afeb61883766..3ed3d98c81d4 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -111,5 +111,11 @@ int event__synthesize_event_types(event__handler_t process,
111int event__process_event_type(event_t *self, 111int event__process_event_type(event_t *self,
112 struct perf_session *session); 112 struct perf_session *session);
113 113
114int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
115 int nb_events,
116 event__handler_t process,
117 struct perf_session *session);
118int event__process_tracing_data(event_t *self,
119 struct perf_session *session);
114 120
115#endif /* __PERF_HEADER_H */ 121#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 96c4629b7740..1516c40d47ac 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -204,6 +204,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
204 handler->attr = process_event_stub; 204 handler->attr = process_event_stub;
205 if (handler->event_type == NULL) 205 if (handler->event_type == NULL)
206 handler->event_type = process_event_stub; 206 handler->event_type = process_event_stub;
207 if (handler->tracing_data == NULL)
208 handler->tracing_data = process_event_stub;
207} 209}
208 210
209static const char *event__name[] = { 211static const char *event__name[] = {
@@ -219,6 +221,7 @@ static const char *event__name[] = {
219 [PERF_RECORD_SAMPLE] = "SAMPLE", 221 [PERF_RECORD_SAMPLE] = "SAMPLE",
220 [PERF_RECORD_HEADER_ATTR] = "ATTR", 222 [PERF_RECORD_HEADER_ATTR] = "ATTR",
221 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 223 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
224 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
222}; 225};
223 226
224unsigned long event__total[PERF_RECORD_HEADER_MAX]; 227unsigned long event__total[PERF_RECORD_HEADER_MAX];
@@ -311,6 +314,11 @@ static void event__event_type_swap(event_t *self)
311 bswap_64(self->event_type.event_type.event_id); 314 bswap_64(self->event_type.event_type.event_id);
312} 315}
313 316
317static void event__tracing_data_swap(event_t *self)
318{
319 self->tracing_data.size = bswap_32(self->tracing_data.size);
320}
321
314typedef void (*event__swap_op)(event_t *self); 322typedef void (*event__swap_op)(event_t *self);
315 323
316static event__swap_op event__swap_ops[] = { 324static event__swap_op event__swap_ops[] = {
@@ -323,6 +331,7 @@ static event__swap_op event__swap_ops[] = {
323 [PERF_RECORD_SAMPLE] = event__all64_swap, 331 [PERF_RECORD_SAMPLE] = event__all64_swap,
324 [PERF_RECORD_HEADER_ATTR] = event__attr_swap, 332 [PERF_RECORD_HEADER_ATTR] = event__attr_swap,
325 [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, 333 [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap,
334 [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap,
326 [PERF_RECORD_HEADER_MAX] = NULL, 335 [PERF_RECORD_HEADER_MAX] = NULL,
327}; 336};
328 337
@@ -367,6 +376,10 @@ static int perf_session__process_event(struct perf_session *self,
367 return ops->attr(event, self); 376 return ops->attr(event, self);
368 case PERF_RECORD_HEADER_EVENT_TYPE: 377 case PERF_RECORD_HEADER_EVENT_TYPE:
369 return ops->event_type(event, self); 378 return ops->event_type(event, self);
379 case PERF_RECORD_HEADER_TRACING_DATA:
380 /* setup for reading amidst mmap */
381 lseek(self->fd, offset + head, SEEK_SET);
382 return ops->tracing_data(event, self);
370 default: 383 default:
371 self->unknown_events++; 384 self->unknown_events++;
372 return -1; 385 return -1;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0dac1f4457d3..0739ebbbf9fd 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -46,7 +46,8 @@ struct perf_event_ops {
46 throttle, 46 throttle,
47 unthrottle, 47 unthrottle,
48 attr, 48 attr,
49 event_type; 49 event_type,
50 tracing_data;
50}; 51};
51 52
52struct perf_session *perf_session__new(const char *filename, int mode, bool force); 53struct perf_session *perf_session__new(const char *filename, int mode, bool force);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 5ea8973ad331..30cd9b575953 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -154,10 +154,17 @@ static void put_tracing_file(char *file)
154 free(file); 154 free(file);
155} 155}
156 156
157static ssize_t calc_data_size;
158
157static ssize_t write_or_die(const void *buf, size_t len) 159static ssize_t write_or_die(const void *buf, size_t len)
158{ 160{
159 int ret; 161 int ret;
160 162
163 if (calc_data_size) {
164 calc_data_size += len;
165 return len;
166 }
167
161 ret = write(output_fd, buf, len); 168 ret = write(output_fd, buf, len);
162 if (ret < 0) 169 if (ret < 0)
163 die("writing to '%s'", output_file); 170 die("writing to '%s'", output_file);
@@ -526,3 +533,20 @@ int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
526 533
527 return 0; 534 return 0;
528} 535}
536
537ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
538 int nb_events)
539{
540 ssize_t size;
541 int err = 0;
542
543 calc_data_size = 1;
544 err = read_tracing_data(fd, pattrs, nb_events);
545 size = calc_data_size - 1;
546 calc_data_size = 0;
547
548 if (err < 0)
549 return err;
550
551 return size;
552}
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 7cd1193918c7..44889c9b5630 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -50,14 +50,37 @@ static int long_size;
50 50
51static unsigned long page_size; 51static unsigned long page_size;
52 52
53static ssize_t calc_data_size;
54
55static int do_read(int fd, void *buf, int size)
56{
57 int rsize = size;
58
59 while (size) {
60 int ret = read(fd, buf, size);
61
62 if (ret <= 0)
63 return -1;
64
65 size -= ret;
66 buf += ret;
67 }
68
69 return rsize;
70}
71
53static int read_or_die(void *data, int size) 72static int read_or_die(void *data, int size)
54{ 73{
55 int r; 74 int r;
56 75
57 r = read(input_fd, data, size); 76 r = do_read(input_fd, data, size);
58 if (r != size) 77 if (r <= 0)
59 die("reading input file (size expected=%d received=%d)", 78 die("reading input file (size expected=%d received=%d)",
60 size, r); 79 size, r);
80
81 if (calc_data_size)
82 calc_data_size += r;
83
61 return r; 84 return r;
62} 85}
63 86
@@ -82,56 +105,28 @@ static char *read_string(void)
82 char buf[BUFSIZ]; 105 char buf[BUFSIZ];
83 char *str = NULL; 106 char *str = NULL;
84 int size = 0; 107 int size = 0;
85 int i;
86 off_t r; 108 off_t r;
109 char c;
87 110
88 for (;;) { 111 for (;;) {
89 r = read(input_fd, buf, BUFSIZ); 112 r = read(input_fd, &c, 1);
90 if (r < 0) 113 if (r < 0)
91 die("reading input file"); 114 die("reading input file");
92 115
93 if (!r) 116 if (!r)
94 die("no data"); 117 die("no data");
95 118
96 for (i = 0; i < r; i++) { 119 buf[size++] = c;
97 if (!buf[i])
98 break;
99 }
100 if (i < r)
101 break;
102 120
103 if (str) { 121 if (!c)
104 size += BUFSIZ; 122 break;
105 str = realloc(str, size);
106 if (!str)
107 die("malloc of size %d", size);
108 memcpy(str + (size - BUFSIZ), buf, BUFSIZ);
109 } else {
110 size = BUFSIZ;
111 str = malloc_or_die(size);
112 memcpy(str, buf, size);
113 }
114 } 123 }
115 124
116 /* trailing \0: */ 125 if (calc_data_size)
117 i++; 126 calc_data_size += size;
118 127
119 /* move the file descriptor to the end of the string */ 128 str = malloc_or_die(size);
120 r = lseek(input_fd, -(r - i), SEEK_CUR); 129 memcpy(str, buf, size);
121 if (r == (off_t)-1)
122 die("lseek");
123
124 if (str) {
125 size += i;
126 str = realloc(str, size);
127 if (!str)
128 die("malloc of size %d", size);
129 memcpy(str + (size - i), buf, i);
130 } else {
131 size = i;
132 str = malloc_or_die(i);
133 memcpy(str, buf, i);
134 }
135 130
136 return str; 131 return str;
137} 132}
@@ -459,7 +454,7 @@ struct record *trace_read_data(int cpu)
459 return data; 454 return data;
460} 455}
461 456
462void trace_report(int fd) 457ssize_t trace_report(int fd)
463{ 458{
464 char buf[BUFSIZ]; 459 char buf[BUFSIZ];
465 char test[] = { 23, 8, 68 }; 460 char test[] = { 23, 8, 68 };
@@ -467,6 +462,9 @@ void trace_report(int fd)
467 int show_version = 0; 462 int show_version = 0;
468 int show_funcs = 0; 463 int show_funcs = 0;
469 int show_printk = 0; 464 int show_printk = 0;
465 ssize_t size;
466
467 calc_data_size = 1;
470 468
471 input_fd = fd; 469 input_fd = fd;
472 470
@@ -499,14 +497,17 @@ void trace_report(int fd)
499 read_proc_kallsyms(); 497 read_proc_kallsyms();
500 read_ftrace_printk(); 498 read_ftrace_printk();
501 499
500 size = calc_data_size - 1;
501 calc_data_size = 0;
502
502 if (show_funcs) { 503 if (show_funcs) {
503 print_funcs(); 504 print_funcs();
504 return; 505 return size;
505 } 506 }
506 if (show_printk) { 507 if (show_printk) {
507 print_printk(); 508 print_printk();
508 return; 509 return size;
509 } 510 }
510 511
511 return; 512 return size;
512} 513}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 81f2fd20a0ea..1f45d468fd9a 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
164void parse_set_info(int nr_cpus, int long_sz); 164void parse_set_info(int nr_cpus, int long_sz);
165 165
166void trace_report(int fd); 166ssize_t trace_report(int fd);
167 167
168void *malloc_or_die(unsigned int size); 168void *malloc_or_die(unsigned int size);
169 169
@@ -259,6 +259,8 @@ void *raw_field_ptr(struct event *event, const char *name, void *data);
259unsigned long long eval_flag(const char *flag); 259unsigned long long eval_flag(const char *flag);
260 260
261int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); 261int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
262ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs,
263 int nb_events);
262 264
263/* taken from kernel/trace/trace.h */ 265/* taken from kernel/trace/trace.h */
264enum trace_flag_type { 266enum trace_flag_type {