diff options
-rw-r--r-- | tools/perf/builtin-top.c | 143 |
1 files changed, 101 insertions, 42 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 4a9fe22..a02fc41 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -318,7 +318,7 @@ static void show_details(struct sym_entry *syme) } /* - * Symbols will be added here in record_ip and will get out + * Symbols will be added here in event__process_sample and will get out * after decayed. */ static LIST_HEAD(active_symbols); @@ -459,18 +459,18 @@ static void print_sym_table(void) } if (nr_counters == 1) - printf(" samples pcnt"); + printf(" samples pcnt"); else - printf(" weight samples pcnt"); + printf(" weight samples pcnt"); if (verbose) printf(" RIP "); - printf(" kernel function\n"); - printf(" %s _______ _____", + printf(" function DSO\n"); + printf(" %s _______ _____", nr_counters == 1 ? " " : "______"); if (verbose) - printf(" ________________"); - printf(" _______________\n\n"); + printf(" ________________"); + printf(" ________________________________ ________________\n\n"); for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { struct symbol *sym; @@ -486,16 +486,15 @@ static void print_sym_table(void) sum_ksamples)); if (nr_counters == 1 || !display_weighted) - printf("%20.2f - ", syme->weight); + printf("%20.2f ", syme->weight); else - printf("%9.1f %10ld - ", syme->weight, syme->snap_count); + printf("%9.1f %10ld ", syme->weight, syme->snap_count); percent_color_fprintf(stdout, "%4.1f%%", pcnt); if (verbose) - printf(" - %016llx", sym->start); - printf(" : %s", sym->name); - if (syme->map->dso->name[0] == '[') - printf(" \t%s", syme->map->dso->name); + printf(" %016llx", sym->start); + printf(" %-32s", sym->name); + printf(" %s", syme->map->dso->short_name); printf("\n"); } } @@ -818,41 +817,97 @@ static int parse_symbols(void) return 0; } -/* - * Binary search in the histogram table and record the hit: - */ -static void record_ip(u64 ip, int counter) +static void event__process_sample(const event_t *self, int counter) { + u64 ip = self->ip.ip; struct map *map; - struct symbol *sym = kernel_maps__find_symbol(ip, &map); - - if (sym != NULL) { - struct sym_entry *syme = dso__sym_priv(map->dso, sym); - - if (!syme->skip) { - syme->count[counter]++; - record_precise_ip(syme, counter, ip); - pthread_mutex_lock(&active_symbols_lock); - if (list_empty(&syme->node) || !syme->node.next) - __list_insert_active_sym(syme); - pthread_mutex_unlock(&active_symbols_lock); + struct sym_entry *syme; + struct symbol *sym; + + switch (self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK) { + case PERF_RECORD_MISC_USER: { + struct thread *thread = threads__findnew(self->ip.pid); + + if (thread == NULL) return; + + map = thread__find_map(thread, ip); + if (map != NULL) { + ip = map->map_ip(map, ip); + sym = map->dso->find_symbol(map->dso, ip); + if (sym == NULL) + return; + userspace_samples++; + break; } } + /* + * If this is outside of all known maps, + * and is a negative address, try to look it + * up in the kernel dso, as it might be a + * vsyscall or vdso (which executes in user-mode). + */ + if ((long long)ip >= 0) + return; + /* Fall thru */ + case PERF_RECORD_MISC_KERNEL: + sym = kernel_maps__find_symbol(ip, &map); + if (sym == NULL) + return; + break; + default: + return; + } + + syme = dso__sym_priv(map->dso, sym); - samples--; + if (!syme->skip) { + syme->count[counter]++; + record_precise_ip(syme, counter, ip); + pthread_mutex_lock(&active_symbols_lock); + if (list_empty(&syme->node) || !syme->node.next) + __list_insert_active_sym(syme); + pthread_mutex_unlock(&active_symbols_lock); + ++samples; + return; + } } -static void process_event(u64 ip, int counter, int user) +static void event__process_mmap(event_t *self) { - samples++; + struct thread *thread = threads__findnew(self->mmap.pid); + + if (thread != NULL) { + struct map *map = map__new(&self->mmap, NULL, 0, + sizeof(struct sym_entry), + symbol_filter); + if (map != NULL) + thread__insert_map(thread, map); + } +} - if (user) { - userspace_samples++; - return; +static void event__process_comm(event_t *self) +{ + struct thread *thread = threads__findnew(self->comm.pid); + + if (thread != NULL) + thread__set_comm(thread, self->comm.comm); +} + +static int event__process(event_t *event) +{ + switch (event->header.type) { + case PERF_RECORD_COMM: + event__process_comm(event); + break; + case PERF_RECORD_MMAP: + event__process_mmap(event); + break; + default: + break; } - record_ip(ip, counter); + return 0; } struct mmap_data { @@ -925,13 +980,11 @@ static void mmap_read_counter(struct mmap_data *md) event = &event_copy; } + if (event->header.type == PERF_RECORD_SAMPLE) + event__process_sample(event, md->counter); + else + event__process(event); old += size; - - if (event->header.type == PERF_RECORD_SAMPLE) { - int user = - (event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_USER; - process_event(event->ip.ip, md->counter, user); - } } md->prev = old; @@ -973,6 +1026,7 @@ static void start_counter(int i, int counter) } attr->inherit = (cpu < 0) && inherit; + attr->mmap = 1; try_again: fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0); @@ -1031,6 +1085,11 @@ static int __cmd_top(void) int i, counter; int ret; + if (target_pid != -1) + event__synthesize_thread(target_pid, event__process); + else + event__synthesize_threads(event__process); + for (i = 0; i < nr_cpus; i++) { group_fd = -1; for (counter = 0; counter < nr_counters; counter++) |