diff options
-rw-r--r-- | tools/perf/builtin-record.c | 7 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 1 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 1 | ||||
-rw-r--r-- | tools/perf/util/event.h | 14 | ||||
-rw-r--r-- | tools/perf/util/header.c | 62 | ||||
-rw-r--r-- | tools/perf/util/header.h | 9 | ||||
-rw-r--r-- | tools/perf/util/session.c | 12 | ||||
-rw-r--r-- | tools/perf/util/session.h | 3 |
8 files changed, 101 insertions, 8 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 289d9cf3bf73..c4c132205ed6 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -592,6 +592,13 @@ static int __cmd_record(int argc, const char **argv) | |||
592 | pr_err("Couldn't synthesize attrs.\n"); | 592 | pr_err("Couldn't synthesize attrs.\n"); |
593 | return err; | 593 | return err; |
594 | } | 594 | } |
595 | |||
596 | err = event__synthesize_event_types(process_synthesized_event, | ||
597 | session); | ||
598 | if (err < 0) { | ||
599 | pr_err("Couldn't synthesize event_types.\n"); | ||
600 | return err; | ||
601 | } | ||
595 | } | 602 | } |
596 | 603 | ||
597 | err = event__synthesize_kernel_mmap(process_synthesized_event, | 604 | err = event__synthesize_kernel_mmap(process_synthesized_event, |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f0486ce591a9..e59d0127d5e3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -268,6 +268,7 @@ static struct perf_event_ops event_ops = { | |||
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 | .attr = event__process_attr, |
271 | .event_type = event__process_event_type, | ||
271 | }; | 272 | }; |
272 | 273 | ||
273 | extern volatile int session_done; | 274 | extern volatile int session_done; |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e30eac6af541..eb884a7dc24b 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -105,6 +105,7 @@ static 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 | .attr = event__process_attr, |
108 | .event_type = event__process_event_type, | ||
108 | }; | 109 | }; |
109 | 110 | ||
110 | extern volatile int session_done; | 111 | extern volatile int session_done; |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index b4fbf25078b9..c720fe06f8d7 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -85,6 +85,7 @@ struct build_id_event { | |||
85 | 85 | ||
86 | enum perf_header_event_type { /* above any possible kernel type */ | 86 | enum 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_MAX | 89 | PERF_RECORD_HEADER_MAX |
89 | }; | 90 | }; |
90 | 91 | ||
@@ -94,6 +95,18 @@ struct attr_event { | |||
94 | u64 id[]; | 95 | u64 id[]; |
95 | }; | 96 | }; |
96 | 97 | ||
98 | #define MAX_EVENT_NAME 64 | ||
99 | |||
100 | struct perf_trace_event_type { | ||
101 | u64 event_id; | ||
102 | char name[MAX_EVENT_NAME]; | ||
103 | }; | ||
104 | |||
105 | struct event_type_event { | ||
106 | struct perf_event_header header; | ||
107 | struct perf_trace_event_type event_type; | ||
108 | }; | ||
109 | |||
97 | typedef union event_union { | 110 | typedef union event_union { |
98 | struct perf_event_header header; | 111 | struct perf_event_header header; |
99 | struct ip_event ip; | 112 | struct ip_event ip; |
@@ -104,6 +117,7 @@ typedef union event_union { | |||
104 | struct read_event read; | 117 | struct read_event read; |
105 | struct sample_event sample; | 118 | struct sample_event sample; |
106 | struct attr_event attr; | 119 | struct attr_event attr; |
120 | struct event_type_event event_type; | ||
107 | } event_t; | 121 | } event_t; |
108 | 122 | ||
109 | struct events_stats { | 123 | struct events_stats { |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index e36173934e8b..44637999dbc1 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -99,13 +99,6 @@ int perf_header__add_attr(struct perf_header *self, | |||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | 101 | ||
102 | #define MAX_EVENT_NAME 64 | ||
103 | |||
104 | struct perf_trace_event_type { | ||
105 | u64 event_id; | ||
106 | char name[MAX_EVENT_NAME]; | ||
107 | }; | ||
108 | |||
109 | static int event_count; | 102 | static int event_count; |
110 | static struct perf_trace_event_type *events; | 103 | static struct perf_trace_event_type *events; |
111 | 104 | ||
@@ -886,3 +879,58 @@ int event__process_attr(event_t *self, struct perf_session *session) | |||
886 | 879 | ||
887 | return 0; | 880 | return 0; |
888 | } | 881 | } |
882 | |||
883 | int event__synthesize_event_type(u64 event_id, char *name, | ||
884 | event__handler_t process, | ||
885 | struct perf_session *session) | ||
886 | { | ||
887 | event_t ev; | ||
888 | size_t size = 0; | ||
889 | int err = 0; | ||
890 | |||
891 | memset(&ev, 0, sizeof(ev)); | ||
892 | |||
893 | ev.event_type.event_type.event_id = event_id; | ||
894 | memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME); | ||
895 | strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); | ||
896 | |||
897 | ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; | ||
898 | size = strlen(name); | ||
899 | size = ALIGN(size, sizeof(u64)); | ||
900 | ev.event_type.header.size = sizeof(ev.event_type) - | ||
901 | (sizeof(ev.event_type.event_type.name) - size); | ||
902 | |||
903 | err = process(&ev, session); | ||
904 | |||
905 | return err; | ||
906 | } | ||
907 | |||
908 | int event__synthesize_event_types(event__handler_t process, | ||
909 | struct perf_session *session) | ||
910 | { | ||
911 | struct perf_trace_event_type *type; | ||
912 | int i, err = 0; | ||
913 | |||
914 | for (i = 0; i < event_count; i++) { | ||
915 | type = &events[i]; | ||
916 | |||
917 | err = event__synthesize_event_type(type->event_id, type->name, | ||
918 | process, session); | ||
919 | if (err) { | ||
920 | pr_debug("failed to create perf header event type\n"); | ||
921 | return err; | ||
922 | } | ||
923 | } | ||
924 | |||
925 | return err; | ||
926 | } | ||
927 | |||
928 | int event__process_event_type(event_t *self, | ||
929 | struct perf_session *session __unused) | ||
930 | { | ||
931 | if (perf_header__push_event(self->event_type.event_type.event_id, | ||
932 | self->event_type.event_type.name) < 0) | ||
933 | return -ENOMEM; | ||
934 | |||
935 | return 0; | ||
936 | } | ||
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index e916ac509a69..afeb61883766 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -103,4 +103,13 @@ int event__synthesize_attrs(struct perf_header *self, | |||
103 | struct perf_session *session); | 103 | struct perf_session *session); |
104 | int event__process_attr(event_t *self, struct perf_session *session); | 104 | int event__process_attr(event_t *self, struct perf_session *session); |
105 | 105 | ||
106 | int event__synthesize_event_type(u64 event_id, char *name, | ||
107 | event__handler_t process, | ||
108 | struct perf_session *session); | ||
109 | int event__synthesize_event_types(event__handler_t process, | ||
110 | struct perf_session *session); | ||
111 | int event__process_event_type(event_t *self, | ||
112 | struct perf_session *session); | ||
113 | |||
114 | |||
106 | #endif /* __PERF_HEADER_H */ | 115 | #endif /* __PERF_HEADER_H */ |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index bc81864cd04e..96c4629b7740 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -202,6 +202,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) | |||
202 | handler->unthrottle = process_event_stub; | 202 | handler->unthrottle = process_event_stub; |
203 | if (handler->attr == NULL) | 203 | if (handler->attr == NULL) |
204 | handler->attr = process_event_stub; | 204 | handler->attr = process_event_stub; |
205 | if (handler->event_type == NULL) | ||
206 | handler->event_type = process_event_stub; | ||
205 | } | 207 | } |
206 | 208 | ||
207 | static const char *event__name[] = { | 209 | static const char *event__name[] = { |
@@ -216,6 +218,7 @@ static const char *event__name[] = { | |||
216 | [PERF_RECORD_READ] = "READ", | 218 | [PERF_RECORD_READ] = "READ", |
217 | [PERF_RECORD_SAMPLE] = "SAMPLE", | 219 | [PERF_RECORD_SAMPLE] = "SAMPLE", |
218 | [PERF_RECORD_HEADER_ATTR] = "ATTR", | 220 | [PERF_RECORD_HEADER_ATTR] = "ATTR", |
221 | [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", | ||
219 | }; | 222 | }; |
220 | 223 | ||
221 | unsigned long event__total[PERF_RECORD_HEADER_MAX]; | 224 | unsigned long event__total[PERF_RECORD_HEADER_MAX]; |
@@ -302,6 +305,12 @@ static void event__attr_swap(event_t *self) | |||
302 | mem_bswap_64(self->attr.id, size); | 305 | mem_bswap_64(self->attr.id, size); |
303 | } | 306 | } |
304 | 307 | ||
308 | static void event__event_type_swap(event_t *self) | ||
309 | { | ||
310 | self->event_type.event_type.event_id = | ||
311 | bswap_64(self->event_type.event_type.event_id); | ||
312 | } | ||
313 | |||
305 | typedef void (*event__swap_op)(event_t *self); | 314 | typedef void (*event__swap_op)(event_t *self); |
306 | 315 | ||
307 | static event__swap_op event__swap_ops[] = { | 316 | static event__swap_op event__swap_ops[] = { |
@@ -313,6 +322,7 @@ static event__swap_op event__swap_ops[] = { | |||
313 | [PERF_RECORD_READ] = event__read_swap, | 322 | [PERF_RECORD_READ] = event__read_swap, |
314 | [PERF_RECORD_SAMPLE] = event__all64_swap, | 323 | [PERF_RECORD_SAMPLE] = event__all64_swap, |
315 | [PERF_RECORD_HEADER_ATTR] = event__attr_swap, | 324 | [PERF_RECORD_HEADER_ATTR] = event__attr_swap, |
325 | [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, | ||
316 | [PERF_RECORD_HEADER_MAX] = NULL, | 326 | [PERF_RECORD_HEADER_MAX] = NULL, |
317 | }; | 327 | }; |
318 | 328 | ||
@@ -355,6 +365,8 @@ static int perf_session__process_event(struct perf_session *self, | |||
355 | return ops->unthrottle(event, self); | 365 | return ops->unthrottle(event, self); |
356 | case PERF_RECORD_HEADER_ATTR: | 366 | case PERF_RECORD_HEADER_ATTR: |
357 | return ops->attr(event, self); | 367 | return ops->attr(event, self); |
368 | case PERF_RECORD_HEADER_EVENT_TYPE: | ||
369 | return ops->event_type(event, self); | ||
358 | default: | 370 | default: |
359 | self->unknown_events++; | 371 | self->unknown_events++; |
360 | return -1; | 372 | return -1; |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 45a13741351d..0dac1f4457d3 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -45,7 +45,8 @@ struct perf_event_ops { | |||
45 | read, | 45 | read, |
46 | throttle, | 46 | throttle, |
47 | unthrottle, | 47 | unthrottle, |
48 | attr; | 48 | attr, |
49 | event_type; | ||
49 | }; | 50 | }; |
50 | 51 | ||
51 | struct perf_session *perf_session__new(const char *filename, int mode, bool force); | 52 | struct perf_session *perf_session__new(const char *filename, int mode, bool force); |