perf: Convert perf event types into event type events
authorTom Zanussi <tzanussi@gmail.com>
Fri, 2 Apr 2010 04:59:20 +0000 (23:59 -0500)
committerIngo Molnar <mingo@elte.hu>
Wed, 14 Apr 2010 09:56:07 +0000 (11:56 +0200)
Bypasses the event type 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.

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-7-git-send-email-tzanussi@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-trace.c
tools/perf/util/event.h
tools/perf/util/header.c
tools/perf/util/header.h
tools/perf/util/session.c
tools/perf/util/session.h

index 289d9cf3bf73c927f601a69285e726a3be5179b8..c4c132205ed6880fa5d9c23fddbdcdbb9ef42533 100644 (file)
@@ -592,6 +592,13 @@ static int __cmd_record(int argc, const char **argv)
                        pr_err("Couldn't synthesize attrs.\n");
                        return err;
                }
+
+               err = event__synthesize_event_types(process_synthesized_event,
+                                                   session);
+               if (err < 0) {
+                       pr_err("Couldn't synthesize event_types.\n");
+                       return err;
+               }
        }
 
        err = event__synthesize_kernel_mmap(process_synthesized_event,
index f0486ce591a9d8f3470676a5c0b19d284041e42d..e59d0127d5e3a1b29a9f565a2d6e581e06130d16 100644 (file)
@@ -268,6 +268,7 @@ static struct perf_event_ops event_ops = {
        .lost   = event__process_lost,
        .read   = process_read_event,
        .attr   = event__process_attr,
+       .event_type = event__process_event_type,
 };
 
 extern volatile int session_done;
index e30eac6af5415ca402374e1e4e7ece01736ad512..eb884a7dc24b4eff2e5d8a2bb85f2e1c8f46e521 100644 (file)
@@ -105,6 +105,7 @@ static struct perf_event_ops event_ops = {
        .sample = process_sample_event,
        .comm   = event__process_comm,
        .attr   = event__process_attr,
+       .event_type = event__process_event_type,
 };
 
 extern volatile int session_done;
index b4fbf25078b97c00ae0161c5bfa29059cc04a839..c720fe06f8d7dec9d5cb1028c119e35409cd25c8 100644 (file)
@@ -85,6 +85,7 @@ struct build_id_event {
 
 enum perf_header_event_type { /* above any possible kernel type */
        PERF_RECORD_HEADER_ATTR                 = 64,
+       PERF_RECORD_HEADER_EVENT_TYPE           = 65,
        PERF_RECORD_HEADER_MAX
 };
 
@@ -94,6 +95,18 @@ struct attr_event {
        u64 id[];
 };
 
+#define MAX_EVENT_NAME 64
+
+struct perf_trace_event_type {
+       u64     event_id;
+       char    name[MAX_EVENT_NAME];
+};
+
+struct event_type_event {
+       struct perf_event_header header;
+       struct perf_trace_event_type event_type;
+};
+
 typedef union event_union {
        struct perf_event_header        header;
        struct ip_event                 ip;
@@ -104,6 +117,7 @@ typedef union event_union {
        struct read_event               read;
        struct sample_event             sample;
        struct attr_event               attr;
+       struct event_type_event         event_type;
 } event_t;
 
 struct events_stats {
index e36173934e8b36d14d2e64506f7aafdac017c818..44637999dbc146991d19ff54181c020d8a064e73 100644 (file)
@@ -99,13 +99,6 @@ int perf_header__add_attr(struct perf_header *self,
        return 0;
 }
 
-#define MAX_EVENT_NAME 64
-
-struct perf_trace_event_type {
-       u64     event_id;
-       char    name[MAX_EVENT_NAME];
-};
-
 static int event_count;
 static struct perf_trace_event_type *events;
 
@@ -886,3 +879,58 @@ int event__process_attr(event_t *self, struct perf_session *session)
 
        return 0;
 }
+
+int event__synthesize_event_type(u64 event_id, char *name,
+                                event__handler_t process,
+                                struct perf_session *session)
+{
+       event_t ev;
+       size_t size = 0;
+       int err = 0;
+
+       memset(&ev, 0, sizeof(ev));
+
+       ev.event_type.event_type.event_id = event_id;
+       memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME);
+       strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
+
+       ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
+       size = strlen(name);
+       size = ALIGN(size, sizeof(u64));
+       ev.event_type.header.size = sizeof(ev.event_type) -
+               (sizeof(ev.event_type.event_type.name) - size);
+
+       err = process(&ev, session);
+
+       return err;
+}
+
+int event__synthesize_event_types(event__handler_t process,
+                                 struct perf_session *session)
+{
+       struct perf_trace_event_type *type;
+       int i, err = 0;
+
+       for (i = 0; i < event_count; i++) {
+               type = &events[i];
+
+               err = event__synthesize_event_type(type->event_id, type->name,
+                                                  process, session);
+               if (err) {
+                       pr_debug("failed to create perf header event type\n");
+                       return err;
+               }
+       }
+
+       return err;
+}
+
+int event__process_event_type(event_t *self,
+                             struct perf_session *session __unused)
+{
+       if (perf_header__push_event(self->event_type.event_type.event_id,
+                                   self->event_type.event_type.name) < 0)
+               return -ENOMEM;
+
+       return 0;
+}
index e916ac509a69bc95d35cb6578f3562437f72282e..afeb61883766b275af087e3c5aadf23af3259249 100644 (file)
@@ -103,4 +103,13 @@ int event__synthesize_attrs(struct perf_header *self,
                            struct perf_session *session);
 int event__process_attr(event_t *self, struct perf_session *session);
 
+int event__synthesize_event_type(u64 event_id, char *name,
+                                event__handler_t process,
+                                struct perf_session *session);
+int event__synthesize_event_types(event__handler_t process,
+                                 struct perf_session *session);
+int event__process_event_type(event_t *self,
+                             struct perf_session *session);
+
+
 #endif /* __PERF_HEADER_H */
index bc81864cd04e834a506f0dac03762f8a96fab6e5..96c4629b7740a26d08a701c364757a07af7cd043 100644 (file)
@@ -202,6 +202,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
                handler->unthrottle = process_event_stub;
        if (handler->attr == NULL)
                handler->attr = process_event_stub;
+       if (handler->event_type == NULL)
+               handler->event_type = process_event_stub;
 }
 
 static const char *event__name[] = {
@@ -216,6 +218,7 @@ static const char *event__name[] = {
        [PERF_RECORD_READ]       = "READ",
        [PERF_RECORD_SAMPLE]     = "SAMPLE",
        [PERF_RECORD_HEADER_ATTR]        = "ATTR",
+       [PERF_RECORD_HEADER_EVENT_TYPE]  = "EVENT_TYPE",
 };
 
 unsigned long event__total[PERF_RECORD_HEADER_MAX];
@@ -302,6 +305,12 @@ static void event__attr_swap(event_t *self)
        mem_bswap_64(self->attr.id, size);
 }
 
+static void event__event_type_swap(event_t *self)
+{
+       self->event_type.event_type.event_id =
+               bswap_64(self->event_type.event_type.event_id);
+}
+
 typedef void (*event__swap_op)(event_t *self);
 
 static event__swap_op event__swap_ops[] = {
@@ -313,6 +322,7 @@ static event__swap_op event__swap_ops[] = {
        [PERF_RECORD_READ]   = event__read_swap,
        [PERF_RECORD_SAMPLE] = event__all64_swap,
        [PERF_RECORD_HEADER_ATTR]   = event__attr_swap,
+       [PERF_RECORD_HEADER_EVENT_TYPE]   = event__event_type_swap,
        [PERF_RECORD_HEADER_MAX]    = NULL,
 };
 
@@ -355,6 +365,8 @@ static int perf_session__process_event(struct perf_session *self,
                return ops->unthrottle(event, self);
        case PERF_RECORD_HEADER_ATTR:
                return ops->attr(event, self);
+       case PERF_RECORD_HEADER_EVENT_TYPE:
+               return ops->event_type(event, self);
        default:
                self->unknown_events++;
                return -1;
index 45a13741351ddfa5b5cbe4d7bf0924a52b8f0ce8..0dac1f4457d3447fadfa991276b826fdd97e6f81 100644 (file)
@@ -45,7 +45,8 @@ struct perf_event_ops {
                 read,
                 throttle,
                 unthrottle,
-                attr;
+                attr,
+                event_type;
 };
 
 struct perf_session *perf_session__new(const char *filename, int mode, bool force);