From bd548e12c8dc4d8edede0ef3ce16ac8bdaf45a20 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 2 May 2010 22:05:29 +0200 Subject: [PATCH] --- yaml --- r: 191317 b: refs/heads/master c: 984028075794c00cbf4fb1e94bb6233e8be08875 h: refs/heads/master i: 191315: d1a1f454aa8c05bfbf50bccff8f1494ad1eddb84 v: v3 --- [refs] | 2 +- trunk/tools/perf/builtin-annotate.c | 9 ++++-- trunk/tools/perf/builtin-diff.c | 14 +++++++-- trunk/tools/perf/builtin-record.c | 34 ++++++++++++++------ trunk/tools/perf/builtin-report.c | 48 ++++++++++++++++++++--------- trunk/tools/perf/util/callchain.c | 7 ----- trunk/tools/perf/util/callchain.h | 4 --- trunk/tools/perf/util/event.c | 27 ++-------------- trunk/tools/perf/util/event.h | 3 +- trunk/tools/perf/util/hist.c | 46 ++++++++------------------- trunk/tools/perf/util/hist.h | 5 ++- trunk/tools/perf/util/map.c | 24 +++++++++++++++ trunk/tools/perf/util/session.c | 8 ----- trunk/tools/perf/util/session.h | 14 ++++----- trunk/tools/perf/util/symbol.c | 2 +- trunk/tools/perf/util/symbol.h | 2 -- 16 files changed, 128 insertions(+), 121 deletions(-) diff --git a/[refs] b/[refs] index 63ee85717746..83364cd89a69 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 232a5c948da5e23dff27e48180abf4a4238f7602 +refs/heads/master: 984028075794c00cbf4fb1e94bb6233e8be08875 diff --git a/trunk/tools/perf/builtin-annotate.c b/trunk/tools/perf/builtin-annotate.c index c7ac45a59ed5..ee154b58772b 100644 --- a/trunk/tools/perf/builtin-annotate.c +++ b/trunk/tools/perf/builtin-annotate.c @@ -72,6 +72,8 @@ 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; @@ -97,8 +99,9 @@ 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) + struct addr_location *al, u64 count) { + bool hit; struct hist_entry *he; if (sym_hist_filter != NULL && @@ -112,7 +115,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, return 0; } - he = __perf_session__add_hist_entry(&self->hists, al, NULL, 1); + he = __perf_session__add_hist_entry(&self->hists, al, NULL, count, &hit); if (he == NULL) return -ENOMEM; @@ -132,7 +135,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)) { + if (!al.filtered && perf_session__add_hist_entry(session, &al, 1)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); return -1; diff --git a/trunk/tools/perf/builtin-diff.c b/trunk/tools/perf/builtin-diff.c index 613a5c4f6d83..4cce68f23686 100644 --- a/trunk/tools/perf/builtin-diff.c +++ b/trunk/tools/perf/builtin-diff.c @@ -25,9 +25,17 @@ static bool show_displacement; static int perf_session__add_hist_entry(struct perf_session *self, struct addr_location *al, u64 count) { - if (__perf_session__add_hist_entry(&self->hists, al, NULL, count) != NULL) - return 0; - return -ENOMEM; + 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; } static int diff__process_sample_event(event_t *event, struct perf_session *session) diff --git a/trunk/tools/perf/builtin-record.c b/trunk/tools/perf/builtin-record.c index d3981ac50e1d..6b77b285fe10 100644 --- a/trunk/tools/perf/builtin-record.c +++ b/trunk/tools/perf/builtin-record.c @@ -494,6 +494,29 @@ static void event__synthesize_guest_os(struct machine *machine, void *data) " relocation symbol.\n", machine->pid); } +static struct perf_event_header finished_round_event = { + .size = sizeof(struct perf_event_header), + .type = PERF_RECORD_FINISHED_ROUND, +}; + +static void mmap_read_all(void) +{ + int i, counter, thread; + + for (i = 0; i < nr_cpu; i++) { + for (counter = 0; counter < nr_counters; counter++) { + for (thread = 0; thread < thread_num; thread++) { + if (mmap_array[i][counter][thread].base) + mmap_read(&mmap_array[i][counter][thread]); + } + + } + } + + if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) + write_output(&finished_round_event, sizeof(finished_round_event)); +} + static int __cmd_record(int argc, const char **argv) { int i, counter; @@ -726,16 +749,7 @@ static int __cmd_record(int argc, const char **argv) int hits = samples; int thread; - for (i = 0; i < nr_cpu; i++) { - for (counter = 0; counter < nr_counters; counter++) { - for (thread = 0; - thread < thread_num; thread++) { - if (mmap_array[i][counter][thread].base) - mmap_read(&mmap_array[i][counter][thread]); - } - - } - } + mmap_read_all(); if (hits == samples) { if (done) diff --git a/trunk/tools/perf/builtin-report.c b/trunk/tools/perf/builtin-report.c index 642a6d8eb5dc..196473b51257 100644 --- a/trunk/tools/perf/builtin-report.c +++ b/trunk/tools/perf/builtin-report.c @@ -82,7 +82,8 @@ static int perf_session__add_hist_entry(struct perf_session *self, { struct map_symbol *syms = NULL; struct symbol *parent = NULL; - int err = -ENOMEM; + bool hit; + int err; struct hist_entry *he; struct event_stat_id *stats; struct perf_event_attr *attr; @@ -100,17 +101,39 @@ static int perf_session__add_hist_entry(struct perf_session *self, else stats = get_stats(self, data->id, 0, 0); if (stats == NULL) - goto out_free_syms; + return -ENOMEM; he = __perf_session__add_hist_entry(&stats->hists, al, parent, - data->period); + data->period, &hit); if (he == NULL) - goto out_free_syms; - err = 0; - if (symbol_conf.use_callchain) + return -ENOMEM; + + if (hit) + __perf_session__add_count(he, al, data->period); + + if (symbol_conf.use_callchain) { + if (!hit) + callchain_init(he->callchain); err = append_chain(he->callchain, data->callchain, syms); -out_free_syms: - free(syms); - return err; + 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; } static int add_event_total(struct perf_session *session, @@ -148,7 +171,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) dump_printf("... chain: nr:%Lu\n", data.callchain->nr); - if (!ip_callchain__valid(data.callchain, event)) { + if (validate_chain(data.callchain, event) < 0) { pr_debug("call-chain problem with event, " "skipping it.\n"); return 0; @@ -343,7 +366,7 @@ static int parse_callchain_opt(const struct option *opt __used, const char *arg, int unset) { - char *tok, *tok2; + char *tok; char *endptr; /* @@ -388,13 +411,10 @@ 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/trunk/tools/perf/util/callchain.c b/trunk/tools/perf/util/callchain.c index ac148613afe8..db628af6d20d 100644 --- a/trunk/tools/perf/util/callchain.c +++ b/trunk/tools/perf/util/callchain.c @@ -17,13 +17,6 @@ #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/trunk/tools/perf/util/callchain.h b/trunk/tools/perf/util/callchain.h index 1cba1f5504e7..8a7e8bbd0fda 100644 --- a/trunk/tools/perf/util/callchain.h +++ b/trunk/tools/perf/util/callchain.h @@ -4,7 +4,6 @@ #include "../perf.h" #include #include -#include "event.h" #include "util.h" #include "symbol.h" @@ -34,7 +33,6 @@ 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; }; @@ -60,6 +58,4 @@ 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/trunk/tools/perf/util/event.c b/trunk/tools/perf/util/event.c index d2ea9dd9fdf1..23d5dfd4ed73 100644 --- a/trunk/tools/perf/util/event.c +++ b/trunk/tools/perf/util/event.c @@ -493,10 +493,8 @@ int event__process_mmap(event_t *self, struct perf_session *session) return 0; } - machine = perf_session__find_host_machine(session); - if (machine == NULL) - goto out_problem; thread = perf_session__findnew(session, self->mmap.pid); + machine = perf_session__find_host_machine(session); map = map__new(&machine->user_dsos, self->mmap.start, self->mmap.len, self->mmap.pgoff, self->mmap.pid, self->mmap.filename, @@ -554,10 +552,6 @@ 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 = '.'; @@ -565,7 +559,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 == NULL) { + if (!machine) { al->map = NULL; return; } @@ -656,16 +650,6 @@ 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); @@ -692,13 +676,6 @@ 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/trunk/tools/perf/util/event.h b/trunk/tools/perf/util/event.h index b364da5b0cbf..6cc1b1dced55 100644 --- a/trunk/tools/perf/util/event.h +++ b/trunk/tools/perf/util/event.h @@ -84,11 +84,12 @@ struct build_id_event { char filename[]; }; -enum perf_header_event_type { /* above any possible kernel type */ +enum perf_user_event_type { /* above any possible kernel type */ PERF_RECORD_HEADER_ATTR = 64, PERF_RECORD_HEADER_EVENT_TYPE = 65, PERF_RECORD_HEADER_TRACING_DATA = 66, PERF_RECORD_HEADER_BUILD_ID = 67, + PERF_RECORD_FINISHED_ROUND = 68, PERF_RECORD_HEADER_MAX }; diff --git a/trunk/tools/perf/util/hist.c b/trunk/tools/perf/util/hist.c index 0f154a530dfd..ad6b22dde27f 100644 --- a/trunk/tools/perf/util/hist.c +++ b/trunk/tools/perf/util/hist.c @@ -8,10 +8,13 @@ struct callchain_param callchain_param = { .min_percent = 0.5 }; -static void perf_session__add_cpumode_count(struct hist_entry *he, - unsigned int cpumode, u64 count) +void __perf_session__add_count(struct hist_entry *he, + struct addr_location *al, + u64 count) { - switch (cpumode) { + he->count += count; + + switch (al->cpumode) { case PERF_RECORD_MISC_KERNEL: he->count_sys += count; break; @@ -33,24 +36,10 @@ static void perf_session__add_cpumode_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) + u64 count, bool *hit) { struct rb_node **p = &hists->rb_node; struct rb_node *parent = NULL; @@ -75,8 +64,8 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, cmp = hist_entry__cmp(&entry, he); if (!cmp) { - he->count += count; - goto out; + *hit = true; + return he; } if (cmp < 0) @@ -85,13 +74,14 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, p = &(*p)->rb_right; } - he = hist_entry__new(&entry); + he = malloc(sizeof(*he) + (symbol_conf.use_callchain ? + sizeof(struct callchain_node) : 0)); if (!he) return NULL; + *he = entry; rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, hists); -out: - perf_session__add_cpumode_count(he, al->cpumode, count); + *hit = false; return he; } @@ -333,7 +323,6 @@ 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; @@ -380,8 +369,6 @@ 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 && @@ -407,7 +394,6 @@ 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) @@ -428,9 +414,6 @@ 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); @@ -469,7 +452,6 @@ 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) { @@ -492,8 +474,6 @@ 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/trunk/tools/perf/util/hist.h b/trunk/tools/perf/util/hist.h index b49013adb34b..9df1c340ec92 100644 --- a/trunk/tools/perf/util/hist.h +++ b/trunk/tools/perf/util/hist.h @@ -12,10 +12,13 @@ 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); + u64 count, bool *hit); 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/trunk/tools/perf/util/map.c b/trunk/tools/perf/util/map.c index e672f2fef65b..44a4df68b3cf 100644 --- a/trunk/tools/perf/util/map.c +++ b/trunk/tools/perf/util/map.c @@ -579,6 +579,30 @@ 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/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index 71bc608e0ec6..5d353e70fe26 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -100,7 +100,6 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->repipe = repipe; self->ordered_samples.flush_limit = ULLONG_MAX; 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) @@ -871,10 +870,3 @@ 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/trunk/tools/perf/util/session.h b/trunk/tools/perf/util/session.h index eb9f179376a5..f2b2c6a3a49d 100644 --- a/trunk/tools/perf/util/session.h +++ b/trunk/tools/perf/util/session.h @@ -25,7 +25,6 @@ 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; @@ -108,22 +107,18 @@ 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 &self->host_machine; + return machines__find_host(&self->machines); } 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); } @@ -131,11 +126,14 @@ 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); } -size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); +static inline +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) +{ + return machines__fprintf_dsos(&self->machines, fp); +} static inline size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index 994efdb531e4..4c0146a49063 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -1889,7 +1889,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name) return dso; } -size_t __dsos__fprintf(struct list_head *head, FILE *fp) +static size_t __dsos__fprintf(struct list_head *head, FILE *fp) { struct dso *pos; size_t ret = 0; diff --git a/trunk/tools/perf/util/symbol.h b/trunk/tools/perf/util/symbol.h index edff866d76b2..a517c17407b7 100644 --- a/trunk/tools/perf/util/symbol.h +++ b/trunk/tools/perf/util/symbol.h @@ -167,8 +167,6 @@ 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);