17ccf4f90SNamhyung Kim #include <stdio.h> 27ccf4f90SNamhyung Kim 37ccf4f90SNamhyung Kim #include "../../util/util.h" 47ccf4f90SNamhyung Kim #include "../../util/hist.h" 57ccf4f90SNamhyung Kim #include "../../util/sort.h" 65b9e2146SNamhyung Kim #include "../../util/evsel.h" 77ccf4f90SNamhyung Kim 87ccf4f90SNamhyung Kim 97ccf4f90SNamhyung Kim static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) 107ccf4f90SNamhyung Kim { 117ccf4f90SNamhyung Kim int i; 127ccf4f90SNamhyung Kim int ret = fprintf(fp, " "); 137ccf4f90SNamhyung Kim 147ccf4f90SNamhyung Kim for (i = 0; i < left_margin; i++) 157ccf4f90SNamhyung Kim ret += fprintf(fp, " "); 167ccf4f90SNamhyung Kim 177ccf4f90SNamhyung Kim return ret; 187ccf4f90SNamhyung Kim } 197ccf4f90SNamhyung Kim 207ccf4f90SNamhyung Kim static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, 217ccf4f90SNamhyung Kim int left_margin) 227ccf4f90SNamhyung Kim { 237ccf4f90SNamhyung Kim int i; 247ccf4f90SNamhyung Kim size_t ret = callchain__fprintf_left_margin(fp, left_margin); 257ccf4f90SNamhyung Kim 267ccf4f90SNamhyung Kim for (i = 0; i < depth; i++) 277ccf4f90SNamhyung Kim if (depth_mask & (1 << i)) 287ccf4f90SNamhyung Kim ret += fprintf(fp, "| "); 297ccf4f90SNamhyung Kim else 307ccf4f90SNamhyung Kim ret += fprintf(fp, " "); 317ccf4f90SNamhyung Kim 327ccf4f90SNamhyung Kim ret += fprintf(fp, "\n"); 337ccf4f90SNamhyung Kim 347ccf4f90SNamhyung Kim return ret; 357ccf4f90SNamhyung Kim } 367ccf4f90SNamhyung Kim 375ab250caSNamhyung Kim static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node, 385ab250caSNamhyung Kim struct callchain_list *chain, 397ccf4f90SNamhyung Kim int depth, int depth_mask, int period, 405ab250caSNamhyung Kim u64 total_samples, int left_margin) 417ccf4f90SNamhyung Kim { 427ccf4f90SNamhyung Kim int i; 437ccf4f90SNamhyung Kim size_t ret = 0; 442989ccaaSAndi Kleen char bf[1024]; 457ccf4f90SNamhyung Kim 467ccf4f90SNamhyung Kim ret += callchain__fprintf_left_margin(fp, left_margin); 477ccf4f90SNamhyung Kim for (i = 0; i < depth; i++) { 487ccf4f90SNamhyung Kim if (depth_mask & (1 << i)) 497ccf4f90SNamhyung Kim ret += fprintf(fp, "|"); 507ccf4f90SNamhyung Kim else 517ccf4f90SNamhyung Kim ret += fprintf(fp, " "); 527ccf4f90SNamhyung Kim if (!period && i == depth - 1) { 535ab250caSNamhyung Kim ret += fprintf(fp, "--"); 545ab250caSNamhyung Kim ret += callchain_node__fprintf_value(node, fp, total_samples); 555ab250caSNamhyung Kim ret += fprintf(fp, "--"); 567ccf4f90SNamhyung Kim } else 577ccf4f90SNamhyung Kim ret += fprintf(fp, "%s", " "); 587ccf4f90SNamhyung Kim } 592989ccaaSAndi Kleen fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp); 602989ccaaSAndi Kleen fputc('\n', fp); 617ccf4f90SNamhyung Kim return ret; 627ccf4f90SNamhyung Kim } 637ccf4f90SNamhyung Kim 647ccf4f90SNamhyung Kim static struct symbol *rem_sq_bracket; 657ccf4f90SNamhyung Kim static struct callchain_list rem_hits; 667ccf4f90SNamhyung Kim 677ccf4f90SNamhyung Kim static void init_rem_hits(void) 687ccf4f90SNamhyung Kim { 697ccf4f90SNamhyung Kim rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); 707ccf4f90SNamhyung Kim if (!rem_sq_bracket) { 717ccf4f90SNamhyung Kim fprintf(stderr, "Not enough memory to display remaining hits\n"); 727ccf4f90SNamhyung Kim return; 737ccf4f90SNamhyung Kim } 747ccf4f90SNamhyung Kim 757ccf4f90SNamhyung Kim strcpy(rem_sq_bracket->name, "[...]"); 767ccf4f90SNamhyung Kim rem_hits.ms.sym = rem_sq_bracket; 777ccf4f90SNamhyung Kim } 787ccf4f90SNamhyung Kim 797ccf4f90SNamhyung Kim static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, 807ccf4f90SNamhyung Kim u64 total_samples, int depth, 817ccf4f90SNamhyung Kim int depth_mask, int left_margin) 827ccf4f90SNamhyung Kim { 837ccf4f90SNamhyung Kim struct rb_node *node, *next; 84f2af0086SNamhyung Kim struct callchain_node *child = NULL; 857ccf4f90SNamhyung Kim struct callchain_list *chain; 867ccf4f90SNamhyung Kim int new_depth_mask = depth_mask; 877ccf4f90SNamhyung Kim u64 remaining; 887ccf4f90SNamhyung Kim size_t ret = 0; 897ccf4f90SNamhyung Kim int i; 907ccf4f90SNamhyung Kim uint entries_printed = 0; 91f2af0086SNamhyung Kim int cumul_count = 0; 927ccf4f90SNamhyung Kim 937ccf4f90SNamhyung Kim remaining = total_samples; 947ccf4f90SNamhyung Kim 957ccf4f90SNamhyung Kim node = rb_first(root); 967ccf4f90SNamhyung Kim while (node) { 977ccf4f90SNamhyung Kim u64 new_total; 987ccf4f90SNamhyung Kim u64 cumul; 997ccf4f90SNamhyung Kim 1007ccf4f90SNamhyung Kim child = rb_entry(node, struct callchain_node, rb_node); 1017ccf4f90SNamhyung Kim cumul = callchain_cumul_hits(child); 1027ccf4f90SNamhyung Kim remaining -= cumul; 103f2af0086SNamhyung Kim cumul_count += callchain_cumul_counts(child); 1047ccf4f90SNamhyung Kim 1057ccf4f90SNamhyung Kim /* 1067ccf4f90SNamhyung Kim * The depth mask manages the output of pipes that show 1077ccf4f90SNamhyung Kim * the depth. We don't want to keep the pipes of the current 1087ccf4f90SNamhyung Kim * level for the last child of this depth. 1097ccf4f90SNamhyung Kim * Except if we have remaining filtered hits. They will 1107ccf4f90SNamhyung Kim * supersede the last child 1117ccf4f90SNamhyung Kim */ 1127ccf4f90SNamhyung Kim next = rb_next(node); 1137ccf4f90SNamhyung Kim if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) 1147ccf4f90SNamhyung Kim new_depth_mask &= ~(1 << (depth - 1)); 1157ccf4f90SNamhyung Kim 1167ccf4f90SNamhyung Kim /* 1177ccf4f90SNamhyung Kim * But we keep the older depth mask for the line separator 1187ccf4f90SNamhyung Kim * to keep the level link until we reach the last child 1197ccf4f90SNamhyung Kim */ 1207ccf4f90SNamhyung Kim ret += ipchain__fprintf_graph_line(fp, depth, depth_mask, 1217ccf4f90SNamhyung Kim left_margin); 1227ccf4f90SNamhyung Kim i = 0; 1237ccf4f90SNamhyung Kim list_for_each_entry(chain, &child->val, list) { 1245ab250caSNamhyung Kim ret += ipchain__fprintf_graph(fp, child, chain, depth, 1257ccf4f90SNamhyung Kim new_depth_mask, i++, 1267ccf4f90SNamhyung Kim total_samples, 1277ccf4f90SNamhyung Kim left_margin); 1287ccf4f90SNamhyung Kim } 1297ccf4f90SNamhyung Kim 1307ccf4f90SNamhyung Kim if (callchain_param.mode == CHAIN_GRAPH_REL) 1317ccf4f90SNamhyung Kim new_total = child->children_hit; 1327ccf4f90SNamhyung Kim else 1337ccf4f90SNamhyung Kim new_total = total_samples; 1347ccf4f90SNamhyung Kim 1357ccf4f90SNamhyung Kim ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total, 1367ccf4f90SNamhyung Kim depth + 1, 1377ccf4f90SNamhyung Kim new_depth_mask | (1 << depth), 1387ccf4f90SNamhyung Kim left_margin); 1397ccf4f90SNamhyung Kim node = next; 1407ccf4f90SNamhyung Kim if (++entries_printed == callchain_param.print_limit) 1417ccf4f90SNamhyung Kim break; 1427ccf4f90SNamhyung Kim } 1437ccf4f90SNamhyung Kim 1447ccf4f90SNamhyung Kim if (callchain_param.mode == CHAIN_GRAPH_REL && 1457ccf4f90SNamhyung Kim remaining && remaining != total_samples) { 1465ab250caSNamhyung Kim struct callchain_node rem_node = { 1475ab250caSNamhyung Kim .hit = remaining, 1485ab250caSNamhyung Kim }; 1497ccf4f90SNamhyung Kim 1507ccf4f90SNamhyung Kim if (!rem_sq_bracket) 1517ccf4f90SNamhyung Kim return ret; 1527ccf4f90SNamhyung Kim 153f2af0086SNamhyung Kim if (callchain_param.value == CCVAL_COUNT && child && child->parent) { 154f2af0086SNamhyung Kim rem_node.count = child->parent->children_count - cumul_count; 155f2af0086SNamhyung Kim if (rem_node.count <= 0) 156f2af0086SNamhyung Kim return ret; 157f2af0086SNamhyung Kim } 158f2af0086SNamhyung Kim 1597ccf4f90SNamhyung Kim new_depth_mask &= ~(1 << (depth - 1)); 1605ab250caSNamhyung Kim ret += ipchain__fprintf_graph(fp, &rem_node, &rem_hits, depth, 1617ccf4f90SNamhyung Kim new_depth_mask, 0, total_samples, 1625ab250caSNamhyung Kim left_margin); 1637ccf4f90SNamhyung Kim } 1647ccf4f90SNamhyung Kim 1657ccf4f90SNamhyung Kim return ret; 1667ccf4f90SNamhyung Kim } 1677ccf4f90SNamhyung Kim 1687ed5d6e2SNamhyung Kim /* 1697ed5d6e2SNamhyung Kim * If have one single callchain root, don't bother printing 1707ed5d6e2SNamhyung Kim * its percentage (100 % in fractal mode and the same percentage 1717ed5d6e2SNamhyung Kim * than the hist in graph mode). This also avoid one level of column. 1727ed5d6e2SNamhyung Kim * 1737ed5d6e2SNamhyung Kim * However when percent-limit applied, it's possible that single callchain 1747ed5d6e2SNamhyung Kim * node have different (non-100% in fractal mode) percentage. 1757ed5d6e2SNamhyung Kim */ 1767ed5d6e2SNamhyung Kim static bool need_percent_display(struct rb_node *node, u64 parent_samples) 1777ed5d6e2SNamhyung Kim { 1787ed5d6e2SNamhyung Kim struct callchain_node *cnode; 1797ed5d6e2SNamhyung Kim 1807ed5d6e2SNamhyung Kim if (rb_next(node)) 1817ed5d6e2SNamhyung Kim return true; 1827ed5d6e2SNamhyung Kim 1837ed5d6e2SNamhyung Kim cnode = rb_entry(node, struct callchain_node, rb_node); 1847ed5d6e2SNamhyung Kim return callchain_cumul_hits(cnode) != parent_samples; 1857ed5d6e2SNamhyung Kim } 1867ed5d6e2SNamhyung Kim 1877ccf4f90SNamhyung Kim static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, 18854d27b31SNamhyung Kim u64 total_samples, u64 parent_samples, 18954d27b31SNamhyung Kim int left_margin) 1907ccf4f90SNamhyung Kim { 1917ccf4f90SNamhyung Kim struct callchain_node *cnode; 1927ccf4f90SNamhyung Kim struct callchain_list *chain; 1937ccf4f90SNamhyung Kim u32 entries_printed = 0; 1947ccf4f90SNamhyung Kim bool printed = false; 1957ccf4f90SNamhyung Kim struct rb_node *node; 1967ccf4f90SNamhyung Kim int i = 0; 1977ccf4f90SNamhyung Kim int ret = 0; 1982989ccaaSAndi Kleen char bf[1024]; 1997ccf4f90SNamhyung Kim 2007ccf4f90SNamhyung Kim node = rb_first(root); 2017ed5d6e2SNamhyung Kim if (node && !need_percent_display(node, parent_samples)) { 2027ccf4f90SNamhyung Kim cnode = rb_entry(node, struct callchain_node, rb_node); 2037ccf4f90SNamhyung Kim list_for_each_entry(chain, &cnode->val, list) { 2047ccf4f90SNamhyung Kim /* 2057ccf4f90SNamhyung Kim * If we sort by symbol, the first entry is the same than 2067ccf4f90SNamhyung Kim * the symbol. No need to print it otherwise it appears as 2077ccf4f90SNamhyung Kim * displayed twice. 2087ccf4f90SNamhyung Kim */ 209cfaa154bSNamhyung Kim if (!i++ && field_order == NULL && 210cfaa154bSNamhyung Kim sort_order && !prefixcmp(sort_order, "sym")) 2117ccf4f90SNamhyung Kim continue; 2127ccf4f90SNamhyung Kim if (!printed) { 2137ccf4f90SNamhyung Kim ret += callchain__fprintf_left_margin(fp, left_margin); 2147ccf4f90SNamhyung Kim ret += fprintf(fp, "|\n"); 2157ccf4f90SNamhyung Kim ret += callchain__fprintf_left_margin(fp, left_margin); 2167ccf4f90SNamhyung Kim ret += fprintf(fp, "---"); 2177ccf4f90SNamhyung Kim left_margin += 3; 2187ccf4f90SNamhyung Kim printed = true; 2197ccf4f90SNamhyung Kim } else 2207ccf4f90SNamhyung Kim ret += callchain__fprintf_left_margin(fp, left_margin); 2217ccf4f90SNamhyung Kim 2222989ccaaSAndi Kleen ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf), 2232989ccaaSAndi Kleen false)); 2247ccf4f90SNamhyung Kim 2257ccf4f90SNamhyung Kim if (++entries_printed == callchain_param.print_limit) 2267ccf4f90SNamhyung Kim break; 2277ccf4f90SNamhyung Kim } 2287ccf4f90SNamhyung Kim root = &cnode->rb_root; 2297ccf4f90SNamhyung Kim } 2307ccf4f90SNamhyung Kim 23154d27b31SNamhyung Kim if (callchain_param.mode == CHAIN_GRAPH_REL) 23254d27b31SNamhyung Kim total_samples = parent_samples; 23354d27b31SNamhyung Kim 2347ccf4f90SNamhyung Kim ret += __callchain__fprintf_graph(fp, root, total_samples, 2357ccf4f90SNamhyung Kim 1, 1, left_margin); 2363848c23bSNamhyung Kim if (ret) { 2373848c23bSNamhyung Kim /* do not add a blank line if it printed nothing */ 2387ccf4f90SNamhyung Kim ret += fprintf(fp, "\n"); 2393848c23bSNamhyung Kim } 2407ccf4f90SNamhyung Kim 2417ccf4f90SNamhyung Kim return ret; 2427ccf4f90SNamhyung Kim } 2437ccf4f90SNamhyung Kim 244316c7136SArnaldo Carvalho de Melo static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node, 2457ccf4f90SNamhyung Kim u64 total_samples) 2467ccf4f90SNamhyung Kim { 2477ccf4f90SNamhyung Kim struct callchain_list *chain; 2487ccf4f90SNamhyung Kim size_t ret = 0; 2492989ccaaSAndi Kleen char bf[1024]; 2507ccf4f90SNamhyung Kim 251316c7136SArnaldo Carvalho de Melo if (!node) 2527ccf4f90SNamhyung Kim return 0; 2537ccf4f90SNamhyung Kim 254316c7136SArnaldo Carvalho de Melo ret += __callchain__fprintf_flat(fp, node->parent, total_samples); 2557ccf4f90SNamhyung Kim 2567ccf4f90SNamhyung Kim 257316c7136SArnaldo Carvalho de Melo list_for_each_entry(chain, &node->val, list) { 2587ccf4f90SNamhyung Kim if (chain->ip >= PERF_CONTEXT_MAX) 2597ccf4f90SNamhyung Kim continue; 2602989ccaaSAndi Kleen ret += fprintf(fp, " %s\n", callchain_list__sym_name(chain, 2612989ccaaSAndi Kleen bf, sizeof(bf), false)); 2627ccf4f90SNamhyung Kim } 2637ccf4f90SNamhyung Kim 2647ccf4f90SNamhyung Kim return ret; 2657ccf4f90SNamhyung Kim } 2667ccf4f90SNamhyung Kim 267316c7136SArnaldo Carvalho de Melo static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree, 2687ccf4f90SNamhyung Kim u64 total_samples) 2697ccf4f90SNamhyung Kim { 2707ccf4f90SNamhyung Kim size_t ret = 0; 2717ccf4f90SNamhyung Kim u32 entries_printed = 0; 2727ccf4f90SNamhyung Kim struct callchain_node *chain; 273316c7136SArnaldo Carvalho de Melo struct rb_node *rb_node = rb_first(tree); 2747ccf4f90SNamhyung Kim 2757ccf4f90SNamhyung Kim while (rb_node) { 2767ccf4f90SNamhyung Kim chain = rb_entry(rb_node, struct callchain_node, rb_node); 2777ccf4f90SNamhyung Kim 2785ab250caSNamhyung Kim ret += fprintf(fp, " "); 2795ab250caSNamhyung Kim ret += callchain_node__fprintf_value(chain, fp, total_samples); 2805ab250caSNamhyung Kim ret += fprintf(fp, "\n"); 2817ccf4f90SNamhyung Kim ret += __callchain__fprintf_flat(fp, chain, total_samples); 2827ccf4f90SNamhyung Kim ret += fprintf(fp, "\n"); 2837ccf4f90SNamhyung Kim if (++entries_printed == callchain_param.print_limit) 2847ccf4f90SNamhyung Kim break; 2857ccf4f90SNamhyung Kim 2867ccf4f90SNamhyung Kim rb_node = rb_next(rb_node); 2877ccf4f90SNamhyung Kim } 2887ccf4f90SNamhyung Kim 2897ccf4f90SNamhyung Kim return ret; 2907ccf4f90SNamhyung Kim } 2917ccf4f90SNamhyung Kim 29226e77924SNamhyung Kim static size_t __callchain__fprintf_folded(FILE *fp, struct callchain_node *node) 29326e77924SNamhyung Kim { 29426e77924SNamhyung Kim const char *sep = symbol_conf.field_sep ?: ";"; 29526e77924SNamhyung Kim struct callchain_list *chain; 29626e77924SNamhyung Kim size_t ret = 0; 29726e77924SNamhyung Kim char bf[1024]; 29826e77924SNamhyung Kim bool first; 29926e77924SNamhyung Kim 30026e77924SNamhyung Kim if (!node) 30126e77924SNamhyung Kim return 0; 30226e77924SNamhyung Kim 30326e77924SNamhyung Kim ret += __callchain__fprintf_folded(fp, node->parent); 30426e77924SNamhyung Kim 30526e77924SNamhyung Kim first = (ret == 0); 30626e77924SNamhyung Kim list_for_each_entry(chain, &node->val, list) { 30726e77924SNamhyung Kim if (chain->ip >= PERF_CONTEXT_MAX) 30826e77924SNamhyung Kim continue; 30926e77924SNamhyung Kim ret += fprintf(fp, "%s%s", first ? "" : sep, 31026e77924SNamhyung Kim callchain_list__sym_name(chain, 31126e77924SNamhyung Kim bf, sizeof(bf), false)); 31226e77924SNamhyung Kim first = false; 31326e77924SNamhyung Kim } 31426e77924SNamhyung Kim 31526e77924SNamhyung Kim return ret; 31626e77924SNamhyung Kim } 31726e77924SNamhyung Kim 31826e77924SNamhyung Kim static size_t callchain__fprintf_folded(FILE *fp, struct rb_root *tree, 31926e77924SNamhyung Kim u64 total_samples) 32026e77924SNamhyung Kim { 32126e77924SNamhyung Kim size_t ret = 0; 32226e77924SNamhyung Kim u32 entries_printed = 0; 32326e77924SNamhyung Kim struct callchain_node *chain; 32426e77924SNamhyung Kim struct rb_node *rb_node = rb_first(tree); 32526e77924SNamhyung Kim 32626e77924SNamhyung Kim while (rb_node) { 32726e77924SNamhyung Kim 32826e77924SNamhyung Kim chain = rb_entry(rb_node, struct callchain_node, rb_node); 32926e77924SNamhyung Kim 3305ab250caSNamhyung Kim ret += callchain_node__fprintf_value(chain, fp, total_samples); 3315ab250caSNamhyung Kim ret += fprintf(fp, " "); 33226e77924SNamhyung Kim ret += __callchain__fprintf_folded(fp, chain); 33326e77924SNamhyung Kim ret += fprintf(fp, "\n"); 33426e77924SNamhyung Kim if (++entries_printed == callchain_param.print_limit) 33526e77924SNamhyung Kim break; 33626e77924SNamhyung Kim 33726e77924SNamhyung Kim rb_node = rb_next(rb_node); 33826e77924SNamhyung Kim } 33926e77924SNamhyung Kim 34026e77924SNamhyung Kim return ret; 34126e77924SNamhyung Kim } 34226e77924SNamhyung Kim 3437ccf4f90SNamhyung Kim static size_t hist_entry_callchain__fprintf(struct hist_entry *he, 3447ccf4f90SNamhyung Kim u64 total_samples, int left_margin, 3457ccf4f90SNamhyung Kim FILE *fp) 3467ccf4f90SNamhyung Kim { 34754d27b31SNamhyung Kim u64 parent_samples = he->stat.period; 34854d27b31SNamhyung Kim 34954d27b31SNamhyung Kim if (symbol_conf.cumulate_callchain) 35054d27b31SNamhyung Kim parent_samples = he->stat_acc->period; 35154d27b31SNamhyung Kim 3527ccf4f90SNamhyung Kim switch (callchain_param.mode) { 3537ccf4f90SNamhyung Kim case CHAIN_GRAPH_REL: 35454d27b31SNamhyung Kim return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, 35554d27b31SNamhyung Kim parent_samples, left_margin); 3567ccf4f90SNamhyung Kim break; 3577ccf4f90SNamhyung Kim case CHAIN_GRAPH_ABS: 3587ccf4f90SNamhyung Kim return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, 35954d27b31SNamhyung Kim parent_samples, left_margin); 3607ccf4f90SNamhyung Kim break; 3617ccf4f90SNamhyung Kim case CHAIN_FLAT: 3627ccf4f90SNamhyung Kim return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); 3637ccf4f90SNamhyung Kim break; 36426e77924SNamhyung Kim case CHAIN_FOLDED: 36526e77924SNamhyung Kim return callchain__fprintf_folded(fp, &he->sorted_chain, total_samples); 36626e77924SNamhyung Kim break; 3677ccf4f90SNamhyung Kim case CHAIN_NONE: 3687ccf4f90SNamhyung Kim break; 3697ccf4f90SNamhyung Kim default: 3707ccf4f90SNamhyung Kim pr_err("Bad callchain mode\n"); 3717ccf4f90SNamhyung Kim } 3727ccf4f90SNamhyung Kim 3737ccf4f90SNamhyung Kim return 0; 3747ccf4f90SNamhyung Kim } 3757ccf4f90SNamhyung Kim 376*bd28d0c5SJiri Olsa int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, 3779da44db1SJiri Olsa struct perf_hpp_list *hpp_list) 378be0e6d10SJiri Olsa { 379be0e6d10SJiri Olsa const char *sep = symbol_conf.field_sep; 380be0e6d10SJiri Olsa struct perf_hpp_fmt *fmt; 381be0e6d10SJiri Olsa char *start = hpp->buf; 382be0e6d10SJiri Olsa int ret; 383be0e6d10SJiri Olsa bool first = true; 384be0e6d10SJiri Olsa 385be0e6d10SJiri Olsa if (symbol_conf.exclude_other && !he->parent) 386be0e6d10SJiri Olsa return 0; 387be0e6d10SJiri Olsa 3889da44db1SJiri Olsa perf_hpp_list__for_each_format(hpp_list, fmt) { 389361459f1SNamhyung Kim if (perf_hpp__should_skip(fmt, he->hists)) 390e67d49a7SNamhyung Kim continue; 391e67d49a7SNamhyung Kim 392be0e6d10SJiri Olsa /* 393be0e6d10SJiri Olsa * If there's no field_sep, we still need 394be0e6d10SJiri Olsa * to display initial ' '. 395be0e6d10SJiri Olsa */ 396be0e6d10SJiri Olsa if (!sep || !first) { 397be0e6d10SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); 398be0e6d10SJiri Olsa advance_hpp(hpp, ret); 399be0e6d10SJiri Olsa } else 400be0e6d10SJiri Olsa first = false; 401be0e6d10SJiri Olsa 4029754c4f9SJiri Olsa if (perf_hpp__use_color() && fmt->color) 403be0e6d10SJiri Olsa ret = fmt->color(fmt, hpp, he); 404be0e6d10SJiri Olsa else 405be0e6d10SJiri Olsa ret = fmt->entry(fmt, hpp, he); 406be0e6d10SJiri Olsa 40789fee709SArnaldo Carvalho de Melo ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret); 408be0e6d10SJiri Olsa advance_hpp(hpp, ret); 409be0e6d10SJiri Olsa } 410be0e6d10SJiri Olsa 411be0e6d10SJiri Olsa return hpp->buf - start; 412be0e6d10SJiri Olsa } 413be0e6d10SJiri Olsa 4149da44db1SJiri Olsa static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) 4159da44db1SJiri Olsa { 4169da44db1SJiri Olsa return __hist_entry__snprintf(he, hpp, he->hists->hpp_list); 4179da44db1SJiri Olsa } 4189da44db1SJiri Olsa 419ef86d68aSNamhyung Kim static int hist_entry__hierarchy_fprintf(struct hist_entry *he, 420ef86d68aSNamhyung Kim struct perf_hpp *hpp, 4212dbbe9f2SNamhyung Kim struct hists *hists, 422ef86d68aSNamhyung Kim FILE *fp) 423ef86d68aSNamhyung Kim { 424ef86d68aSNamhyung Kim const char *sep = symbol_conf.field_sep; 425ef86d68aSNamhyung Kim struct perf_hpp_fmt *fmt; 426f58c95e3SNamhyung Kim struct perf_hpp_list_node *fmt_node; 427ef86d68aSNamhyung Kim char *buf = hpp->buf; 428cb1fab91SNamhyung Kim size_t size = hpp->size; 429ef86d68aSNamhyung Kim int ret, printed = 0; 430ef86d68aSNamhyung Kim bool first = true; 431ef86d68aSNamhyung Kim 432ef86d68aSNamhyung Kim if (symbol_conf.exclude_other && !he->parent) 433ef86d68aSNamhyung Kim return 0; 434ef86d68aSNamhyung Kim 435ef86d68aSNamhyung Kim ret = scnprintf(hpp->buf, hpp->size, "%*s", he->depth * HIERARCHY_INDENT, ""); 436ef86d68aSNamhyung Kim advance_hpp(hpp, ret); 437ef86d68aSNamhyung Kim 438f58c95e3SNamhyung Kim /* the first hpp_list_node is for overhead columns */ 439f58c95e3SNamhyung Kim fmt_node = list_first_entry(&hists->hpp_formats, 440f58c95e3SNamhyung Kim struct perf_hpp_list_node, list); 441f58c95e3SNamhyung Kim perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 442ef86d68aSNamhyung Kim /* 443ef86d68aSNamhyung Kim * If there's no field_sep, we still need 444ef86d68aSNamhyung Kim * to display initial ' '. 445ef86d68aSNamhyung Kim */ 446ef86d68aSNamhyung Kim if (!sep || !first) { 447ef86d68aSNamhyung Kim ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); 448ef86d68aSNamhyung Kim advance_hpp(hpp, ret); 449ef86d68aSNamhyung Kim } else 450ef86d68aSNamhyung Kim first = false; 451ef86d68aSNamhyung Kim 452ef86d68aSNamhyung Kim if (perf_hpp__use_color() && fmt->color) 453ef86d68aSNamhyung Kim ret = fmt->color(fmt, hpp, he); 454ef86d68aSNamhyung Kim else 455ef86d68aSNamhyung Kim ret = fmt->entry(fmt, hpp, he); 456ef86d68aSNamhyung Kim 457ef86d68aSNamhyung Kim ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret); 458ef86d68aSNamhyung Kim advance_hpp(hpp, ret); 459ef86d68aSNamhyung Kim } 460ef86d68aSNamhyung Kim 4611b2dbbf4SNamhyung Kim if (!sep) 462ef86d68aSNamhyung Kim ret = scnprintf(hpp->buf, hpp->size, "%*s", 4632dbbe9f2SNamhyung Kim (hists->nr_hpp_node - 2) * HIERARCHY_INDENT, ""); 464ef86d68aSNamhyung Kim advance_hpp(hpp, ret); 465ef86d68aSNamhyung Kim 466cb1fab91SNamhyung Kim printed += fprintf(fp, "%s", buf); 467cb1fab91SNamhyung Kim 4681b2dbbf4SNamhyung Kim perf_hpp_list__for_each_format(he->hpp_list, fmt) { 469cb1fab91SNamhyung Kim hpp->buf = buf; 470cb1fab91SNamhyung Kim hpp->size = size; 471cb1fab91SNamhyung Kim 472ef86d68aSNamhyung Kim /* 473ef86d68aSNamhyung Kim * No need to call hist_entry__snprintf_alignment() since this 474ef86d68aSNamhyung Kim * fmt is always the last column in the hierarchy mode. 475ef86d68aSNamhyung Kim */ 476ef86d68aSNamhyung Kim if (perf_hpp__use_color() && fmt->color) 477ef86d68aSNamhyung Kim fmt->color(fmt, hpp, he); 478ef86d68aSNamhyung Kim else 479ef86d68aSNamhyung Kim fmt->entry(fmt, hpp, he); 480ef86d68aSNamhyung Kim 481cb1fab91SNamhyung Kim /* 482cb1fab91SNamhyung Kim * dynamic entries are right-aligned but we want left-aligned 483cb1fab91SNamhyung Kim * in the hierarchy mode 484cb1fab91SNamhyung Kim */ 4851b2dbbf4SNamhyung Kim printed += fprintf(fp, "%s%s", sep ?: " ", ltrim(buf)); 4861b2dbbf4SNamhyung Kim } 4871b2dbbf4SNamhyung Kim printed += putc('\n', fp); 488ef86d68aSNamhyung Kim 489ef86d68aSNamhyung Kim if (symbol_conf.use_callchain && he->leaf) { 490ef86d68aSNamhyung Kim u64 total = hists__total_period(hists); 491ef86d68aSNamhyung Kim 492ef86d68aSNamhyung Kim printed += hist_entry_callchain__fprintf(he, total, 0, fp); 493ef86d68aSNamhyung Kim goto out; 494ef86d68aSNamhyung Kim } 495ef86d68aSNamhyung Kim 496ef86d68aSNamhyung Kim out: 497ef86d68aSNamhyung Kim return printed; 498ef86d68aSNamhyung Kim } 499ef86d68aSNamhyung Kim 500000078bcSNamhyung Kim static int hist_entry__fprintf(struct hist_entry *he, size_t size, 501d05e3aaeSJiri Olsa char *bf, size_t bfsz, FILE *fp, 502d05e3aaeSJiri Olsa bool use_callchain) 503000078bcSNamhyung Kim { 504000078bcSNamhyung Kim int ret; 505ea251d51SNamhyung Kim struct perf_hpp hpp = { 506ea251d51SNamhyung Kim .buf = bf, 507ea251d51SNamhyung Kim .size = size, 508ea251d51SNamhyung Kim }; 5098f1d1b44SJiri Olsa struct hists *hists = he->hists; 5107e597d32SNamhyung Kim u64 total_period = hists->stats.total_period; 511000078bcSNamhyung Kim 51299cf666cSArnaldo Carvalho de Melo if (size == 0 || size > bfsz) 51399cf666cSArnaldo Carvalho de Melo size = hpp.size = bfsz; 514000078bcSNamhyung Kim 5152dbbe9f2SNamhyung Kim if (symbol_conf.report_hierarchy) 5162dbbe9f2SNamhyung Kim return hist_entry__hierarchy_fprintf(he, &hpp, hists, fp); 517ef86d68aSNamhyung Kim 51826d8b338SNamhyung Kim hist_entry__snprintf(he, &hpp); 519000078bcSNamhyung Kim 520000078bcSNamhyung Kim ret = fprintf(fp, "%s\n", bf); 521000078bcSNamhyung Kim 522d05e3aaeSJiri Olsa if (use_callchain) 5237e597d32SNamhyung Kim ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); 524000078bcSNamhyung Kim 525000078bcSNamhyung Kim return ret; 526000078bcSNamhyung Kim } 527000078bcSNamhyung Kim 5282dbbe9f2SNamhyung Kim static int print_hierarchy_indent(const char *sep, int indent, 5298e2fc44fSNamhyung Kim const char *line, FILE *fp) 5308e2fc44fSNamhyung Kim { 5312dbbe9f2SNamhyung Kim if (sep != NULL || indent < 2) 5328e2fc44fSNamhyung Kim return 0; 5338e2fc44fSNamhyung Kim 5342dbbe9f2SNamhyung Kim return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line); 5358e2fc44fSNamhyung Kim } 5368e2fc44fSNamhyung Kim 537195bc0f8SNamhyung Kim static int hists__fprintf_hierarchy_headers(struct hists *hists, 538195bc0f8SNamhyung Kim struct perf_hpp *hpp, FILE *fp) 5398e2fc44fSNamhyung Kim { 540f58c95e3SNamhyung Kim bool first_node, first_col; 5412dbbe9f2SNamhyung Kim int indent; 542cb1fab91SNamhyung Kim int depth; 5438e2fc44fSNamhyung Kim unsigned width = 0; 5448e2fc44fSNamhyung Kim unsigned header_width = 0; 5458e2fc44fSNamhyung Kim struct perf_hpp_fmt *fmt; 546f58c95e3SNamhyung Kim struct perf_hpp_list_node *fmt_node; 547195bc0f8SNamhyung Kim const char *sep = symbol_conf.field_sep; 5488e2fc44fSNamhyung Kim 5492dbbe9f2SNamhyung Kim indent = hists->nr_hpp_node; 5508e2fc44fSNamhyung Kim 5518e2fc44fSNamhyung Kim /* preserve max indent depth for column headers */ 5522dbbe9f2SNamhyung Kim print_hierarchy_indent(sep, indent, spaces, fp); 5538e2fc44fSNamhyung Kim 554f58c95e3SNamhyung Kim /* the first hpp_list_node is for overhead columns */ 555f58c95e3SNamhyung Kim fmt_node = list_first_entry(&hists->hpp_formats, 556f58c95e3SNamhyung Kim struct perf_hpp_list_node, list); 5578e2fc44fSNamhyung Kim 558f58c95e3SNamhyung Kim perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 55929659ab4SJiri Olsa fmt->header(fmt, hpp, hists, 0, NULL); 560f58c95e3SNamhyung Kim fprintf(fp, "%s%s", hpp->buf, sep ?: " "); 5618e2fc44fSNamhyung Kim } 5628e2fc44fSNamhyung Kim 5638e2fc44fSNamhyung Kim /* combine sort headers with ' / ' */ 564f58c95e3SNamhyung Kim first_node = true; 565f58c95e3SNamhyung Kim list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) { 566f58c95e3SNamhyung Kim if (!first_node) 567f58c95e3SNamhyung Kim header_width += fprintf(fp, " / "); 568f58c95e3SNamhyung Kim first_node = false; 569f58c95e3SNamhyung Kim 570f58c95e3SNamhyung Kim first_col = true; 571f58c95e3SNamhyung Kim perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 5728e2fc44fSNamhyung Kim if (perf_hpp__should_skip(fmt, hists)) 5738e2fc44fSNamhyung Kim continue; 5748e2fc44fSNamhyung Kim 575f58c95e3SNamhyung Kim if (!first_col) 576f58c95e3SNamhyung Kim header_width += fprintf(fp, "+"); 577f58c95e3SNamhyung Kim first_col = false; 5788e2fc44fSNamhyung Kim 57929659ab4SJiri Olsa fmt->header(fmt, hpp, hists, 0, NULL); 5808e2fc44fSNamhyung Kim 5817d6a7e78SJiri Olsa header_width += fprintf(fp, "%s", trim(hpp->buf)); 5828e2fc44fSNamhyung Kim } 583f58c95e3SNamhyung Kim } 5848e2fc44fSNamhyung Kim 5858e2fc44fSNamhyung Kim fprintf(fp, "\n# "); 5868e2fc44fSNamhyung Kim 5878e2fc44fSNamhyung Kim /* preserve max indent depth for initial dots */ 5882dbbe9f2SNamhyung Kim print_hierarchy_indent(sep, indent, dots, fp); 5898e2fc44fSNamhyung Kim 590f58c95e3SNamhyung Kim /* the first hpp_list_node is for overhead columns */ 591f58c95e3SNamhyung Kim fmt_node = list_first_entry(&hists->hpp_formats, 592f58c95e3SNamhyung Kim struct perf_hpp_list_node, list); 5938e2fc44fSNamhyung Kim 594f58c95e3SNamhyung Kim first_col = true; 595f58c95e3SNamhyung Kim perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 596f58c95e3SNamhyung Kim if (!first_col) 597f58c95e3SNamhyung Kim fprintf(fp, "%s", sep ?: ".."); 598f58c95e3SNamhyung Kim first_col = false; 5998e2fc44fSNamhyung Kim 600da1b0407SJiri Olsa width = fmt->width(fmt, hpp, hists); 6018e2fc44fSNamhyung Kim fprintf(fp, "%.*s", width, dots); 6028e2fc44fSNamhyung Kim } 6038e2fc44fSNamhyung Kim 604cb1fab91SNamhyung Kim depth = 0; 605f58c95e3SNamhyung Kim list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) { 606f58c95e3SNamhyung Kim first_col = true; 607f58c95e3SNamhyung Kim width = depth * HIERARCHY_INDENT; 608f58c95e3SNamhyung Kim 609f58c95e3SNamhyung Kim perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 6108e2fc44fSNamhyung Kim if (perf_hpp__should_skip(fmt, hists)) 6118e2fc44fSNamhyung Kim continue; 6128e2fc44fSNamhyung Kim 613f58c95e3SNamhyung Kim if (!first_col) 614f58c95e3SNamhyung Kim width++; /* for '+' sign between column header */ 615f58c95e3SNamhyung Kim first_col = false; 616f58c95e3SNamhyung Kim 617da1b0407SJiri Olsa width += fmt->width(fmt, hpp, hists); 618f58c95e3SNamhyung Kim } 619cb1fab91SNamhyung Kim 6208e2fc44fSNamhyung Kim if (width > header_width) 6218e2fc44fSNamhyung Kim header_width = width; 622cb1fab91SNamhyung Kim 623cb1fab91SNamhyung Kim depth++; 6248e2fc44fSNamhyung Kim } 6258e2fc44fSNamhyung Kim 6268e2fc44fSNamhyung Kim fprintf(fp, "%s%-.*s", sep ?: " ", header_width, dots); 6278e2fc44fSNamhyung Kim 6288e2fc44fSNamhyung Kim fprintf(fp, "\n#\n"); 6298e2fc44fSNamhyung Kim 6308e2fc44fSNamhyung Kim return 2; 6318e2fc44fSNamhyung Kim } 6328e2fc44fSNamhyung Kim 633f3705b06SJiri Olsa static void fprintf_line(struct hists *hists, struct perf_hpp *hpp, 634f3705b06SJiri Olsa int line, FILE *fp) 6357ccf4f90SNamhyung Kim { 6361240005eSJiri Olsa struct perf_hpp_fmt *fmt; 6377ccf4f90SNamhyung Kim const char *sep = symbol_conf.field_sep; 6385395a048SJiri Olsa bool first = true; 63929659ab4SJiri Olsa int span = 0; 6407ccf4f90SNamhyung Kim 641f0786af5SJiri Olsa hists__for_each_format(hists, fmt) { 642361459f1SNamhyung Kim if (perf_hpp__should_skip(fmt, hists)) 643e67d49a7SNamhyung Kim continue; 644e67d49a7SNamhyung Kim 64529659ab4SJiri Olsa if (!first && !span) 646ea251d51SNamhyung Kim fprintf(fp, "%s", sep ?: " "); 6475395a048SJiri Olsa else 6485395a048SJiri Olsa first = false; 6497ccf4f90SNamhyung Kim 65029659ab4SJiri Olsa fmt->header(fmt, hpp, hists, line, &span); 65129659ab4SJiri Olsa 65229659ab4SJiri Olsa if (!span) 6537a72a2e5SJiri Olsa fprintf(fp, "%s", hpp->buf); 6547ccf4f90SNamhyung Kim } 655f3705b06SJiri Olsa } 6567ccf4f90SNamhyung Kim 657f3705b06SJiri Olsa static int 658f3705b06SJiri Olsa hists__fprintf_standard_headers(struct hists *hists, 659f3705b06SJiri Olsa struct perf_hpp *hpp, 660f3705b06SJiri Olsa FILE *fp) 661f3705b06SJiri Olsa { 662f3705b06SJiri Olsa struct perf_hpp_list *hpp_list = hists->hpp_list; 663f3705b06SJiri Olsa struct perf_hpp_fmt *fmt; 664f3705b06SJiri Olsa unsigned int width; 665f3705b06SJiri Olsa const char *sep = symbol_conf.field_sep; 666f3705b06SJiri Olsa bool first = true; 667f3705b06SJiri Olsa int line; 668f3705b06SJiri Olsa 669f3705b06SJiri Olsa for (line = 0; line < hpp_list->nr_header_lines; line++) { 670f3705b06SJiri Olsa /* first # is displayed one level up */ 671f3705b06SJiri Olsa if (line) 672f3705b06SJiri Olsa fprintf(fp, "# "); 673f3705b06SJiri Olsa fprintf_line(hists, hpp, line, fp); 6747ccf4f90SNamhyung Kim fprintf(fp, "\n"); 675f3705b06SJiri Olsa } 6767ccf4f90SNamhyung Kim 6777ccf4f90SNamhyung Kim if (sep) 678f3705b06SJiri Olsa return hpp_list->nr_header_lines; 6797ccf4f90SNamhyung Kim 6805395a048SJiri Olsa first = true; 6815395a048SJiri Olsa 682ea251d51SNamhyung Kim fprintf(fp, "# "); 683ea251d51SNamhyung Kim 684f0786af5SJiri Olsa hists__for_each_format(hists, fmt) { 6851240005eSJiri Olsa unsigned int i; 686ea251d51SNamhyung Kim 687361459f1SNamhyung Kim if (perf_hpp__should_skip(fmt, hists)) 688e67d49a7SNamhyung Kim continue; 689e67d49a7SNamhyung Kim 6905395a048SJiri Olsa if (!first) 691ea251d51SNamhyung Kim fprintf(fp, "%s", sep ?: " "); 6925395a048SJiri Olsa else 6935395a048SJiri Olsa first = false; 694ea251d51SNamhyung Kim 695da1b0407SJiri Olsa width = fmt->width(fmt, hpp, hists); 696ea251d51SNamhyung Kim for (i = 0; i < width; i++) 697ea251d51SNamhyung Kim fprintf(fp, "."); 6987ccf4f90SNamhyung Kim } 699ea251d51SNamhyung Kim 7007ccf4f90SNamhyung Kim fprintf(fp, "\n"); 7017ccf4f90SNamhyung Kim fprintf(fp, "#\n"); 702f3705b06SJiri Olsa return hpp_list->nr_header_lines + 2; 70336592ebbSJiri Olsa } 70436592ebbSJiri Olsa 7057a72a2e5SJiri Olsa static int hists__fprintf_headers(struct hists *hists, FILE *fp) 7067a72a2e5SJiri Olsa { 707d5278220SJiri Olsa char bf[1024]; 7087a72a2e5SJiri Olsa struct perf_hpp dummy_hpp = { 7097a72a2e5SJiri Olsa .buf = bf, 7107a72a2e5SJiri Olsa .size = sizeof(bf), 7117a72a2e5SJiri Olsa }; 7127a72a2e5SJiri Olsa 7137a72a2e5SJiri Olsa fprintf(fp, "# "); 7147a72a2e5SJiri Olsa 7157a72a2e5SJiri Olsa if (symbol_conf.report_hierarchy) 7167a72a2e5SJiri Olsa return hists__fprintf_hierarchy_headers(hists, &dummy_hpp, fp); 7177a72a2e5SJiri Olsa else 7187a72a2e5SJiri Olsa return hists__fprintf_standard_headers(hists, &dummy_hpp, fp); 7197a72a2e5SJiri Olsa 7207a72a2e5SJiri Olsa } 7217a72a2e5SJiri Olsa 72236592ebbSJiri Olsa size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 723d05e3aaeSJiri Olsa int max_cols, float min_pcnt, FILE *fp, 724d05e3aaeSJiri Olsa bool use_callchain) 72536592ebbSJiri Olsa { 72636592ebbSJiri Olsa struct rb_node *nd; 72736592ebbSJiri Olsa size_t ret = 0; 72836592ebbSJiri Olsa const char *sep = symbol_conf.field_sep; 72936592ebbSJiri Olsa int nr_rows = 0; 73036592ebbSJiri Olsa size_t linesz; 73136592ebbSJiri Olsa char *line = NULL; 73236592ebbSJiri Olsa unsigned indent; 73336592ebbSJiri Olsa 73436592ebbSJiri Olsa init_rem_hits(); 73536592ebbSJiri Olsa 736e3b60bc9SNamhyung Kim hists__reset_column_width(hists); 73736592ebbSJiri Olsa 73836592ebbSJiri Olsa if (symbol_conf.col_width_list_str) 73936592ebbSJiri Olsa perf_hpp__set_user_width(symbol_conf.col_width_list_str); 74036592ebbSJiri Olsa 74136592ebbSJiri Olsa if (show_header) 74236592ebbSJiri Olsa nr_rows += hists__fprintf_headers(hists, fp); 74336592ebbSJiri Olsa 74436592ebbSJiri Olsa if (max_rows && nr_rows >= max_rows) 7457ccf4f90SNamhyung Kim goto out; 7467ccf4f90SNamhyung Kim 74799cf666cSArnaldo Carvalho de Melo linesz = hists__sort_list_width(hists) + 3 + 1; 7489754c4f9SJiri Olsa linesz += perf_hpp__color_overhead(); 74999cf666cSArnaldo Carvalho de Melo line = malloc(linesz); 75099cf666cSArnaldo Carvalho de Melo if (line == NULL) { 75199cf666cSArnaldo Carvalho de Melo ret = -1; 75299cf666cSArnaldo Carvalho de Melo goto out; 75399cf666cSArnaldo Carvalho de Melo } 75499cf666cSArnaldo Carvalho de Melo 755bd4abd39SNamhyung Kim indent = hists__overhead_width(hists) + 4; 756bd4abd39SNamhyung Kim 757ef86d68aSNamhyung Kim for (nd = rb_first(&hists->entries); nd; nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD)) { 7587ccf4f90SNamhyung Kim struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 75914135663SNamhyung Kim float percent; 7607ccf4f90SNamhyung Kim 7617ccf4f90SNamhyung Kim if (h->filtered) 7627ccf4f90SNamhyung Kim continue; 7637ccf4f90SNamhyung Kim 76414135663SNamhyung Kim percent = hist_entry__get_percent_limit(h); 765064f1981SNamhyung Kim if (percent < min_pcnt) 766064f1981SNamhyung Kim continue; 767064f1981SNamhyung Kim 768d05e3aaeSJiri Olsa ret += hist_entry__fprintf(h, max_cols, line, linesz, fp, use_callchain); 7697ccf4f90SNamhyung Kim 7707ccf4f90SNamhyung Kim if (max_rows && ++nr_rows >= max_rows) 77199cf666cSArnaldo Carvalho de Melo break; 7727ccf4f90SNamhyung Kim 773bd4abd39SNamhyung Kim /* 774bd4abd39SNamhyung Kim * If all children are filtered out or percent-limited, 775bd4abd39SNamhyung Kim * display "no entry >= x.xx%" message. 776bd4abd39SNamhyung Kim */ 777bd4abd39SNamhyung Kim if (!h->leaf && !hist_entry__has_hierarchy_children(h, min_pcnt)) { 778f58c95e3SNamhyung Kim int depth = hists->nr_hpp_node + h->depth + 1; 779bd4abd39SNamhyung Kim 780f58c95e3SNamhyung Kim print_hierarchy_indent(sep, depth, spaces, fp); 781bd4abd39SNamhyung Kim fprintf(fp, "%*sno entry >= %.2f%%\n", indent, "", min_pcnt); 782bd4abd39SNamhyung Kim 783bd4abd39SNamhyung Kim if (max_rows && ++nr_rows >= max_rows) 784bd4abd39SNamhyung Kim break; 785bd4abd39SNamhyung Kim } 786bd4abd39SNamhyung Kim 7877ccf4f90SNamhyung Kim if (h->ms.map == NULL && verbose > 1) { 78893d5731dSArnaldo Carvalho de Melo __map_groups__fprintf_maps(h->thread->mg, 789acebd408SJiri Olsa MAP__FUNCTION, fp); 7907ccf4f90SNamhyung Kim fprintf(fp, "%.10s end\n", graph_dotted_line); 7917ccf4f90SNamhyung Kim } 7927ccf4f90SNamhyung Kim } 79399cf666cSArnaldo Carvalho de Melo 79499cf666cSArnaldo Carvalho de Melo free(line); 7957ccf4f90SNamhyung Kim out: 79674cf249dSArnaldo Carvalho de Melo zfree(&rem_sq_bracket); 7977ccf4f90SNamhyung Kim 7987ccf4f90SNamhyung Kim return ret; 7997ccf4f90SNamhyung Kim } 8007ccf4f90SNamhyung Kim 80152168eeaSArnaldo Carvalho de Melo size_t events_stats__fprintf(struct events_stats *stats, FILE *fp) 8027ccf4f90SNamhyung Kim { 8037ccf4f90SNamhyung Kim int i; 8047ccf4f90SNamhyung Kim size_t ret = 0; 8057ccf4f90SNamhyung Kim 8067ccf4f90SNamhyung Kim for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 8077ccf4f90SNamhyung Kim const char *name; 8087ccf4f90SNamhyung Kim 80952168eeaSArnaldo Carvalho de Melo if (stats->nr_events[i] == 0) 8107ccf4f90SNamhyung Kim continue; 8117ccf4f90SNamhyung Kim 8127ccf4f90SNamhyung Kim name = perf_event__name(i); 8137ccf4f90SNamhyung Kim if (!strcmp(name, "UNKNOWN")) 8147ccf4f90SNamhyung Kim continue; 8157ccf4f90SNamhyung Kim 8167ccf4f90SNamhyung Kim ret += fprintf(fp, "%16s events: %10d\n", name, 81752168eeaSArnaldo Carvalho de Melo stats->nr_events[i]); 8187ccf4f90SNamhyung Kim } 8197ccf4f90SNamhyung Kim 8207ccf4f90SNamhyung Kim return ret; 8217ccf4f90SNamhyung Kim } 822