diff options
-rw-r--r-- | tools/perf/builtin-annotate.c | 9 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 14 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 48 | ||||
-rw-r--r-- | tools/perf/util/callchain.c | 7 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 4 | ||||
-rw-r--r-- | tools/perf/util/event.c | 27 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 46 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 5 | ||||
-rw-r--r-- | tools/perf/util/map.c | 24 | ||||
-rw-r--r-- | tools/perf/util/session.c | 8 | ||||
-rw-r--r-- | tools/perf/util/session.h | 14 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 2 |
13 files changed, 109 insertions, 101 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ee154b58772..c7ac45a59ed 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -72,8 +72,6 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) struct sym_priv *priv; struct sym_hist *h; - he->count++; - if (!sym || !he->ms.map) return 0; @@ -99,9 +97,8 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) } static int perf_session__add_hist_entry(struct perf_session *self, - struct addr_location *al, u64 count) + struct addr_location *al) { - bool hit; struct hist_entry *he; if (sym_hist_filter != NULL && @@ -115,7 +112,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, return 0; } - he = __perf_session__add_hist_entry(&self->hists, al, NULL, count, &hit); + he = __perf_session__add_hist_entry(&self->hists, al, NULL, 1); if (he == NULL) return -ENOMEM; @@ -135,7 +132,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) return -1; } - if (!al.filtered && perf_session__add_hist_entry(session, &al, 1)) { + if (!al.filtered && perf_session__add_hist_entry(session, &al)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); return -1; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 4cce68f2368..613a5c4f6d8 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -25,17 +25,9 @@ static bool show_displacement; static int perf_session__add_hist_entry(struct perf_session *self, struct addr_location *al, u64 count) { - bool hit; - struct hist_entry *he = __perf_session__add_hist_entry(&self->hists, - al, NULL, - count, &hit); - if (he == NULL) - return -ENOMEM; - - if (hit) - __perf_session__add_count(he, al, count); - - return 0; + if (__perf_session__add_hist_entry(&self->hists, al, NULL, count) != NULL) + return 0; + return -ENOMEM; } static int diff__process_sample_event(event_t *event, struct perf_session *session) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 196473b5125..642a6d8eb5d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -82,8 +82,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, { struct map_symbol *syms = NULL; struct symbol *parent = NULL; - bool hit; - int err; + int err = -ENOMEM; struct hist_entry *he; struct event_stat_id *stats; struct perf_event_attr *attr; @@ -101,39 +100,17 @@ static int perf_session__add_hist_entry(struct perf_session *self, else stats = get_stats(self, data->id, 0, 0); if (stats == NULL) - return -ENOMEM; + goto out_free_syms; he = __perf_session__add_hist_entry(&stats->hists, al, parent, - data->period, &hit); + data->period); if (he == NULL) - return -ENOMEM; - - if (hit) - __perf_session__add_count(he, al, data->period); - - if (symbol_conf.use_callchain) { - if (!hit) - callchain_init(he->callchain); + goto out_free_syms; + err = 0; + if (symbol_conf.use_callchain) err = append_chain(he->callchain, data->callchain, syms); - free(syms); - - if (err) - return err; - } - - return 0; -} - -static int validate_chain(struct ip_callchain *chain, event_t *event) -{ - unsigned int chain_size; - - chain_size = event->header.size; - chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; - - if (chain->nr*sizeof(u64) > chain_size) - return -1; - - return 0; +out_free_syms: + free(syms); + return err; } static int add_event_total(struct perf_session *session, @@ -171,7 +148,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) dump_printf("... chain: nr:%Lu\n", data.callchain->nr); - if (validate_chain(data.callchain, event) < 0) { + if (!ip_callchain__valid(data.callchain, event)) { pr_debug("call-chain problem with event, " "skipping it.\n"); return 0; @@ -366,7 +343,7 @@ static int parse_callchain_opt(const struct option *opt __used, const char *arg, int unset) { - char *tok; + char *tok, *tok2; char *endptr; /* @@ -411,10 +388,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, if (!tok) goto setup; + tok2 = strtok(NULL, ","); callchain_param.min_percent = strtod(tok, &endptr); if (tok == endptr) return -1; + if (tok2) + callchain_param.print_limit = strtod(tok2, &endptr); setup: if (register_callchain_param(&callchain_param) < 0) { fprintf(stderr, "Can't register callchain params\n"); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index db628af6d20..ac148613afe 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -17,6 +17,13 @@ #include "callchain.h" +bool ip_callchain__valid(struct ip_callchain *chain, event_t *event) +{ + unsigned int chain_size = event->header.size; + chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; + return chain->nr * sizeof(u64) <= chain_size; +} + #define chain_for_each_child(child, parent) \ list_for_each_entry(child, &parent->children, brothers) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 8a7e8bbd0fd..1cba1f5504e 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -4,6 +4,7 @@ #include "../perf.h" #include <linux/list.h> #include <linux/rbtree.h> +#include "event.h" #include "util.h" #include "symbol.h" @@ -33,6 +34,7 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *, struct callchain_param { enum chain_mode mode; + u32 print_limit; double min_percent; sort_chain_func_t sort; }; @@ -58,4 +60,6 @@ static inline u64 cumul_hits(struct callchain_node *node) int register_callchain_param(struct callchain_param *param); int append_chain(struct callchain_node *root, struct ip_callchain *chain, struct map_symbol *syms); + +bool ip_callchain__valid(struct ip_callchain *chain, event_t *event); #endif /* __PERF_CALLCHAIN_H */ diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 23d5dfd4ed7..d2ea9dd9fdf 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -493,8 +493,10 @@ int event__process_mmap(event_t *self, struct perf_session *session) return 0; } - thread = perf_session__findnew(session, self->mmap.pid); machine = perf_session__find_host_machine(session); + if (machine == NULL) + goto out_problem; + thread = perf_session__findnew(session, self->mmap.pid); map = map__new(&machine->user_dsos, self->mmap.start, self->mmap.len, self->mmap.pgoff, self->mmap.pid, self->mmap.filename, @@ -552,6 +554,10 @@ void thread__find_addr_map(struct thread *self, if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { al->level = 'k'; machine = perf_session__find_host_machine(session); + if (machine == NULL) { + al->map = NULL; + return; + } mg = &machine->kmaps; } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { al->level = '.'; @@ -559,7 +565,7 @@ void thread__find_addr_map(struct thread *self, } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { al->level = 'g'; machine = perf_session__find_machine(session, pid); - if (!machine) { + if (machine == NULL) { al->map = NULL; return; } @@ -650,6 +656,16 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, goto out_filtered; dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); + /* + * Have we already created the kernel maps for the host machine? + * + * This should have happened earlier, when we processed the kernel MMAP + * events, but for older perf.data files there was no such thing, so do + * it now. + */ + if (cpumode == PERF_RECORD_MISC_KERNEL && + session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) + machine__create_kernel_maps(&session->host_machine); thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, self->ip.pid, self->ip.ip, al); @@ -676,6 +692,13 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, dso__calc_col_width(al->map->dso); al->sym = map__find_symbol(al->map, al->addr, filter); + } else { + const unsigned int unresolved_col_width = BITS_PER_LONG / 4; + + if (dsos__col_width < unresolved_col_width && + !symbol_conf.col_width_list_str && !symbol_conf.field_sep && + !symbol_conf.dso_list) + dsos__col_width = unresolved_col_width; } if (symbol_conf.sym_list && al->sym && diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index ad6b22dde27..0f154a530df 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -8,13 +8,10 @@ struct callchain_param callchain_param = { .min_percent = 0.5 }; -void __perf_session__add_count(struct hist_entry *he, - struct addr_location *al, - u64 count) +static void perf_session__add_cpumode_count(struct hist_entry *he, + unsigned int cpumode, u64 count) { - he->count += count; - - switch (al->cpumode) { + switch (cpumode) { case PERF_RECORD_MISC_KERNEL: he->count_sys += count; break; @@ -36,10 +33,24 @@ void __perf_session__add_count(struct hist_entry *he, * histogram, sorted on item, collects counts */ +static struct hist_entry *hist_entry__new(struct hist_entry *template) +{ + size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_node) : 0; + struct hist_entry *self = malloc(sizeof(*self) + callchain_size); + + if (self != NULL) { + *self = *template; + if (symbol_conf.use_callchain) + callchain_init(self->callchain); + } + + return self; +} + struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, struct addr_location *al, struct symbol *sym_parent, - u64 count, bool *hit) + u64 count) { struct rb_node **p = &hists->rb_node; struct rb_node *parent = NULL; @@ -64,8 +75,8 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, cmp = hist_entry__cmp(&entry, he); if (!cmp) { - *hit = true; - return he; + he->count += count; + goto out; } if (cmp < 0) @@ -74,14 +85,13 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, p = &(*p)->rb_right; } - he = malloc(sizeof(*he) + (symbol_conf.use_callchain ? - sizeof(struct callchain_node) : 0)); + he = hist_entry__new(&entry); if (!he) return NULL; - *he = entry; rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, hists); - *hit = false; +out: + perf_session__add_cpumode_count(he, al->cpumode, count); return he; } @@ -323,6 +333,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, u64 remaining; size_t ret = 0; int i; + uint entries_printed = 0; if (callchain_param.mode == CHAIN_GRAPH_REL) new_total = self->children_hit; @@ -369,6 +380,8 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, new_depth_mask | (1 << depth), left_margin); node = next; + if (++entries_printed == callchain_param.print_limit) + break; } if (callchain_param.mode == CHAIN_GRAPH_REL && @@ -394,6 +407,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, bool printed = false; int i = 0; int ret = 0; + u32 entries_printed = 0; list_for_each_entry(chain, &self->val, list) { if (!i++ && sort__first_dimension == SORT_SYM) @@ -414,6 +428,9 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ret += fprintf(fp, " %s\n", chain->ms.sym->name); else ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); + + if (++entries_printed == callchain_param.print_limit) + break; } ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin); @@ -452,6 +469,7 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, struct rb_node *rb_node; struct callchain_node *chain; size_t ret = 0; + u32 entries_printed = 0; rb_node = rb_first(&self->sorted_chain); while (rb_node) { @@ -474,6 +492,8 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, break; } ret += fprintf(fp, "\n"); + if (++entries_printed == callchain_param.print_limit) + break; rb_node = rb_next(rb_node); } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 9df1c340ec9..b49013adb34 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -12,13 +12,10 @@ struct addr_location; struct symbol; struct rb_root; -void __perf_session__add_count(struct hist_entry *he, - struct addr_location *al, - u64 count); struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, struct addr_location *al, struct symbol *parent, - u64 count, bool *hit); + u64 count); extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); int hist_entry__fprintf(struct hist_entry *self, diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 44a4df68b3c..e672f2fef65 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -579,30 +579,6 @@ struct machine *machines__find(struct rb_root *self, pid_t pid) return default_machine; } -/* - * FIXME: Why repeatedly search for this? - */ -struct machine *machines__find_host(struct rb_root *self) -{ - struct rb_node **p = &self->rb_node; - struct rb_node *parent = NULL; - struct machine *machine; - pid_t pid = HOST_KERNEL_ID; - - while (*p != NULL) { - parent = *p; - machine = rb_entry(parent, struct machine, rb_node); - if (pid < machine->pid) - p = &(*p)->rb_left; - else if (pid > machine->pid) - p = &(*p)->rb_right; - else - return machine; - } - - return NULL; -} - struct machine *machines__findnew(struct rb_root *self, pid_t pid) { char path[PATH_MAX]; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 00ab298bbb4..c088d8f9b51 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -99,6 +99,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->machines = RB_ROOT; self->repipe = repipe; INIT_LIST_HEAD(&self->ordered_samples.samples_head); + machine__init(&self->host_machine, "", HOST_KERNEL_ID); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) @@ -919,3 +920,10 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, return 0; } + +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) +{ + return __dsos__fprintf(&self->host_machine.kernel_dsos, fp) + + __dsos__fprintf(&self->host_machine.user_dsos, fp) + + machines__fprintf_dsos(&self->machines, fp); +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 568fd08a478..242d528bfae 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -26,6 +26,7 @@ struct perf_session { unsigned long mmap_window; struct rb_root threads; struct thread *last_match; + struct machine host_machine; struct rb_root machines; struct events_stats events_stats; struct rb_root stats_by_id; @@ -113,18 +114,22 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, static inline struct machine *perf_session__find_host_machine(struct perf_session *self) { - return machines__find_host(&self->machines); + return &self->host_machine; } static inline struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) { + if (pid == HOST_KERNEL_ID) + return &self->host_machine; return machines__find(&self->machines, pid); } static inline struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) { + if (pid == HOST_KERNEL_ID) + return &self->host_machine; return machines__findnew(&self->machines, pid); } @@ -132,14 +137,11 @@ static inline void perf_session__process_machines(struct perf_session *self, machine__process_t process) { + process(&self->host_machine, self); return machines__process(&self->machines, process, self); } -static inline -size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) -{ - return machines__fprintf_dsos(&self->machines, fp); -} +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); static inline size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 4c0146a4906..994efdb531e 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1889,7 +1889,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name) return dso; } -static size_t __dsos__fprintf(struct list_head *head, FILE *fp) +size_t __dsos__fprintf(struct list_head *head, FILE *fp) { struct dso *pos; size_t ret = 0; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index a517c17407b..edff866d76b 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -167,6 +167,8 @@ int machine__load_kallsyms(struct machine *self, const char *filename, int machine__load_vmlinux_path(struct machine *self, enum map_type type, symbol_filter_t filter); +size_t __dsos__fprintf(struct list_head *head, FILE *fp); + size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); |