1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h> 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/util.h" 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/hist.h" 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/sort.h" 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "../../util/evsel.h" 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret = fprintf(fp, " "); 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < left_margin; i++) 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, " "); 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int left_margin) 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret = callchain__fprintf_left_margin(fp, left_margin); 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < depth; i++) 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (depth_mask & (1 << i)) 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "| "); 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, " "); 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "\n"); 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int depth, int depth_mask, int period, 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_samples, u64 hits, 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int left_margin) 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret = 0; 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += callchain__fprintf_left_margin(fp, left_margin); 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < depth; i++) { 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (depth_mask & (1 << i)) 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "|"); 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, " "); 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!period && i == depth - 1) { 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng double percent; 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng percent = hits * 100.0 / total_samples; 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent); 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "%s", " "); 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (chain->ms.sym) 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "%s\n", chain->ms.sym->name); 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct symbol *rem_sq_bracket; 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct callchain_list rem_hits; 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void init_rem_hits(void) 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!rem_sq_bracket) { 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(stderr, "Not enough memory to display remaining hits\n"); 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strcpy(rem_sq_bracket->name, "[...]"); 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rem_hits.ms.sym = rem_sq_bracket; 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_samples, int depth, 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int depth_mask, int left_margin) 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *node, *next; 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct callchain_node *child; 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct callchain_list *chain; 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int new_depth_mask = depth_mask; 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 remaining; 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret = 0; 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng uint entries_printed = 0; 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng remaining = total_samples; 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng node = rb_first(root); 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (node) { 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 new_total; 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 cumul; 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng child = rb_entry(node, struct callchain_node, rb_node); 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cumul = callchain_cumul_hits(child); 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng remaining -= cumul; 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * The depth mask manages the output of pipes that show 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * the depth. We don't want to keep the pipes of the current 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * level for the last child of this depth. 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Except if we have remaining filtered hits. They will 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * supersede the last child 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = rb_next(node); 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_depth_mask &= ~(1 << (depth - 1)); 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * But we keep the older depth mask for the line separator 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * to keep the level link until we reach the last child 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += ipchain__fprintf_graph_line(fp, depth, depth_mask, 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin); 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng i = 0; 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(chain, &child->val, list) { 125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += ipchain__fprintf_graph(fp, chain, depth, 126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_depth_mask, i++, 127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng total_samples, 128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cumul, 129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin); 130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (callchain_param.mode == CHAIN_GRAPH_REL) 133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_total = child->children_hit; 134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_total = total_samples; 136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += __callchain__fprintf_graph(fp, &child->rb_root, new_total, 138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng depth + 1, 139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_depth_mask | (1 << depth), 140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin); 141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng node = next; 142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (++entries_printed == callchain_param.print_limit) 143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (callchain_param.mode == CHAIN_GRAPH_REL && 147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng remaining && remaining != total_samples) { 148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!rem_sq_bracket) 150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_depth_mask &= ~(1 << (depth - 1)); 153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += ipchain__fprintf_graph(fp, &rem_hits, depth, 154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_depth_mask, 0, total_samples, 155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng remaining, left_margin); 156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, 162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_samples, int left_margin) 163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct callchain_node *cnode; 165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct callchain_list *chain; 166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u32 entries_printed = 0; 167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool printed = false; 168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *node; 169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i = 0; 170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret = 0; 171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * If have one single callchain root, don't bother printing 174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * its percentage (100 % in fractal mode and the same percentage 175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * than the hist in graph mode). This also avoid one level of column. 176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng node = rb_first(root); 178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (node && !rb_next(node)) { 179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cnode = rb_entry(node, struct callchain_node, rb_node); 180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(chain, &cnode->val, list) { 181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * If we sort by symbol, the first entry is the same than 183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * the symbol. No need to print it otherwise it appears as 184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * displayed twice. 185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!i++ && sort__first_dimension == SORT_SYM) 187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!printed) { 189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += callchain__fprintf_left_margin(fp, left_margin); 190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "|\n"); 191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += callchain__fprintf_left_margin(fp, left_margin); 192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "---"); 193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin += 3; 194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed = true; 195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += callchain__fprintf_left_margin(fp, left_margin); 197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (chain->ms.sym) 199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, " %s\n", chain->ms.sym->name); 200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); 202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (++entries_printed == callchain_param.print_limit) 204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng root = &cnode->rb_root; 207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += __callchain__fprintf_graph(fp, root, total_samples, 210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1, 1, left_margin); 211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "\n"); 212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t __callchain__fprintf_flat(FILE *fp, 217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct callchain_node *self, 218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_samples) 219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct callchain_list *chain; 221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret = 0; 222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!self) 224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += __callchain__fprintf_flat(fp, self->parent, total_samples); 227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(chain, &self->val, list) { 230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (chain->ip >= PERF_CONTEXT_MAX) 231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (chain->ms.sym) 233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, " %s\n", chain->ms.sym->name); 234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, " %p\n", 236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (void *)(long)chain->ip); 237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, 243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_samples) 244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret = 0; 246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u32 entries_printed = 0; 247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *rb_node; 248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct callchain_node *chain; 249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_node = rb_first(self); 251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (rb_node) { 252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng double percent; 253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng chain = rb_entry(rb_node, struct callchain_node, rb_node); 255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng percent = chain->hit * 100.0 / total_samples; 256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = percent_color_fprintf(fp, " %6.2f%%\n", percent); 258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += __callchain__fprintf_flat(fp, chain, total_samples); 259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "\n"); 260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (++entries_printed == callchain_param.print_limit) 261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_node = rb_next(rb_node); 264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t hist_entry_callchain__fprintf(struct hist_entry *he, 270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_samples, int left_margin, 271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng FILE *fp) 272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng switch (callchain_param.mode) { 274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case CHAIN_GRAPH_REL: 275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period, 276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin); 277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case CHAIN_GRAPH_ABS: 279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, 280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin); 281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case CHAIN_FLAT: 283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); 284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case CHAIN_NONE: 286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng default: 288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("Bad callchain mode\n"); 289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic size_t hist_entry__callchain_fprintf(struct hist_entry *he, 295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hists *hists, 296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng FILE *fp) 297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int left_margin = 0; 299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_period = hists->stats.total_period; 300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sort__first_dimension == SORT_COMM) { 302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sort_entry *se = list_first_entry(&hist_entry__sort_list, 303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng typeof(*se), list); 304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin = hists__col_len(hists, se->se_width_idx); 305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng left_margin -= thread__comm_len(he->thread); 306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); 309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic inline void advance_hpp(struct perf_hpp *hpp, int inc) 312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng hpp->buf += inc; 314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng hpp->size -= inc; 315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hist_entry__period_snprintf(struct perf_hpp *hpp, 318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hist_entry *he) 319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *sep = symbol_conf.field_sep; 321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_hpp_fmt *fmt; 322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *start = hpp->buf; 323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret; 324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool first = true; 325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (symbol_conf.exclude_other && !he->parent) 327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_hpp__for_each_format(fmt) { 330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * If there's no field_sep, we still need 332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * to display initial ' '. 333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!sep || !first) { 335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); 336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng advance_hpp(hpp, ret); 337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng first = false; 339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_hpp__use_color() && fmt->color) 341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = fmt->color(fmt, hpp, he); 342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = fmt->entry(fmt, hpp, he); 344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng advance_hpp(hpp, ret); 346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return hpp->buf - start; 349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int hist_entry__fprintf(struct hist_entry *he, size_t size, 352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hists *hists, 353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *bf, size_t bfsz, FILE *fp) 354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret; 356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_hpp hpp = { 357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .buf = bf, 358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .size = size, 359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (size == 0 || size > bfsz) 362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size = hpp.size = bfsz; 363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = hist_entry__period_snprintf(&hpp, he); 365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); 366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = fprintf(fp, "%s\n", bf); 368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (symbol_conf.use_callchain) 370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += hist_entry__callchain_fprintf(he, hists, fp); 371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int max_cols, float min_pcnt, FILE *fp) 377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_hpp_fmt *fmt; 379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sort_entry *se; 380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *nd; 381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret = 0; 382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned int width; 383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *sep = symbol_conf.field_sep; 384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *col_width = symbol_conf.col_width_list_str; 385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int nr_rows = 0; 386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char bf[96]; 387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_hpp dummy_hpp = { 388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .buf = bf, 389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .size = sizeof(bf), 390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .ptr = hists_to_evsel(hists), 391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool first = true; 393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t linesz; 394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *line = NULL; 395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng init_rem_hits(); 397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!show_header) 399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto print_entries; 400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "# "); 402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_hpp__for_each_format(fmt) { 404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!first) 405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "%s", sep ?: " "); 406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng first = false; 408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fmt->header(fmt, &dummy_hpp); 410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "%s", bf); 411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(se, &hist_entry__sort_list, list) { 414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (se->elide) 415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sep) { 417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "%c%s", *sep, se->se_header); 418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng width = strlen(se->se_header); 421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (symbol_conf.col_width_list_str) { 422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (col_width) { 423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng hists__set_col_len(hists, se->se_width_idx, 424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoi(col_width)); 425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng col_width = strchr(col_width, ','); 426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (col_width) 427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ++col_width; 428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!hists__new_col_len(hists, se->se_width_idx, width)) 431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng width = hists__col_len(hists, se->se_width_idx); 432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, " %*s", width, se->se_header); 433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "\n"); 436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (max_rows && ++nr_rows >= max_rows) 437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sep) 440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto print_entries; 441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng first = true; 443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "# "); 445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_hpp__for_each_format(fmt) { 447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned int i; 448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!first) 450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "%s", sep ?: " "); 451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng first = false; 453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng width = fmt->width(fmt, &dummy_hpp); 455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < width; i++) 456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "."); 457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(se, &hist_entry__sort_list, list) { 460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned int i; 461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (se->elide) 463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, " "); 466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng width = hists__col_len(hists, se->se_width_idx); 467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (width == 0) 468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng width = strlen(se->se_header); 469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < width; i++) 470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "."); 471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "\n"); 474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (max_rows && ++nr_rows >= max_rows) 475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "#\n"); 478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (max_rows && ++nr_rows >= max_rows) 479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengprint_entries: 482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng linesz = hists__sort_list_width(hists) + 3 + 1; 483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng linesz += perf_hpp__color_overhead(); 484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng line = malloc(linesz); 485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (line == NULL) { 486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = -1; 487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng float percent = h->stat.period * 100.0 / 493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng hists->stats.total_period; 494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (h->filtered) 496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (percent < min_pcnt) 499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp); 502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (max_rows && ++nr_rows >= max_rows) 504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (h->ms.map == NULL && verbose > 1) { 507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng __map_groups__fprintf_maps(&h->thread->mg, 508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng MAP__FUNCTION, verbose, fp); 509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fprintf(fp, "%.10s end\n", graph_dotted_line); 510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(line); 514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout: 515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(rem_sq_bracket); 516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t events_stats__fprintf(struct events_stats *stats, FILE *fp) 521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t ret = 0; 524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *name; 527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (stats->nr_events[i] == 0) 529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng name = perf_event__name(i); 532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcmp(name, "UNKNOWN")) 533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret += fprintf(fp, "%16s events: %10d\n", name, 536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng stats->nr_events[i]); 537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 541