Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __PERF_CALLCHAIN_H
0003 #define __PERF_CALLCHAIN_H
0004 
0005 #include <linux/list.h>
0006 #include <linux/rbtree.h>
0007 #include "map_symbol.h"
0008 #include "branch.h"
0009 
0010 struct addr_location;
0011 struct evsel;
0012 struct ip_callchain;
0013 struct map;
0014 struct perf_sample;
0015 struct thread;
0016 struct hists;
0017 
0018 #define HELP_PAD "\t\t\t\t"
0019 
0020 #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"
0021 
0022 # define RECORD_MODE_HELP  HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
0023 
0024 #define RECORD_SIZE_HELP                        \
0025     HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
0026     HELP_PAD "\t\tdefault: 8192 (bytes)\n"
0027 
0028 #define CALLCHAIN_RECORD_HELP  CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP
0029 
0030 #define CALLCHAIN_REPORT_HELP                       \
0031     HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|folded|none)\n" \
0032     HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \
0033     HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \
0034     HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \
0035     HELP_PAD "sort_key:\tcall graph sort key (function|address)\n"  \
0036     HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" \
0037     HELP_PAD "value:\t\tcall graph value (percent|period|count)\n"
0038 
0039 enum perf_call_graph_mode {
0040     CALLCHAIN_NONE,
0041     CALLCHAIN_FP,
0042     CALLCHAIN_DWARF,
0043     CALLCHAIN_LBR,
0044     CALLCHAIN_MAX
0045 };
0046 
0047 enum chain_mode {
0048     CHAIN_NONE,
0049     CHAIN_FLAT,
0050     CHAIN_GRAPH_ABS,
0051     CHAIN_GRAPH_REL,
0052     CHAIN_FOLDED,
0053 };
0054 
0055 enum chain_order {
0056     ORDER_CALLER,
0057     ORDER_CALLEE
0058 };
0059 
0060 struct callchain_node {
0061     struct callchain_node   *parent;
0062     struct list_head    val;
0063     struct list_head    parent_val;
0064     struct rb_node      rb_node_in; /* to insert nodes in an rbtree */
0065     struct rb_node      rb_node;    /* to sort nodes in an output tree */
0066     struct rb_root      rb_root_in; /* input tree of children */
0067     struct rb_root      rb_root;    /* sorted output tree of children */
0068     unsigned int        val_nr;
0069     unsigned int        count;
0070     unsigned int        children_count;
0071     u64         hit;
0072     u64         children_hit;
0073 };
0074 
0075 struct callchain_root {
0076     u64         max_depth;
0077     struct callchain_node   node;
0078 };
0079 
0080 struct callchain_param;
0081 
0082 typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
0083                  u64, struct callchain_param *);
0084 
0085 enum chain_key {
0086     CCKEY_FUNCTION,
0087     CCKEY_ADDRESS,
0088     CCKEY_SRCLINE
0089 };
0090 
0091 enum chain_value {
0092     CCVAL_PERCENT,
0093     CCVAL_PERIOD,
0094     CCVAL_COUNT,
0095 };
0096 
0097 extern bool dwarf_callchain_users;
0098 
0099 struct callchain_param {
0100     bool            enabled;
0101     enum perf_call_graph_mode record_mode;
0102     u32         dump_size;
0103     enum chain_mode     mode;
0104     u16         max_stack;
0105     u32         print_limit;
0106     double          min_percent;
0107     sort_chain_func_t   sort;
0108     enum chain_order    order;
0109     bool            order_set;
0110     enum chain_key      key;
0111     bool            branch_callstack;
0112     enum chain_value    value;
0113 };
0114 
0115 extern struct callchain_param callchain_param;
0116 extern struct callchain_param callchain_param_default;
0117 
0118 struct callchain_list {
0119     u64         ip;
0120     struct map_symbol   ms;
0121     struct /* for TUI */ {
0122         bool        unfolded;
0123         bool        has_children;
0124     };
0125     u64         branch_count;
0126     u64         from_count;
0127     u64         predicted_count;
0128     u64         abort_count;
0129     u64         cycles_count;
0130     u64         iter_count;
0131     u64         iter_cycles;
0132     struct branch_type_stat brtype_stat;
0133     const char      *srcline;
0134     struct list_head    list;
0135 };
0136 
0137 /*
0138  * A callchain cursor is a single linked list that
0139  * let one feed a callchain progressively.
0140  * It keeps persistent allocated entries to minimize
0141  * allocations.
0142  */
0143 struct callchain_cursor_node {
0144     u64             ip;
0145     struct map_symbol       ms;
0146     const char          *srcline;
0147     /* Indicate valid cursor node for LBR stitch */
0148     bool                valid;
0149 
0150     bool                branch;
0151     struct branch_flags     branch_flags;
0152     u64             branch_from;
0153     int             nr_loop_iter;
0154     u64             iter_cycles;
0155     struct callchain_cursor_node    *next;
0156 };
0157 
0158 struct stitch_list {
0159     struct list_head        node;
0160     struct callchain_cursor_node    cursor;
0161 };
0162 
0163 struct callchain_cursor {
0164     u64             nr;
0165     struct callchain_cursor_node    *first;
0166     struct callchain_cursor_node    **last;
0167     u64             pos;
0168     struct callchain_cursor_node    *curr;
0169 };
0170 
0171 extern __thread struct callchain_cursor callchain_cursor;
0172 
0173 static inline void callchain_init(struct callchain_root *root)
0174 {
0175     INIT_LIST_HEAD(&root->node.val);
0176     INIT_LIST_HEAD(&root->node.parent_val);
0177 
0178     root->node.parent = NULL;
0179     root->node.hit = 0;
0180     root->node.children_hit = 0;
0181     root->node.rb_root_in = RB_ROOT;
0182     root->max_depth = 0;
0183 }
0184 
0185 static inline u64 callchain_cumul_hits(struct callchain_node *node)
0186 {
0187     return node->hit + node->children_hit;
0188 }
0189 
0190 static inline unsigned callchain_cumul_counts(struct callchain_node *node)
0191 {
0192     return node->count + node->children_count;
0193 }
0194 
0195 int callchain_register_param(struct callchain_param *param);
0196 int callchain_append(struct callchain_root *root,
0197              struct callchain_cursor *cursor,
0198              u64 period);
0199 
0200 int callchain_merge(struct callchain_cursor *cursor,
0201             struct callchain_root *dst, struct callchain_root *src);
0202 
0203 void callchain_cursor_reset(struct callchain_cursor *cursor);
0204 
0205 int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
0206                 struct map_symbol *ms,
0207                 bool branch, struct branch_flags *flags,
0208                 int nr_loop_iter, u64 iter_cycles, u64 branch_from,
0209                 const char *srcline);
0210 
0211 /* Close a cursor writing session. Initialize for the reader */
0212 static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
0213 {
0214     cursor->curr = cursor->first;
0215     cursor->pos = 0;
0216 }
0217 
0218 /* Cursor reading iteration helpers */
0219 static inline struct callchain_cursor_node *
0220 callchain_cursor_current(struct callchain_cursor *cursor)
0221 {
0222     if (cursor->pos == cursor->nr)
0223         return NULL;
0224 
0225     return cursor->curr;
0226 }
0227 
0228 static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
0229 {
0230     cursor->curr = cursor->curr->next;
0231     cursor->pos++;
0232 }
0233 
0234 int callchain_cursor__copy(struct callchain_cursor *dst,
0235                struct callchain_cursor *src);
0236 
0237 struct option;
0238 struct hist_entry;
0239 
0240 int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
0241 int record_callchain_opt(const struct option *opt, const char *arg, int unset);
0242 
0243 struct record_opts;
0244 
0245 int record_opts__parse_callchain(struct record_opts *record,
0246                  struct callchain_param *callchain,
0247                  const char *arg, bool unset);
0248 
0249 int sample__resolve_callchain(struct perf_sample *sample,
0250                   struct callchain_cursor *cursor, struct symbol **parent,
0251                   struct evsel *evsel, struct addr_location *al,
0252                   int max_stack);
0253 int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
0254 int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
0255             bool hide_unresolved);
0256 
0257 extern const char record_callchain_help[];
0258 int parse_callchain_record(const char *arg, struct callchain_param *param);
0259 int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
0260 int parse_callchain_report_opt(const char *arg);
0261 int parse_callchain_top_opt(const char *arg);
0262 int perf_callchain_config(const char *var, const char *value);
0263 
0264 static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
0265                          struct callchain_cursor *src)
0266 {
0267     *dest = *src;
0268 
0269     dest->first = src->curr;
0270     dest->nr -= src->pos;
0271 }
0272 
0273 #ifdef HAVE_SKIP_CALLCHAIN_IDX
0274 int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
0275 #else
0276 static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
0277             struct ip_callchain *chain __maybe_unused)
0278 {
0279     return -1;
0280 }
0281 #endif
0282 
0283 void arch__add_leaf_frame_record_opts(struct record_opts *opts);
0284 
0285 char *callchain_list__sym_name(struct callchain_list *cl,
0286                    char *bf, size_t bfsize, bool show_dso);
0287 char *callchain_node__scnprintf_value(struct callchain_node *node,
0288                       char *bf, size_t bfsize, u64 total);
0289 int callchain_node__fprintf_value(struct callchain_node *node,
0290                   FILE *fp, u64 total);
0291 
0292 int callchain_list_counts__printf_value(struct callchain_list *clist,
0293                     FILE *fp, char *bf, int bfsize);
0294 
0295 void free_callchain(struct callchain_root *root);
0296 void decay_callchain(struct callchain_root *root);
0297 int callchain_node__make_parent_list(struct callchain_node *node);
0298 
0299 int callchain_branch_counts(struct callchain_root *root,
0300                 u64 *branch_count, u64 *predicted_count,
0301                 u64 *abort_count, u64 *cycles_count);
0302 
0303 void callchain_param_setup(u64 sample_type, const char *arch);
0304 
0305 bool callchain_cnode_matched(struct callchain_node *base_cnode,
0306                  struct callchain_node *pair_cnode);
0307 
0308 u64 callchain_total_hits(struct hists *hists);
0309 
0310 s64 callchain_avg_cycles(struct callchain_node *cnode);
0311 
0312 #endif  /* __PERF_CALLCHAIN_H */