Loading tools/perf/Makefile +30 −17 Original line number Diff line number Diff line Loading @@ -61,8 +61,6 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar FLEX = $(CROSS_COMPILE)flex BISON= $(CROSS_COMPILE)bison # Additional ARCH settings for x86 ifeq ($(ARCH),i386) Loading Loading @@ -184,7 +182,7 @@ endif ### --- END CONFIGURATION SECTION --- BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE BASIC_LDFLAGS = # Guard against environment variables Loading Loading @@ -236,6 +234,25 @@ endif export PERL_PATH FLEX = $(CROSS_COMPILE)flex BISON= $(CROSS_COMPILE)bison event-parser: $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.c: event-parser $(OUTPUT)util/parse-events-bison.c: event-parser pmu-parser: $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.c: pmu-parser $(OUTPUT)util/pmu-bison.c: pmu-parser $(OUTPUT)util/parse-events.o: event-parser pmu-parser LIB_FILE=$(OUTPUT)libperf.a LIB_H += ../../include/linux/perf_event.h Loading Loading @@ -754,6 +771,15 @@ $(OUTPUT)perf.o perf.spec \ .SUFFIXES: .SUFFIXES: .o .c .S .s # These two need to be here so that when O= is not used they take precedence # over the general rule for .o $(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< $(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS Loading Loading @@ -790,12 +816,6 @@ $(OUTPUT)util/ui/browsers/map.o: util/ui/browsers/map.c $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< $(OUTPUT)util/parse-events-flex.o: util/parse-events-flex.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)util/pmu-flex.o: util/pmu-flex.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< Loading Loading @@ -883,14 +903,6 @@ cscope: $(RM) cscope* $(FIND) . -name '*.[hcS]' -print | xargs cscope -b event-parser: $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o util/parse-events-bison.c $(QUIET_FLEX)$(FLEX) --header-file=util/parse-events-flex.h -t util/parse-events.l > util/parse-events-flex.c pmu-parser: $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o util/pmu-bison.c $(QUIET_FLEX)$(FLEX) --header-file=util/pmu-flex.h -t util/pmu.l > util/pmu-flex.c ### Detect prefix changes TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\ $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) Loading Loading @@ -978,6 +990,7 @@ clean: $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(MAKE) -C Documentation/ clean $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(RM) $(OUTPUT)util/*-{bison,flex}* $(python-clean) .PHONY: all install clean strip Loading tools/perf/util/annotate.c +4 −4 Original line number Diff line number Diff line Loading @@ -28,8 +28,8 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym) int symbol__alloc_hist(struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); size_t sizeof_sym_hist = (sizeof(struct sym_hist) + (sym->end - sym->start) * sizeof(u64)); const size_t size = sym->end - sym->start + 1; size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); if (notes->src == NULL) Loading Loading @@ -64,7 +64,7 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); if (addr >= sym->end) if (addr > sym->end) return 0; offset = addr - sym->start; Loading Loading @@ -408,7 +408,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, if (!notes->src->lines) return -1; start = map->unmap_ip(map, sym->start); start = map__rip_2objdump(map, sym->start); for (i = 0; i < len; i++) { char *path = NULL; Loading tools/perf/util/evsel.c +2 −0 Original line number Diff line number Diff line Loading @@ -580,6 +580,8 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, return -EFAULT; data->raw_data = (void *) pdata; array = (void *)array + data->raw_size + sizeof(u32); } if (type & PERF_SAMPLE_BRANCH_STACK) { Loading tools/perf/util/hist.c +93 −64 Original line number Diff line number Diff line Loading @@ -607,7 +607,7 @@ static void init_rem_hits(void) rem_hits.ms.sym = rem_sq_bracket; } static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, u64 total_samples, int depth, int depth_mask, int left_margin) { Loading @@ -615,21 +615,16 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, struct callchain_node *child; struct callchain_list *chain; int new_depth_mask = depth_mask; u64 new_total; u64 remaining; size_t ret = 0; int i; uint entries_printed = 0; if (callchain_param.mode == CHAIN_GRAPH_REL) new_total = self->children_hit; else new_total = total_samples; remaining = new_total; remaining = total_samples; node = rb_first(&self->rb_root); node = rb_first(root); while (node) { u64 new_total; u64 cumul; child = rb_entry(node, struct callchain_node, rb_node); Loading Loading @@ -657,11 +652,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, list_for_each_entry(chain, &child->val, list) { ret += ipchain__fprintf_graph(fp, chain, depth, new_depth_mask, i++, new_total, total_samples, cumul, left_margin); } ret += __callchain__fprintf_graph(fp, child, new_total, if (callchain_param.mode == CHAIN_GRAPH_REL) new_total = child->children_hit; else new_total = total_samples; ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total, depth + 1, new_depth_mask | (1 << depth), left_margin); Loading @@ -671,40 +672,52 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, } if (callchain_param.mode == CHAIN_GRAPH_REL && remaining && remaining != new_total) { remaining && remaining != total_samples) { if (!rem_sq_bracket) return ret; new_depth_mask &= ~(1 << (depth - 1)); ret += ipchain__fprintf_graph(fp, &rem_hits, depth, new_depth_mask, 0, new_total, new_depth_mask, 0, total_samples, remaining, left_margin); } return ret; } static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, u64 total_samples, int left_margin) { struct callchain_node *cnode; struct callchain_list *chain; u32 entries_printed = 0; bool printed = false; struct rb_node *node; int i = 0; int ret = 0; u32 entries_printed = 0; int ret; list_for_each_entry(chain, &self->val, list) { /* * If have one single callchain root, don't bother printing * its percentage (100 % in fractal mode and the same percentage * than the hist in graph mode). This also avoid one level of column. */ node = rb_first(root); if (node && !rb_next(node)) { cnode = rb_entry(node, struct callchain_node, rb_node); list_for_each_entry(chain, &cnode->val, list) { /* * If we sort by symbol, the first entry is the same than * the symbol. No need to print it otherwise it appears as * displayed twice. */ if (!i++ && sort__first_dimension == SORT_SYM) continue; if (!printed) { ret += callchain__fprintf_left_margin(fp, left_margin); ret += fprintf(fp, "|\n"); ret += callchain__fprintf_left_margin(fp, left_margin); ret += fprintf(fp, "---"); left_margin += 3; printed = true; } else Loading @@ -718,13 +731,15 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, if (++entries_printed == callchain_param.print_limit) break; } root = &cnode->rb_root; } ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin); return ret; return __callchain__fprintf_graph(fp, root, total_samples, 1, 1, left_margin); } static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *self, u64 total_samples) { struct callchain_list *chain; Loading @@ -733,7 +748,7 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, if (!self) return 0; ret += callchain__fprintf_flat(fp, self->parent, total_samples); ret += __callchain__fprintf_flat(fp, self->parent, total_samples); list_for_each_entry(chain, &self->val, list) { Loading @@ -749,44 +764,58 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, return ret; } static size_t hist_entry_callchain__fprintf(struct hist_entry *he, u64 total_samples, int left_margin, FILE *fp) static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, u64 total_samples) { struct rb_node *rb_node; struct callchain_node *chain; size_t ret = 0; u32 entries_printed = 0; struct rb_node *rb_node; struct callchain_node *chain; rb_node = rb_first(&he->sorted_chain); rb_node = rb_first(self); while (rb_node) { double percent; chain = rb_entry(rb_node, struct callchain_node, rb_node); percent = chain->hit * 100.0 / total_samples; switch (callchain_param.mode) { case CHAIN_FLAT: ret += percent_color_fprintf(fp, " %6.2f%%\n", percent); ret += callchain__fprintf_flat(fp, chain, total_samples); break; case CHAIN_GRAPH_ABS: /* Falldown */ case CHAIN_GRAPH_REL: ret += callchain__fprintf_graph(fp, chain, total_samples, left_margin); case CHAIN_NONE: default: break; } ret = percent_color_fprintf(fp, " %6.2f%%\n", percent); ret += __callchain__fprintf_flat(fp, chain, total_samples); ret += fprintf(fp, "\n"); if (++entries_printed == callchain_param.print_limit) break; rb_node = rb_next(rb_node); } return ret; } static size_t hist_entry_callchain__fprintf(struct hist_entry *he, u64 total_samples, int left_margin, FILE *fp) { switch (callchain_param.mode) { case CHAIN_GRAPH_REL: return callchain__fprintf_graph(fp, &he->sorted_chain, he->period, left_margin); break; case CHAIN_GRAPH_ABS: return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, left_margin); break; case CHAIN_FLAT: return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); break; case CHAIN_NONE: break; default: pr_err("Bad callchain mode\n"); } return 0; } void hists__output_recalc_col_len(struct hists *hists, int max_rows) { struct rb_node *next = rb_first(&hists->entries); Loading Loading
tools/perf/Makefile +30 −17 Original line number Diff line number Diff line Loading @@ -61,8 +61,6 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar FLEX = $(CROSS_COMPILE)flex BISON= $(CROSS_COMPILE)bison # Additional ARCH settings for x86 ifeq ($(ARCH),i386) Loading Loading @@ -184,7 +182,7 @@ endif ### --- END CONFIGURATION SECTION --- BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE BASIC_LDFLAGS = # Guard against environment variables Loading Loading @@ -236,6 +234,25 @@ endif export PERL_PATH FLEX = $(CROSS_COMPILE)flex BISON= $(CROSS_COMPILE)bison event-parser: $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.c: event-parser $(OUTPUT)util/parse-events-bison.c: event-parser pmu-parser: $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.c: pmu-parser $(OUTPUT)util/pmu-bison.c: pmu-parser $(OUTPUT)util/parse-events.o: event-parser pmu-parser LIB_FILE=$(OUTPUT)libperf.a LIB_H += ../../include/linux/perf_event.h Loading Loading @@ -754,6 +771,15 @@ $(OUTPUT)perf.o perf.spec \ .SUFFIXES: .SUFFIXES: .o .c .S .s # These two need to be here so that when O= is not used they take precedence # over the general rule for .o $(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -Iutil/ -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< $(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS Loading Loading @@ -790,12 +816,6 @@ $(OUTPUT)util/ui/browsers/map.o: util/ui/browsers/map.c $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< $(OUTPUT)util/parse-events-flex.o: util/parse-events-flex.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)util/pmu-flex.o: util/pmu-flex.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls -Wno-switch-default -Wno-unused-function $< $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< Loading Loading @@ -883,14 +903,6 @@ cscope: $(RM) cscope* $(FIND) . -name '*.[hcS]' -print | xargs cscope -b event-parser: $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o util/parse-events-bison.c $(QUIET_FLEX)$(FLEX) --header-file=util/parse-events-flex.h -t util/parse-events.l > util/parse-events-flex.c pmu-parser: $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o util/pmu-bison.c $(QUIET_FLEX)$(FLEX) --header-file=util/pmu-flex.h -t util/pmu.l > util/pmu-flex.c ### Detect prefix changes TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\ $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) Loading Loading @@ -978,6 +990,7 @@ clean: $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(MAKE) -C Documentation/ clean $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(RM) $(OUTPUT)util/*-{bison,flex}* $(python-clean) .PHONY: all install clean strip Loading
tools/perf/util/annotate.c +4 −4 Original line number Diff line number Diff line Loading @@ -28,8 +28,8 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym) int symbol__alloc_hist(struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); size_t sizeof_sym_hist = (sizeof(struct sym_hist) + (sym->end - sym->start) * sizeof(u64)); const size_t size = sym->end - sym->start + 1; size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); if (notes->src == NULL) Loading Loading @@ -64,7 +64,7 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); if (addr >= sym->end) if (addr > sym->end) return 0; offset = addr - sym->start; Loading Loading @@ -408,7 +408,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, if (!notes->src->lines) return -1; start = map->unmap_ip(map, sym->start); start = map__rip_2objdump(map, sym->start); for (i = 0; i < len; i++) { char *path = NULL; Loading
tools/perf/util/evsel.c +2 −0 Original line number Diff line number Diff line Loading @@ -580,6 +580,8 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, return -EFAULT; data->raw_data = (void *) pdata; array = (void *)array + data->raw_size + sizeof(u32); } if (type & PERF_SAMPLE_BRANCH_STACK) { Loading
tools/perf/util/hist.c +93 −64 Original line number Diff line number Diff line Loading @@ -607,7 +607,7 @@ static void init_rem_hits(void) rem_hits.ms.sym = rem_sq_bracket; } static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, u64 total_samples, int depth, int depth_mask, int left_margin) { Loading @@ -615,21 +615,16 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, struct callchain_node *child; struct callchain_list *chain; int new_depth_mask = depth_mask; u64 new_total; u64 remaining; size_t ret = 0; int i; uint entries_printed = 0; if (callchain_param.mode == CHAIN_GRAPH_REL) new_total = self->children_hit; else new_total = total_samples; remaining = new_total; remaining = total_samples; node = rb_first(&self->rb_root); node = rb_first(root); while (node) { u64 new_total; u64 cumul; child = rb_entry(node, struct callchain_node, rb_node); Loading Loading @@ -657,11 +652,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, list_for_each_entry(chain, &child->val, list) { ret += ipchain__fprintf_graph(fp, chain, depth, new_depth_mask, i++, new_total, total_samples, cumul, left_margin); } ret += __callchain__fprintf_graph(fp, child, new_total, if (callchain_param.mode == CHAIN_GRAPH_REL) new_total = child->children_hit; else new_total = total_samples; ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total, depth + 1, new_depth_mask | (1 << depth), left_margin); Loading @@ -671,40 +672,52 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, } if (callchain_param.mode == CHAIN_GRAPH_REL && remaining && remaining != new_total) { remaining && remaining != total_samples) { if (!rem_sq_bracket) return ret; new_depth_mask &= ~(1 << (depth - 1)); ret += ipchain__fprintf_graph(fp, &rem_hits, depth, new_depth_mask, 0, new_total, new_depth_mask, 0, total_samples, remaining, left_margin); } return ret; } static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, u64 total_samples, int left_margin) { struct callchain_node *cnode; struct callchain_list *chain; u32 entries_printed = 0; bool printed = false; struct rb_node *node; int i = 0; int ret = 0; u32 entries_printed = 0; int ret; list_for_each_entry(chain, &self->val, list) { /* * If have one single callchain root, don't bother printing * its percentage (100 % in fractal mode and the same percentage * than the hist in graph mode). This also avoid one level of column. */ node = rb_first(root); if (node && !rb_next(node)) { cnode = rb_entry(node, struct callchain_node, rb_node); list_for_each_entry(chain, &cnode->val, list) { /* * If we sort by symbol, the first entry is the same than * the symbol. No need to print it otherwise it appears as * displayed twice. */ if (!i++ && sort__first_dimension == SORT_SYM) continue; if (!printed) { ret += callchain__fprintf_left_margin(fp, left_margin); ret += fprintf(fp, "|\n"); ret += callchain__fprintf_left_margin(fp, left_margin); ret += fprintf(fp, "---"); left_margin += 3; printed = true; } else Loading @@ -718,13 +731,15 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, if (++entries_printed == callchain_param.print_limit) break; } root = &cnode->rb_root; } ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin); return ret; return __callchain__fprintf_graph(fp, root, total_samples, 1, 1, left_margin); } static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *self, u64 total_samples) { struct callchain_list *chain; Loading @@ -733,7 +748,7 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, if (!self) return 0; ret += callchain__fprintf_flat(fp, self->parent, total_samples); ret += __callchain__fprintf_flat(fp, self->parent, total_samples); list_for_each_entry(chain, &self->val, list) { Loading @@ -749,44 +764,58 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, return ret; } static size_t hist_entry_callchain__fprintf(struct hist_entry *he, u64 total_samples, int left_margin, FILE *fp) static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, u64 total_samples) { struct rb_node *rb_node; struct callchain_node *chain; size_t ret = 0; u32 entries_printed = 0; struct rb_node *rb_node; struct callchain_node *chain; rb_node = rb_first(&he->sorted_chain); rb_node = rb_first(self); while (rb_node) { double percent; chain = rb_entry(rb_node, struct callchain_node, rb_node); percent = chain->hit * 100.0 / total_samples; switch (callchain_param.mode) { case CHAIN_FLAT: ret += percent_color_fprintf(fp, " %6.2f%%\n", percent); ret += callchain__fprintf_flat(fp, chain, total_samples); break; case CHAIN_GRAPH_ABS: /* Falldown */ case CHAIN_GRAPH_REL: ret += callchain__fprintf_graph(fp, chain, total_samples, left_margin); case CHAIN_NONE: default: break; } ret = percent_color_fprintf(fp, " %6.2f%%\n", percent); ret += __callchain__fprintf_flat(fp, chain, total_samples); ret += fprintf(fp, "\n"); if (++entries_printed == callchain_param.print_limit) break; rb_node = rb_next(rb_node); } return ret; } static size_t hist_entry_callchain__fprintf(struct hist_entry *he, u64 total_samples, int left_margin, FILE *fp) { switch (callchain_param.mode) { case CHAIN_GRAPH_REL: return callchain__fprintf_graph(fp, &he->sorted_chain, he->period, left_margin); break; case CHAIN_GRAPH_ABS: return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, left_margin); break; case CHAIN_FLAT: return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); break; case CHAIN_NONE: break; default: pr_err("Bad callchain mode\n"); } return 0; } void hists__output_recalc_col_len(struct hists *hists, int max_rows) { struct rb_node *next = rb_first(&hists->entries); Loading