1 #ifndef __PERF_HIST_H 2 #define __PERF_HIST_H 3 4 #include <linux/types.h> 5 #include <pthread.h> 6 #include "callchain.h" 7 #include "evsel.h" 8 #include "header.h" 9 #include "color.h" 10 #include "ui/progress.h" 11 12 struct hist_entry; 13 struct hist_entry_ops; 14 struct addr_location; 15 struct symbol; 16 17 enum hist_filter { 18 HIST_FILTER__DSO, 19 HIST_FILTER__THREAD, 20 HIST_FILTER__PARENT, 21 HIST_FILTER__SYMBOL, 22 HIST_FILTER__GUEST, 23 HIST_FILTER__HOST, 24 HIST_FILTER__SOCKET, 25 HIST_FILTER__C2C, 26 }; 27 28 enum hist_column { 29 HISTC_SYMBOL, 30 HISTC_DSO, 31 HISTC_THREAD, 32 HISTC_COMM, 33 HISTC_CGROUP_ID, 34 HISTC_PARENT, 35 HISTC_CPU, 36 HISTC_SOCKET, 37 HISTC_SRCLINE, 38 HISTC_SRCFILE, 39 HISTC_MISPREDICT, 40 HISTC_IN_TX, 41 HISTC_ABORT, 42 HISTC_SYMBOL_FROM, 43 HISTC_SYMBOL_TO, 44 HISTC_DSO_FROM, 45 HISTC_DSO_TO, 46 HISTC_LOCAL_WEIGHT, 47 HISTC_GLOBAL_WEIGHT, 48 HISTC_MEM_DADDR_SYMBOL, 49 HISTC_MEM_DADDR_DSO, 50 HISTC_MEM_LOCKED, 51 HISTC_MEM_TLB, 52 HISTC_MEM_LVL, 53 HISTC_MEM_SNOOP, 54 HISTC_MEM_DCACHELINE, 55 HISTC_MEM_IADDR_SYMBOL, 56 HISTC_TRANSACTION, 57 HISTC_CYCLES, 58 HISTC_SRCLINE_FROM, 59 HISTC_SRCLINE_TO, 60 HISTC_TRACE, 61 HISTC_SYM_SIZE, 62 HISTC_NR_COLS, /* Last entry */ 63 }; 64 65 struct thread; 66 struct dso; 67 68 struct hists { 69 struct rb_root entries_in_array[2]; 70 struct rb_root *entries_in; 71 struct rb_root entries; 72 struct rb_root entries_collapsed; 73 u64 nr_entries; 74 u64 nr_non_filtered_entries; 75 u64 callchain_period; 76 u64 callchain_non_filtered_period; 77 struct thread *thread_filter; 78 const struct dso *dso_filter; 79 const char *uid_filter_str; 80 const char *symbol_filter_str; 81 pthread_mutex_t lock; 82 struct events_stats stats; 83 u64 event_stream; 84 u16 col_len[HISTC_NR_COLS]; 85 int socket_filter; 86 struct perf_hpp_list *hpp_list; 87 struct list_head hpp_formats; 88 int nr_hpp_node; 89 }; 90 91 #define hists__has(__h, __f) (__h)->hpp_list->__f 92 93 struct hist_entry_iter; 94 95 struct hist_iter_ops { 96 int (*prepare_entry)(struct hist_entry_iter *, struct addr_location *); 97 int (*add_single_entry)(struct hist_entry_iter *, struct addr_location *); 98 int (*next_entry)(struct hist_entry_iter *, struct addr_location *); 99 int (*add_next_entry)(struct hist_entry_iter *, struct addr_location *); 100 int (*finish_entry)(struct hist_entry_iter *, struct addr_location *); 101 }; 102 103 struct hist_entry_iter { 104 int total; 105 int curr; 106 107 bool hide_unresolved; 108 int max_stack; 109 110 struct perf_evsel *evsel; 111 struct perf_sample *sample; 112 struct hist_entry *he; 113 struct symbol *parent; 114 void *priv; 115 116 const struct hist_iter_ops *ops; 117 /* user-defined callback function (optional) */ 118 int (*add_entry_cb)(struct hist_entry_iter *iter, 119 struct addr_location *al, bool single, void *arg); 120 }; 121 122 extern const struct hist_iter_ops hist_iter_normal; 123 extern const struct hist_iter_ops hist_iter_branch; 124 extern const struct hist_iter_ops hist_iter_mem; 125 extern const struct hist_iter_ops hist_iter_cumulative; 126 127 struct hist_entry *hists__add_entry(struct hists *hists, 128 struct addr_location *al, 129 struct symbol *parent, 130 struct branch_info *bi, 131 struct mem_info *mi, 132 struct perf_sample *sample, 133 bool sample_self); 134 135 struct hist_entry *hists__add_entry_ops(struct hists *hists, 136 struct hist_entry_ops *ops, 137 struct addr_location *al, 138 struct symbol *sym_parent, 139 struct branch_info *bi, 140 struct mem_info *mi, 141 struct perf_sample *sample, 142 bool sample_self); 143 144 int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 145 int max_stack_depth, void *arg); 146 147 struct perf_hpp; 148 struct perf_hpp_fmt; 149 150 int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); 151 int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); 152 int hist_entry__transaction_len(void); 153 int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, 154 struct hists *hists); 155 int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, 156 struct perf_hpp_fmt *fmt, int printed); 157 void hist_entry__delete(struct hist_entry *he); 158 159 typedef int (*hists__resort_cb_t)(struct hist_entry *he); 160 161 void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); 162 void hists__output_resort(struct hists *hists, struct ui_progress *prog); 163 void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog, 164 hists__resort_cb_t cb); 165 int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 166 167 void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 168 void hists__delete_entries(struct hists *hists); 169 void hists__output_recalc_col_len(struct hists *hists, int max_rows); 170 171 u64 hists__total_period(struct hists *hists); 172 void hists__reset_stats(struct hists *hists); 173 void hists__inc_stats(struct hists *hists, struct hist_entry *h); 174 void hists__inc_nr_events(struct hists *hists, u32 type); 175 void hists__inc_nr_samples(struct hists *hists, bool filtered); 176 void events_stats__inc(struct events_stats *stats, u32 type); 177 size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); 178 179 size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 180 int max_cols, float min_pcnt, FILE *fp, 181 bool use_callchain); 182 size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); 183 184 void hists__filter_by_dso(struct hists *hists); 185 void hists__filter_by_thread(struct hists *hists); 186 void hists__filter_by_symbol(struct hists *hists); 187 void hists__filter_by_socket(struct hists *hists); 188 189 static inline bool hists__has_filter(struct hists *hists) 190 { 191 return hists->thread_filter || hists->dso_filter || 192 hists->symbol_filter_str || (hists->socket_filter > -1); 193 } 194 195 u16 hists__col_len(struct hists *hists, enum hist_column col); 196 void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len); 197 bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len); 198 void hists__reset_col_len(struct hists *hists); 199 void hists__calc_col_len(struct hists *hists, struct hist_entry *he); 200 201 void hists__match(struct hists *leader, struct hists *other); 202 int hists__link(struct hists *leader, struct hists *other); 203 204 struct hists_evsel { 205 struct perf_evsel evsel; 206 struct hists hists; 207 }; 208 209 static inline struct perf_evsel *hists_to_evsel(struct hists *hists) 210 { 211 struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists); 212 return &hevsel->evsel; 213 } 214 215 static inline struct hists *evsel__hists(struct perf_evsel *evsel) 216 { 217 struct hists_evsel *hevsel = (struct hists_evsel *)evsel; 218 return &hevsel->hists; 219 } 220 221 int hists__init(void); 222 int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); 223 224 struct rb_root *hists__get_rotate_entries_in(struct hists *hists); 225 226 struct perf_hpp { 227 char *buf; 228 size_t size; 229 const char *sep; 230 void *ptr; 231 }; 232 233 struct perf_hpp_fmt { 234 const char *name; 235 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 236 struct hists *hists, int line, int *span); 237 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 238 struct hists *hists); 239 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 240 struct hist_entry *he); 241 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 242 struct hist_entry *he); 243 int64_t (*cmp)(struct perf_hpp_fmt *fmt, 244 struct hist_entry *a, struct hist_entry *b); 245 int64_t (*collapse)(struct perf_hpp_fmt *fmt, 246 struct hist_entry *a, struct hist_entry *b); 247 int64_t (*sort)(struct perf_hpp_fmt *fmt, 248 struct hist_entry *a, struct hist_entry *b); 249 bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); 250 void (*free)(struct perf_hpp_fmt *fmt); 251 252 struct list_head list; 253 struct list_head sort_list; 254 bool elide; 255 int len; 256 int user_len; 257 int idx; 258 int level; 259 }; 260 261 struct perf_hpp_list { 262 struct list_head fields; 263 struct list_head sorts; 264 265 int nr_header_lines; 266 int need_collapse; 267 int parent; 268 int sym; 269 int dso; 270 int socket; 271 int thread; 272 int comm; 273 }; 274 275 extern struct perf_hpp_list perf_hpp_list; 276 277 struct perf_hpp_list_node { 278 struct list_head list; 279 struct perf_hpp_list hpp; 280 int level; 281 bool skip; 282 }; 283 284 void perf_hpp_list__column_register(struct perf_hpp_list *list, 285 struct perf_hpp_fmt *format); 286 void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, 287 struct perf_hpp_fmt *format); 288 void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list, 289 struct perf_hpp_fmt *format); 290 291 static inline void perf_hpp__column_register(struct perf_hpp_fmt *format) 292 { 293 perf_hpp_list__column_register(&perf_hpp_list, format); 294 } 295 296 static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) 297 { 298 perf_hpp_list__register_sort_field(&perf_hpp_list, format); 299 } 300 301 static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format) 302 { 303 perf_hpp_list__prepend_sort_field(&perf_hpp_list, format); 304 } 305 306 #define perf_hpp_list__for_each_format(_list, format) \ 307 list_for_each_entry(format, &(_list)->fields, list) 308 309 #define perf_hpp_list__for_each_format_safe(_list, format, tmp) \ 310 list_for_each_entry_safe(format, tmp, &(_list)->fields, list) 311 312 #define perf_hpp_list__for_each_sort_list(_list, format) \ 313 list_for_each_entry(format, &(_list)->sorts, sort_list) 314 315 #define perf_hpp_list__for_each_sort_list_safe(_list, format, tmp) \ 316 list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list) 317 318 #define hists__for_each_format(hists, format) \ 319 perf_hpp_list__for_each_format((hists)->hpp_list, fmt) 320 321 #define hists__for_each_sort_list(hists, format) \ 322 perf_hpp_list__for_each_sort_list((hists)->hpp_list, fmt) 323 324 extern struct perf_hpp_fmt perf_hpp__format[]; 325 326 enum { 327 /* Matches perf_hpp__format array. */ 328 PERF_HPP__OVERHEAD, 329 PERF_HPP__OVERHEAD_SYS, 330 PERF_HPP__OVERHEAD_US, 331 PERF_HPP__OVERHEAD_GUEST_SYS, 332 PERF_HPP__OVERHEAD_GUEST_US, 333 PERF_HPP__OVERHEAD_ACC, 334 PERF_HPP__SAMPLES, 335 PERF_HPP__PERIOD, 336 337 PERF_HPP__MAX_INDEX 338 }; 339 340 void perf_hpp__init(void); 341 void perf_hpp__column_unregister(struct perf_hpp_fmt *format); 342 void perf_hpp__cancel_cumulate(void); 343 void perf_hpp__setup_output_field(struct perf_hpp_list *list); 344 void perf_hpp__reset_output_field(struct perf_hpp_list *list); 345 void perf_hpp__append_sort_keys(struct perf_hpp_list *list); 346 int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, 347 struct perf_evlist *evlist); 348 349 350 bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); 351 bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format); 352 bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists); 353 bool perf_hpp__is_trace_entry(struct perf_hpp_fmt *fmt); 354 bool perf_hpp__is_srcline_entry(struct perf_hpp_fmt *fmt); 355 bool perf_hpp__is_srcfile_entry(struct perf_hpp_fmt *fmt); 356 bool perf_hpp__is_thread_entry(struct perf_hpp_fmt *fmt); 357 bool perf_hpp__is_comm_entry(struct perf_hpp_fmt *fmt); 358 bool perf_hpp__is_dso_entry(struct perf_hpp_fmt *fmt); 359 bool perf_hpp__is_sym_entry(struct perf_hpp_fmt *fmt); 360 361 struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt); 362 363 int hist_entry__filter(struct hist_entry *he, int type, const void *arg); 364 365 static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format, 366 struct hists *hists) 367 { 368 if (format->elide) 369 return true; 370 371 if (perf_hpp__is_dynamic_entry(format) && 372 !perf_hpp__defined_dynamic_entry(format, hists)) 373 return true; 374 375 return false; 376 } 377 378 void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 379 void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists); 380 void perf_hpp__set_user_width(const char *width_list_str); 381 void hists__reset_column_width(struct hists *hists); 382 383 typedef u64 (*hpp_field_fn)(struct hist_entry *he); 384 typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 385 typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...); 386 387 int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 388 struct hist_entry *he, hpp_field_fn get_field, 389 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent); 390 int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 391 struct hist_entry *he, hpp_field_fn get_field, 392 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent); 393 394 static inline void advance_hpp(struct perf_hpp *hpp, int inc) 395 { 396 hpp->buf += inc; 397 hpp->size -= inc; 398 } 399 400 static inline size_t perf_hpp__use_color(void) 401 { 402 return !symbol_conf.field_sep; 403 } 404 405 static inline size_t perf_hpp__color_overhead(void) 406 { 407 return perf_hpp__use_color() ? 408 (COLOR_MAXLEN + sizeof(PERF_COLOR_RESET)) * PERF_HPP__MAX_INDEX 409 : 0; 410 } 411 412 struct perf_evlist; 413 414 struct hist_browser_timer { 415 void (*timer)(void *arg); 416 void *arg; 417 int refresh; 418 }; 419 420 #ifdef HAVE_SLANG_SUPPORT 421 #include "../ui/keysyms.h" 422 int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 423 struct hist_browser_timer *hbt); 424 425 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 426 struct hist_browser_timer *hbt); 427 428 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 429 struct hist_browser_timer *hbt, 430 float min_pcnt, 431 struct perf_env *env); 432 int script_browse(const char *script_opt); 433 #else 434 static inline 435 int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 436 const char *help __maybe_unused, 437 struct hist_browser_timer *hbt __maybe_unused, 438 float min_pcnt __maybe_unused, 439 struct perf_env *env __maybe_unused) 440 { 441 return 0; 442 } 443 static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused, 444 struct perf_evsel *evsel __maybe_unused, 445 struct hist_browser_timer *hbt __maybe_unused) 446 { 447 return 0; 448 } 449 450 static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, 451 struct perf_evsel *evsel __maybe_unused, 452 struct hist_browser_timer *hbt __maybe_unused) 453 { 454 return 0; 455 } 456 457 static inline int script_browse(const char *script_opt __maybe_unused) 458 { 459 return 0; 460 } 461 462 #define K_LEFT -1000 463 #define K_RIGHT -2000 464 #define K_SWITCH_INPUT_DATA -3000 465 #endif 466 467 unsigned int hists__sort_list_width(struct hists *hists); 468 unsigned int hists__overhead_width(struct hists *hists); 469 470 void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, 471 struct perf_sample *sample, bool nonany_branch_mode); 472 473 struct option; 474 int parse_filter_percentage(const struct option *opt, const char *arg, int unset); 475 int perf_hist_config(const char *var, const char *value); 476 477 void perf_hpp_list__init(struct perf_hpp_list *list); 478 479 enum hierarchy_move_dir { 480 HMD_NORMAL, 481 HMD_FORCE_SIBLING, 482 HMD_FORCE_CHILD, 483 }; 484 485 struct rb_node *rb_hierarchy_last(struct rb_node *node); 486 struct rb_node *__rb_hierarchy_next(struct rb_node *node, 487 enum hierarchy_move_dir hmd); 488 struct rb_node *rb_hierarchy_prev(struct rb_node *node); 489 490 static inline struct rb_node *rb_hierarchy_next(struct rb_node *node) 491 { 492 return __rb_hierarchy_next(node, HMD_NORMAL); 493 } 494 495 #define HIERARCHY_INDENT 3 496 497 bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit); 498 int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...); 499 int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...); 500 int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, 501 struct perf_hpp_list *hpp_list); 502 int hists__fprintf_headers(struct hists *hists, FILE *fp); 503 504 #endif /* __PERF_HIST_H */ 505