Merge branch 'sh-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / tools / perf / util / event.c
index 1478ab4..1023f67 100644 (file)
@@ -6,8 +6,9 @@
 #include "string.h"
 #include "strlist.h"
 #include "thread.h"
+#include "thread_map.h"
 
-static const char *event__name[] = {
+static const char *perf_event__names[] = {
        [0]                      = "TOTAL",
        [PERF_RECORD_MMAP]       = "MMAP",
        [PERF_RECORD_LOST]       = "LOST",
@@ -25,16 +26,16 @@ static const char *event__name[] = {
        [PERF_RECORD_FINISHED_ROUND]     = "FINISHED_ROUND",
 };
 
-const char *event__get_event_name(unsigned int id)
+const char *perf_event__name(unsigned int id)
 {
-       if (id >= ARRAY_SIZE(event__name))
+       if (id >= ARRAY_SIZE(perf_event__names))
                return "INVALID";
-       if (!event__name[id])
+       if (!perf_event__names[id])
                return "UNKNOWN";
-       return event__name[id];
+       return perf_event__names[id];
 }
 
-static struct sample_data synth_sample = {
+static struct perf_sample synth_sample = {
        .pid       = -1,
        .tid       = -1,
        .time      = -1,
@@ -43,9 +44,9 @@ static struct sample_data synth_sample = {
        .period    = 1,
 };
 
-static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
-                                   event__handler_t process,
-                                   struct perf_session *session)
+static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid,
+                                        int full, perf_event__handler_t process,
+                                        struct perf_session *session)
 {
        char filename[PATH_MAX];
        char bf[BUFSIZ];
@@ -126,9 +127,10 @@ out:
        return tgid;
 }
 
-static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
-                                        event__handler_t process,
-                                        struct perf_session *session)
+static int perf_event__synthesize_mmap_events(union perf_event *event,
+                                             pid_t pid, pid_t tgid,
+                                             perf_event__handler_t process,
+                                             struct perf_session *session)
 {
        char filename[PATH_MAX];
        FILE *fp;
@@ -199,14 +201,14 @@ static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
        return 0;
 }
 
-int event__synthesize_modules(event__handler_t process,
-                             struct perf_session *session,
-                             struct machine *machine)
+int perf_event__synthesize_modules(perf_event__handler_t process,
+                                  struct perf_session *session,
+                                  struct machine *machine)
 {
        struct rb_node *nd;
        struct map_groups *kmaps = &machine->kmaps;
-       event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
-
+       union perf_event *event = zalloc((sizeof(event->mmap) +
+                                         session->id_hdr_size));
        if (event == NULL) {
                pr_debug("Not enough memory synthesizing mmap event "
                         "for kernel modules\n");
@@ -251,23 +253,25 @@ int event__synthesize_modules(event__handler_t process,
        return 0;
 }
 
-static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
-                                     pid_t pid, event__handler_t process,
+static int __event__synthesize_thread(union perf_event *comm_event,
+                                     union perf_event *mmap_event,
+                                     pid_t pid, perf_event__handler_t process,
                                      struct perf_session *session)
 {
-       pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
+       pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process,
                                            session);
        if (tgid == -1)
                return -1;
-       return event__synthesize_mmap_events(mmap_event, pid, tgid,
+       return perf_event__synthesize_mmap_events(mmap_event, pid, tgid,
                                             process, session);
 }
 
-int event__synthesize_thread(pid_t pid, event__handler_t process,
-                            struct perf_session *session)
+int perf_event__synthesize_thread_map(struct thread_map *threads,
+                                     perf_event__handler_t process,
+                                     struct perf_session *session)
 {
-       event_t *comm_event, *mmap_event;
-       int err = -1;
+       union perf_event *comm_event, *mmap_event;
+       int err = -1, thread;
 
        comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
        if (comm_event == NULL)
@@ -277,8 +281,15 @@ int event__synthesize_thread(pid_t pid, event__handler_t process,
        if (mmap_event == NULL)
                goto out_free_comm;
 
-       err = __event__synthesize_thread(comm_event, mmap_event, pid,
-                                        process, session);
+       err = 0;
+       for (thread = 0; thread < threads->nr; ++thread) {
+               if (__event__synthesize_thread(comm_event, mmap_event,
+                                              threads->map[thread],
+                                              process, session)) {
+                       err = -1;
+                       break;
+               }
+       }
        free(mmap_event);
 out_free_comm:
        free(comm_event);
@@ -286,12 +297,12 @@ out:
        return err;
 }
 
-int event__synthesize_threads(event__handler_t process,
-                             struct perf_session *session)
+int perf_event__synthesize_threads(perf_event__handler_t process,
+                                  struct perf_session *session)
 {
        DIR *proc;
        struct dirent dirent, *next;
-       event_t *comm_event, *mmap_event;
+       union perf_event *comm_event, *mmap_event;
        int err = -1;
 
        comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
@@ -349,10 +360,10 @@ static int find_symbol_cb(void *arg, const char *name, char type,
        return 1;
 }
 
-int event__synthesize_kernel_mmap(event__handler_t process,
-                                 struct perf_session *session,
-                                 struct machine *machine,
-                                 const char *symbol_name)
+int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
+                                      struct perf_session *session,
+                                      struct machine *machine,
+                                      const char *symbol_name)
 {
        size_t size;
        const char *filename, *mmap_name;
@@ -366,8 +377,8 @@ int event__synthesize_kernel_mmap(event__handler_t process,
         * kernels.
         */
        struct process_symbol_args args = { .name = symbol_name, };
-       event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
-
+       union perf_event *event = zalloc((sizeof(event->mmap) +
+                                         session->id_hdr_size));
        if (event == NULL) {
                pr_debug("Not enough memory synthesizing mmap event "
                         "for kernel modules\n");
@@ -413,42 +424,15 @@ int event__synthesize_kernel_mmap(event__handler_t process,
        return err;
 }
 
-static void thread__comm_adjust(struct thread *self, struct hists *hists)
-{
-       char *comm = self->comm;
-
-       if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
-           (!symbol_conf.comm_list ||
-            strlist__has_entry(symbol_conf.comm_list, comm))) {
-               u16 slen = strlen(comm);
-
-               if (hists__new_col_len(hists, HISTC_COMM, slen))
-                       hists__set_col_len(hists, HISTC_THREAD, slen + 6);
-       }
-}
-
-static int thread__set_comm_adjust(struct thread *self, const char *comm,
-                                  struct hists *hists)
-{
-       int ret = thread__set_comm(self, comm);
-
-       if (ret)
-               return ret;
-
-       thread__comm_adjust(self, hists);
-
-       return 0;
-}
-
-int event__process_comm(event_t *self, struct sample_data *sample __used,
-                       struct perf_session *session)
+int perf_event__process_comm(union perf_event *event,
+                            struct perf_sample *sample __used,
+                            struct perf_session *session)
 {
-       struct thread *thread = perf_session__findnew(session, self->comm.tid);
+       struct thread *thread = perf_session__findnew(session, event->comm.tid);
 
-       dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
+       dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid);
 
-       if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm,
-                                                     &session->hists)) {
+       if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
                dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
                return -1;
        }
@@ -456,19 +440,21 @@ int event__process_comm(event_t *self, struct sample_data *sample __used,
        return 0;
 }
 
-int event__process_lost(event_t *self, struct sample_data *sample __used,
-                       struct perf_session *session)
+int perf_event__process_lost(union perf_event *event,
+                            struct perf_sample *sample __used,
+                            struct perf_session *session)
 {
        dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
-                   self->lost.id, self->lost.lost);
-       session->hists.stats.total_lost += self->lost.lost;
+                   event->lost.id, event->lost.lost);
+       session->hists.stats.total_lost += event->lost.lost;
        return 0;
 }
 
-static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
+static void perf_event__set_kernel_mmap_len(union perf_event *event,
+                                           struct map **maps)
 {
-       maps[MAP__FUNCTION]->start = self->mmap.start;
-       maps[MAP__FUNCTION]->end   = self->mmap.start + self->mmap.len;
+       maps[MAP__FUNCTION]->start = event->mmap.start;
+       maps[MAP__FUNCTION]->end   = event->mmap.start + event->mmap.len;
        /*
         * Be a bit paranoid here, some perf.data file came with
         * a zero sized synthesized MMAP event for the kernel.
@@ -477,8 +463,8 @@ static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
                maps[MAP__FUNCTION]->end = ~0ULL;
 }
 
-static int event__process_kernel_mmap(event_t *self,
-                       struct perf_session *session)
+static int perf_event__process_kernel_mmap(union perf_event *event,
+                                          struct perf_session *session)
 {
        struct map *map;
        char kmmap_prefix[PATH_MAX];
@@ -486,9 +472,9 @@ static int event__process_kernel_mmap(event_t *self,
        enum dso_kernel_type kernel_type;
        bool is_kernel_mmap;
 
-       machine = perf_session__findnew_machine(session, self->mmap.pid);
+       machine = perf_session__findnew_machine(session, event->mmap.pid);
        if (!machine) {
-               pr_err("Can't find id %d's machine\n", self->mmap.pid);
+               pr_err("Can't find id %d's machine\n", event->mmap.pid);
                goto out_problem;
        }
 
@@ -498,17 +484,17 @@ static int event__process_kernel_mmap(event_t *self,
        else
                kernel_type = DSO_TYPE_GUEST_KERNEL;
 
-       is_kernel_mmap = memcmp(self->mmap.filename,
+       is_kernel_mmap = memcmp(event->mmap.filename,
                                kmmap_prefix,
                                strlen(kmmap_prefix)) == 0;
-       if (self->mmap.filename[0] == '/' ||
-           (!is_kernel_mmap && self->mmap.filename[0] == '[')) {
+       if (event->mmap.filename[0] == '/' ||
+           (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
 
                char short_module_name[1024];
                char *name, *dot;
 
-               if (self->mmap.filename[0] == '/') {
-                       name = strrchr(self->mmap.filename, '/');
+               if (event->mmap.filename[0] == '/') {
+                       name = strrchr(event->mmap.filename, '/');
                        if (name == NULL)
                                goto out_problem;
 
@@ -520,10 +506,10 @@ static int event__process_kernel_mmap(event_t *self,
                                        "[%.*s]", (int)(dot - name), name);
                        strxfrchar(short_module_name, '-', '_');
                } else
-                       strcpy(short_module_name, self->mmap.filename);
+                       strcpy(short_module_name, event->mmap.filename);
 
-               map = machine__new_module(machine, self->mmap.start,
-                                         self->mmap.filename);
+               map = machine__new_module(machine, event->mmap.start,
+                                         event->mmap.filename);
                if (map == NULL)
                        goto out_problem;
 
@@ -533,9 +519,9 @@ static int event__process_kernel_mmap(event_t *self,
 
                map->dso->short_name = name;
                map->dso->sname_alloc = 1;
-               map->end = map->start + self->mmap.len;
+               map->end = map->start + event->mmap.len;
        } else if (is_kernel_mmap) {
-               const char *symbol_name = (self->mmap.filename +
+               const char *symbol_name = (event->mmap.filename +
                                strlen(kmmap_prefix));
                /*
                 * Should be there already, from the build-id table in
@@ -550,10 +536,10 @@ static int event__process_kernel_mmap(event_t *self,
                if (__machine__create_kernel_maps(machine, kernel) < 0)
                        goto out_problem;
 
-               event_set_kernel_mmap_len(machine->vmlinux_maps, self);
+               perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
                perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
                                                         symbol_name,
-                                                        self->mmap.pgoff);
+                                                        event->mmap.pgoff);
                if (machine__is_default_guest(machine)) {
                        /*
                         * preload dso of guest kernel and modules
@@ -567,22 +553,23 @@ out_problem:
        return -1;
 }
 
-int event__process_mmap(event_t *self, struct sample_data *sample __used,
-                       struct perf_session *session)
+int perf_event__process_mmap(union perf_event *event,
+                            struct perf_sample *sample __used,
+                            struct perf_session *session)
 {
        struct machine *machine;
        struct thread *thread;
        struct map *map;
-       u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+       u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
        int ret = 0;
 
        dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
-                       self->mmap.pid, self->mmap.tid, self->mmap.start,
-                       self->mmap.len, self->mmap.pgoff, self->mmap.filename);
+                       event->mmap.pid, event->mmap.tid, event->mmap.start,
+                       event->mmap.len, event->mmap.pgoff, event->mmap.filename);
 
        if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
            cpumode == PERF_RECORD_MISC_KERNEL) {
-               ret = event__process_kernel_mmap(self, session);
+               ret = perf_event__process_kernel_mmap(event, session);
                if (ret < 0)
                        goto out_problem;
                return 0;
@@ -591,12 +578,12 @@ int event__process_mmap(event_t *self, struct sample_data *sample __used,
        machine = perf_session__find_host_machine(session);
        if (machine == NULL)
                goto out_problem;
-       thread = perf_session__findnew(session, self->mmap.pid);
+       thread = perf_session__findnew(session, event->mmap.pid);
        if (thread == NULL)
                goto out_problem;
-       map = map__new(&machine->user_dsos, self->mmap.start,
-                       self->mmap.len, self->mmap.pgoff,
-                       self->mmap.pid, self->mmap.filename,
+       map = map__new(&machine->user_dsos, event->mmap.start,
+                       event->mmap.len, event->mmap.pgoff,
+                       event->mmap.pid, event->mmap.filename,
                        MAP__FUNCTION);
        if (map == NULL)
                goto out_problem;
@@ -609,16 +596,17 @@ out_problem:
        return 0;
 }
 
-int event__process_task(event_t *self, struct sample_data *sample __used,
-                       struct perf_session *session)
+int perf_event__process_task(union perf_event *event,
+                            struct perf_sample *sample __used,
+                            struct perf_session *session)
 {
-       struct thread *thread = perf_session__findnew(session, self->fork.tid);
-       struct thread *parent = perf_session__findnew(session, self->fork.ptid);
+       struct thread *thread = perf_session__findnew(session, event->fork.tid);
+       struct thread *parent = perf_session__findnew(session, event->fork.ptid);
 
-       dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
-                   self->fork.ppid, self->fork.ptid);
+       dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
+                   event->fork.ppid, event->fork.ptid);
 
-       if (self->header.type == PERF_RECORD_EXIT) {
+       if (event->header.type == PERF_RECORD_EXIT) {
                perf_session__remove_thread(session, thread);
                return 0;
        }
@@ -632,20 +620,22 @@ int event__process_task(event_t *self, struct sample_data *sample __used,
        return 0;
 }
 
-int event__process(event_t *event, struct sample_data *sample,
-                  struct perf_session *session)
+int perf_event__process(union perf_event *event, struct perf_sample *sample,
+                       struct perf_session *session)
 {
        switch (event->header.type) {
        case PERF_RECORD_COMM:
-               event__process_comm(event, sample, session);
+               perf_event__process_comm(event, sample, session);
                break;
        case PERF_RECORD_MMAP:
-               event__process_mmap(event, sample, session);
+               perf_event__process_mmap(event, sample, session);
                break;
        case PERF_RECORD_FORK:
        case PERF_RECORD_EXIT:
-               event__process_task(event, sample, session);
+               perf_event__process_task(event, sample, session);
                break;
+       case PERF_RECORD_LOST:
+               perf_event__process_lost(event, sample, session);
        default:
                break;
        }
@@ -720,7 +710,7 @@ try_again:
                 * in the whole kernel symbol list.
                 */
                if ((long long)al->addr < 0 &&
-                   cpumode == PERF_RECORD_MISC_KERNEL &&
+                   cpumode == PERF_RECORD_MISC_USER &&
                    machine && mg != &machine->kmaps) {
                        mg = &machine->kmaps;
                        goto try_again;
@@ -742,24 +732,14 @@ void thread__find_addr_location(struct thread *self,
                al->sym = NULL;
 }
 
-static void dso__calc_col_width(struct dso *self, struct hists *hists)
-{
-       if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
-           (!symbol_conf.dso_list ||
-            strlist__has_entry(symbol_conf.dso_list, self->name))) {
-               u16 slen = dso__name_len(self);
-               hists__new_col_len(hists, HISTC_DSO, slen);
-       }
-
-       self->slen_calculated = 1;
-}
-
-int event__preprocess_sample(const event_t *self, struct perf_session *session,
-                            struct addr_location *al, struct sample_data *data,
-                            symbol_filter_t filter)
+int perf_event__preprocess_sample(const union perf_event *event,
+                                 struct perf_session *session,
+                                 struct addr_location *al,
+                                 struct perf_sample *sample,
+                                 symbol_filter_t filter)
 {
-       u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-       struct thread *thread = perf_session__findnew(session, self->ip.pid);
+       u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+       struct thread *thread = perf_session__findnew(session, event->ip.pid);
 
        if (thread == NULL)
                return -1;
@@ -781,12 +761,12 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
                machine__create_kernel_maps(&session->host_machine);
 
        thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
-                             self->ip.pid, self->ip.ip, al);
+                             event->ip.pid, event->ip.ip, al);
        dump_printf(" ...... dso: %s\n",
                    al->map ? al->map->dso->long_name :
                        al->level == 'H' ? "[hypervisor]" : "<not found>");
        al->sym = NULL;
-       al->cpu = data->cpu;
+       al->cpu = sample->cpu;
 
        if (al->map) {
                if (symbol_conf.dso_list &&
@@ -797,23 +777,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
                        strlist__has_entry(symbol_conf.dso_list,
                                           al->map->dso->long_name)))))
                        goto out_filtered;
