aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Zanussi <tzanussi@gmail.com>2010-04-02 00:59:19 -0400
committerIngo Molnar <mingo@elte.hu>2010-04-14 05:56:07 -0400
commit2c46dbb517a10b18d459e6ceffefde5bfb290cf6 (patch)
tree20853decc73cd1fc69c2db7d8227d11cce6ee4de
parentc239da3b4b55dbb8f30bcb8d1a0d63fc44a567c3 (diff)
perf: Convert perf header attrs into attr events
Bypasses the attr 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. Making the attrs into events allows them to be streamed over a pipe along with the rest of the header data (in later patches). It also paves the way to allowing events to be added and removed from perf sessions dynamically. 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-6-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-record.c10
-rw-r--r--tools/perf/builtin-report.c1
-rw-r--r--tools/perf/builtin-trace.c1
-rw-r--r--tools/perf/util/event.h10
-rw-r--r--tools/perf/util/header.c79
-rw-r--r--tools/perf/util/header.h8
-rw-r--r--tools/perf/util/session.c26
-rw-r--r--tools/perf/util/session.h3
8 files changed, 136 insertions, 2 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d4464f7fcea5..289d9cf3bf73 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -584,6 +584,16 @@ static int __cmd_record(int argc, const char **argv)
584 584
585 post_processing_offset = lseek(output, 0, SEEK_CUR); 585 post_processing_offset = lseek(output, 0, SEEK_CUR);
586 586
587 if (pipe_output) {
588 err = event__synthesize_attrs(&session->header,
589 process_synthesized_event,
590 session);
591 if (err < 0) {
592 pr_err("Couldn't synthesize attrs.\n");
593 return err;
594 }
595 }
596
587 err = event__synthesize_kernel_mmap(process_synthesized_event, 597 err = event__synthesize_kernel_mmap(process_synthesized_event,
588 session, "_text"); 598 session, "_text");
589 if (err < 0) 599 if (err < 0)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 00b358ff135c..f0486ce591a9 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -267,6 +267,7 @@ static struct perf_event_ops event_ops = {
267 .fork = event__process_task, 267 .fork = event__process_task,
268 .lost = event__process_lost, 268 .lost = event__process_lost,
269 .read = process_read_event, 269 .read = process_read_event,
270 .attr = event__process_attr,
270}; 271};
271 272
272extern volatile int session_done; 273extern volatile int session_done;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c681e85a912c..e30eac6af541 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -104,6 +104,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
104static struct perf_event_ops event_ops = { 104static struct perf_event_ops event_ops = {
105 .sample = process_sample_event, 105 .sample = process_sample_event,
106 .comm = event__process_comm, 106 .comm = event__process_comm,
107 .attr = event__process_attr,
107}; 108};
108 109
109extern volatile int session_done; 110extern volatile int session_done;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 5c1eba671305..b4fbf25078b9 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -84,7 +84,14 @@ struct build_id_event {
84}; 84};
85 85
86enum perf_header_event_type { /* above any possible kernel type */ 86enum perf_header_event_type { /* above any possible kernel type */
87 PERF_RECORD_HEADER_MAX = 64, 87 PERF_RECORD_HEADER_ATTR = 64,
88 PERF_RECORD_HEADER_MAX
89};
90
91struct attr_event {
92 struct perf_event_header header;
93 struct perf_event_attr attr;
94 u64 id[];
88}; 95};
89 96
90typedef union event_union { 97typedef union event_union {
@@ -96,6 +103,7 @@ typedef union event_union {
96 struct lost_event lost; 103 struct lost_event lost;
97 struct read_event read; 104 struct read_event read;
98 struct sample_event sample; 105 struct sample_event sample;
106 struct attr_event attr;
99} event_t; 107} event_t;
100 108
101struct events_stats { 109struct events_stats {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 8d05337d1a59..e36173934e8b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -807,3 +807,82 @@ perf_header__find_attr(u64 id, struct perf_header *header)
807 807
808 return NULL; 808 return NULL;
809} 809}
810
811int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
812 event__handler_t process,
813 struct perf_session *session)
814{
815 event_t *ev;
816 size_t size;
817 int err;
818
819 size = sizeof(struct perf_event_attr);
820 size = ALIGN(size, sizeof(u64));
821 size += sizeof(struct perf_event_header);
822 size += ids * sizeof(u64);
823
824 ev = malloc(size);
825
826 ev->attr.attr = *attr;
827 memcpy(ev->attr.id, id, ids * sizeof(u64));
828
829 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
830 ev->attr.header.size = size;
831
832 err = process(ev, session);
833
834 free(ev);
835
836 return err;
837}
838
839int event__synthesize_attrs(struct perf_header *self,
840 event__handler_t process,
841 struct perf_session *session)
842{
843 struct perf_header_attr *attr;
844 int i, err = 0;
845
846 for (i = 0; i < self->attrs; i++) {
847 attr = self->attr[i];
848
849 err = event__synthesize_attr(&attr->attr, attr->ids, attr->id,
850 process, session);
851 if (err) {
852 pr_debug("failed to create perf header attribute\n");
853 return err;
854 }
855 }
856
857 return err;
858}
859
860int event__process_attr(event_t *self, struct perf_session *session)
861{
862 struct perf_header_attr *attr;
863 unsigned int i, ids, n_ids;
864
865 attr = perf_header_attr__new(&self->attr.attr);
866 if (attr == NULL)
867 return -ENOMEM;
868
869 ids = self->header.size;
870 ids -= (void *)&self->attr.id - (void *)self;
871 n_ids = ids / sizeof(u64);
872
873 for (i = 0; i < n_ids; i++) {
874 if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) {
875 perf_header_attr__delete(attr);
876 return -ENOMEM;
877 }
878 }
879
880 if (perf_header__add_attr(&session->header, attr) < 0) {
881 perf_header_attr__delete(attr);
882 return -ENOMEM;
883 }
884
885 perf_session__update_sample_type(session);
886
887 return 0;
888}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6562ece67064..e916ac509a69 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -95,4 +95,12 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
95 const char *name, bool is_kallsyms); 95 const char *name, bool is_kallsyms);
96int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 96int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
97 97
98int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
99 event__handler_t process,
100 struct perf_session *session);
101int event__synthesize_attrs(struct perf_header *self,
102 event__handler_t process,
103 struct perf_session *session);
104int event__process_attr(event_t *self, struct perf_session *session);
105
98#endif /* __PERF_HEADER_H */ 106#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 2c1277cb4ae4..bc81864cd04e 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -200,6 +200,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
200 handler->throttle = process_event_stub; 200 handler->throttle = process_event_stub;
201 if (handler->unthrottle == NULL) 201 if (handler->unthrottle == NULL)
202 handler->unthrottle = process_event_stub; 202 handler->unthrottle = process_event_stub;
203 if (handler->attr == NULL)
204 handler->attr = process_event_stub;
203} 205}
204 206
205static const char *event__name[] = { 207static const char *event__name[] = {
@@ -213,6 +215,7 @@ static const char *event__name[] = {
213 [PERF_RECORD_FORK] = "FORK", 215 [PERF_RECORD_FORK] = "FORK",
214 [PERF_RECORD_READ] = "READ", 216 [PERF_RECORD_READ] = "READ",
215 [PERF_RECORD_SAMPLE] = "SAMPLE", 217 [PERF_RECORD_SAMPLE] = "SAMPLE",
218 [PERF_RECORD_HEADER_ATTR] = "ATTR",
216}; 219};
217 220
218unsigned long event__total[PERF_RECORD_HEADER_MAX]; 221unsigned long event__total[PERF_RECORD_HEADER_MAX];
@@ -279,6 +282,26 @@ static void event__read_swap(event_t *self)
279 self->read.id = bswap_64(self->read.id); 282 self->read.id = bswap_64(self->read.id);
280} 283}
281 284
285static void event__attr_swap(event_t *self)
286{
287 size_t size;
288
289 self->attr.attr.type = bswap_32(self->attr.attr.type);
290 self->attr.attr.size = bswap_32(self->attr.attr.size);
291 self->attr.attr.config = bswap_64(self->attr.attr.config);
292 self->attr.attr.sample_period = bswap_64(self->attr.attr.sample_period);
293 self->attr.attr.sample_type = bswap_64(self->attr.attr.sample_type);
294 self->attr.attr.read_format = bswap_64(self->attr.attr.read_format);
295 self->attr.attr.wakeup_events = bswap_32(self->attr.attr.wakeup_events);
296 self->attr.attr.bp_type = bswap_32(self->attr.attr.bp_type);
297 self->attr.attr.bp_addr = bswap_64(self->attr.attr.bp_addr);
298 self->attr.attr.bp_len = bswap_64(self->attr.attr.bp_len);
299
300 size = self->header.size;
301 size -= (void *)&self->attr.id - (void *)self;
302 mem_bswap_64(self->attr.id, size);
303}
304
282typedef void (*event__swap_op)(event_t *self); 305typedef void (*event__swap_op)(event_t *self);
283 306
284static event__swap_op event__swap_ops[] = { 307static event__swap_op event__swap_ops[] = {
@@ -289,6 +312,7 @@ static event__swap_op event__swap_ops[] = {
289 [PERF_RECORD_LOST] = event__all64_swap, 312 [PERF_RECORD_LOST] = event__all64_swap,
290 [PERF_RECORD_READ] = event__read_swap, 313 [PERF_RECORD_READ] = event__read_swap,
291 [PERF_RECORD_SAMPLE] = event__all64_swap, 314 [PERF_RECORD_SAMPLE] = event__all64_swap,
315 [PERF_RECORD_HEADER_ATTR] = event__attr_swap,
292 [PERF_RECORD_HEADER_MAX] = NULL, 316 [PERF_RECORD_HEADER_MAX] = NULL,
293}; 317};
294 318
@@ -329,6 +353,8 @@ static int perf_session__process_event(struct perf_session *self,
329 return ops->throttle(event, self); 353 return ops->throttle(event, self);
330 case PERF_RECORD_UNTHROTTLE: 354 case PERF_RECORD_UNTHROTTLE:
331 return ops->unthrottle(event, self); 355 return ops->unthrottle(event, self);
356 case PERF_RECORD_HEADER_ATTR:
357 return ops->attr(event, self);
332 default: 358 default:
333 self->unknown_events++; 359 self->unknown_events++;
334 return -1; 360 return -1;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 5f7891136655..45a13741351d 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -44,7 +44,8 @@ struct perf_event_ops {
44 lost, 44 lost,
45 read, 45 read,
46 throttle, 46 throttle,
47 unthrottle; 47 unthrottle,
48 attr;
48}; 49};
49 50
50struct perf_session *perf_session__new(const char *filename, int mode, bool force); 51struct perf_session *perf_session__new(const char *filename, int mode, bool force);