-               /*
-                * We have to do this here as we may have a dso with no symbol
-                * hit that has a name longer than the ones with symbols
-                * sampled.
-                */
-               if (!sort_dso.elide && !al->map->dso->slen_calculated)
-                       dso__calc_col_width(al->map->dso, &session->hists);
 
                al->sym = map__find_symbol(al->map, al->addr, filter);
-       } else {
-               const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
-
-               if (hists__col_len(&session->hists, HISTC_DSO) < unresolved_col_width &&
-                   !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
-                   !symbol_conf.dso_list)
-                       hists__set_col_len(&session->hists, HISTC_DSO,
-                                          unresolved_col_width);
        }
 
        if (symbol_conf.sym_list && al->sym &&
@@ -826,128 +791,3 @@ out_filtered:
        al->filtered = true;
        return 0;
 }
-
-static int event__parse_id_sample(const event_t *event,
-                                 struct perf_session *session,
-                                 struct sample_data *sample)
-{
-       const u64 *array;
-       u64 type;
-
-       sample->cpu = sample->pid = sample->tid = -1;
-       sample->stream_id = sample->id = sample->time = -1ULL;
-
-       if (!session->sample_id_all)
-               return 0;
-
-       array = event->sample.array;
-       array += ((event->header.size -
-                  sizeof(event->header)) / sizeof(u64)) - 1;
-       type = session->sample_type;
-
-       if (type & PERF_SAMPLE_CPU) {
-               u32 *p = (u32 *)array;
-               sample->cpu = *p;
-               array--;
-       }
-
-       if (type & PERF_SAMPLE_STREAM_ID) {
-               sample->stream_id = *array;
-               array--;
-       }
-
-       if (type & PERF_SAMPLE_ID) {
-               sample->id = *array;
-               array--;
-       }
-
-       if (type & PERF_SAMPLE_TIME) {
-               sample->time = *array;
-               array--;
-       }
-
-       if (type & PERF_SAMPLE_TID) {
-               u32 *p = (u32 *)array;
-               sample->pid = p[0];
-               sample->tid = p[1];
-       }
-
-       return 0;
-}
-
-int event__parse_sample(const event_t *event, struct perf_session *session,
-                       struct sample_data *data)
-{
-       const u64 *array;
-       u64 type;
-
-       if (event->header.type != PERF_RECORD_SAMPLE)
-               return event__parse_id_sample(event, session, data);
-
-       array = event->sample.array;
-       type = session->sample_type;
-
-       if (type & PERF_SAMPLE_IP) {
-               data->ip = event->ip.ip;
-               array++;
-       }
-
-       if (type & PERF_SAMPLE_TID) {
-               u32 *p = (u32 *)array;
-               data->pid = p[0];
-               data->tid = p[1];
-               array++;
-       }
-
-       if (type & PERF_SAMPLE_TIME) {
-               data->time = *array;
-               array++;
-       }
-
-       if (type & PERF_SAMPLE_ADDR) {
-               data->addr = *array;
-               array++;
-       }
-
-       data->id = -1ULL;
-       if (type & PERF_SAMPLE_ID) {
-               data->id = *array;
-               array++;
-       }
-
-       if (type & PERF_SAMPLE_STREAM_ID) {
-               data->stream_id = *array;
-               array++;
-       }
-
-       if (type & PERF_SAMPLE_CPU) {
-               u32 *p = (u32 *)array;
-               data->cpu = *p;
-               array++;
-       } else
-               data->cpu = -1;
-
-       if (type & PERF_SAMPLE_PERIOD) {
-               data->period = *array;
-               array++;
-       }
-
-       if (type & PERF_SAMPLE_READ) {
-               pr_debug("PERF_SAMPLE_READ is unsuported for now\n");
-               return -1;
-       }
-
-       if (type & PERF_SAMPLE_CALLCHAIN) {
-               data->callchain = (struct ip_callchain *)array;
-               array += 1 + data->callchain->nr;
-       }
-
-       if (type & PERF_SAMPLE_RAW) {
-               u32 *p = (u32 *)array;
-               data->raw_size = *p;
-               p++;
-               data->raw_data = p;
-       }
-
-       return 0;
-}