1 /* SPDX-License-Identifier: GPL-2.0 */
5 #include <linux/rbtree.h>
6 #include <linux/types.h>
9 #include "events_stats.h"
11 #include "map_symbol.h"
59 HISTC_MEM_DADDR_SYMBOL
,
62 HISTC_MEM_DATA_PAGE_SIZE
,
68 HISTC_MEM_IADDR_SYMBOL
,
80 HISTC_LOCAL_P_STAGE_CYC
,
81 HISTC_GLOBAL_P_STAGE_CYC
,
90 HISTC_CALLCHAIN_BRANCH_PREDICTED
,
91 HISTC_CALLCHAIN_BRANCH_ABORT
,
92 HISTC_CALLCHAIN_BRANCH_CYCLES
,
93 HISTC_NR_COLS
, /* Last entry */
100 struct rb_root_cached entries_in_array
[2];
101 struct rb_root_cached
*entries_in
;
102 struct rb_root_cached entries
;
103 struct rb_root_cached entries_collapsed
;
105 u64 nr_non_filtered_entries
;
106 u64 callchain_period
;
107 u64 callchain_non_filtered_period
;
108 struct thread
*thread_filter
;
109 const struct dso
*dso_filter
;
110 const char *uid_filter_str
;
111 const char *symbol_filter_str
;
113 struct hists_stats stats
;
115 u16 col_len
[HISTC_NR_COLS
];
118 struct perf_hpp_list
*hpp_list
;
119 struct list_head hpp_formats
;
123 #define hists__has(__h, __f) (__h)->hpp_list->__f
125 struct hist_entry_iter
;
127 struct hist_iter_ops
{
128 int (*prepare_entry
)(struct hist_entry_iter
*, struct addr_location
*);
129 int (*add_single_entry
)(struct hist_entry_iter
*, struct addr_location
*);
130 int (*next_entry
)(struct hist_entry_iter
*, struct addr_location
*);
131 int (*add_next_entry
)(struct hist_entry_iter
*, struct addr_location
*);
132 int (*finish_entry
)(struct hist_entry_iter
*, struct addr_location
*);
135 struct hist_entry_iter
{
140 struct perf_sample
*sample
;
141 struct hist_entry
*he
;
142 struct symbol
*parent
;
145 struct branch_info
*bi
;
146 struct hist_entry
**he_cache
;
148 const struct hist_iter_ops
*ops
;
149 /* user-defined callback function (optional) */
150 int (*add_entry_cb
)(struct hist_entry_iter
*iter
,
151 struct addr_location
*al
, bool single
, void *arg
);
152 bool hide_unresolved
;
155 extern const struct hist_iter_ops hist_iter_normal
;
156 extern const struct hist_iter_ops hist_iter_branch
;
157 extern const struct hist_iter_ops hist_iter_mem
;
158 extern const struct hist_iter_ops hist_iter_cumulative
;
170 u64 period_guest_sys
;
178 struct namespace_id
{
183 struct hist_entry_diff
{
186 /* PERF_HPP__DELTA */
187 double period_ratio_delta
;
189 /* PERF_HPP__RATIO */
192 /* HISTC_WEIGHTED_DIFF */
195 /* PERF_HPP_DIFF__CYCLES */
199 unsigned long svals
[NUM_SPARKS
];
202 struct hist_entry_ops
{
203 void *(*new)(size_t size
);
204 void (*free
)(void *ptr
);
208 * struct hist_entry - histogram entry
210 * @row_offset - offset from the first callchain expanded to appear on screen
211 * @nr_rows - rows expanded in callchain, recalculated on folding/unfolding
214 struct rb_node rb_node_in
;
215 struct rb_node rb_node
;
217 struct list_head node
;
218 struct list_head head
;
221 struct he_stat
*stat_acc
;
222 struct map_symbol ms
;
223 struct thread
*thread
;
225 struct namespace_id cgroup_id
;
238 struct simd_flags simd_flags
;
240 /* We are added by hists__add_dummy_entry. */
250 * Since perf diff only supports the stdio output, TUI
251 * fields are only accessed from perf report (or perf
252 * top). So make it a union to reduce memory usage.
254 struct hist_entry_diff diff
;
255 struct /* for TUI */ {
258 bool init_have_children
;
266 struct symbol
*parent
;
267 struct branch_info
*branch_info
;
270 struct mem_info
*mem_info
;
271 struct block_info
*block_info
;
272 struct kvm_info
*kvm_info
;
276 struct res_sample
*res_samples
;
278 struct perf_hpp_list
*hpp_list
;
279 struct hist_entry
*parent_he
;
280 struct hist_entry_ops
*ops
;
281 struct annotated_data_type
*mem_type
;
283 /* this is for hierarchical entry structure */
285 struct rb_root_cached hroot_in
;
286 struct rb_root_cached hroot_out
;
287 }; /* non-leaf entries */
288 struct rb_root sorted_chain
; /* leaf entry has callchains */
290 struct callchain_root callchain
[0]; /* must be last member */
293 static __pure
inline bool hist_entry__has_callchains(struct hist_entry
*he
)
295 return he
->callchain_size
!= 0;
298 static inline bool hist_entry__has_pairs(struct hist_entry
*he
)
300 return !list_empty(&he
->pairs
.node
);
303 static inline struct hist_entry
*hist_entry__next_pair(struct hist_entry
*he
)
305 if (hist_entry__has_pairs(he
))
306 return list_entry(he
->pairs
.node
.next
, struct hist_entry
, pairs
.node
);
310 static inline void hist_entry__add_pair(struct hist_entry
*pair
,
311 struct hist_entry
*he
)
313 list_add_tail(&pair
->pairs
.node
, &he
->pairs
.head
);
316 struct hist_entry
*hists__add_entry(struct hists
*hists
,
317 struct addr_location
*al
,
318 struct symbol
*parent
,
319 struct branch_info
*bi
,
322 struct perf_sample
*sample
,
325 struct hist_entry
*hists__add_entry_ops(struct hists
*hists
,
326 struct hist_entry_ops
*ops
,
327 struct addr_location
*al
,
328 struct symbol
*sym_parent
,
329 struct branch_info
*bi
,
332 struct perf_sample
*sample
,
335 struct hist_entry
*hists__add_entry_block(struct hists
*hists
,
336 struct addr_location
*al
,
337 struct block_info
*bi
);
339 int hist_entry_iter__add(struct hist_entry_iter
*iter
, struct addr_location
*al
,
340 int max_stack_depth
, void *arg
);
345 int64_t hist_entry__cmp(struct hist_entry
*left
, struct hist_entry
*right
);
346 int64_t hist_entry__collapse(struct hist_entry
*left
, struct hist_entry
*right
);
347 int hist_entry__transaction_len(void);
348 int hist_entry__sort_snprintf(struct hist_entry
*he
, char *bf
, size_t size
,
349 struct hists
*hists
);
350 int hist_entry__snprintf_alignment(struct hist_entry
*he
, struct perf_hpp
*hpp
,
351 struct perf_hpp_fmt
*fmt
, int printed
);
352 int hist_entry__sym_snprintf(struct hist_entry
*he
, char *bf
, size_t size
,
354 void hist_entry__delete(struct hist_entry
*he
);
356 typedef int (*hists__resort_cb_t
)(struct hist_entry
*he
, void *arg
);
358 void evsel__output_resort_cb(struct evsel
*evsel
, struct ui_progress
*prog
,
359 hists__resort_cb_t cb
, void *cb_arg
);
360 void evsel__output_resort(struct evsel
*evsel
, struct ui_progress
*prog
);
361 void hists__output_resort(struct hists
*hists
, struct ui_progress
*prog
);
362 void hists__output_resort_cb(struct hists
*hists
, struct ui_progress
*prog
,
363 hists__resort_cb_t cb
);
364 int hists__collapse_resort(struct hists
*hists
, struct ui_progress
*prog
);
366 void hists__decay_entries(struct hists
*hists
, bool zap_user
, bool zap_kernel
);
367 void hists__delete_entries(struct hists
*hists
);
368 void hists__output_recalc_col_len(struct hists
*hists
, int max_rows
);
370 struct hist_entry
*hists__get_entry(struct hists
*hists
, int idx
);
372 u64
hists__total_period(struct hists
*hists
);
373 void hists__reset_stats(struct hists
*hists
);
374 void hists__inc_stats(struct hists
*hists
, struct hist_entry
*h
);
375 void hists__inc_nr_events(struct hists
*hists
);
376 void hists__inc_nr_samples(struct hists
*hists
, bool filtered
);
377 void hists__inc_nr_lost_samples(struct hists
*hists
, u32 lost
);
378 void hists__inc_nr_dropped_samples(struct hists
*hists
, u32 lost
);
380 size_t hists__fprintf(struct hists
*hists
, bool show_header
, int max_rows
,
381 int max_cols
, float min_pcnt
, FILE *fp
,
382 bool ignore_callchains
);
383 size_t evlist__fprintf_nr_events(struct evlist
*evlist
, FILE *fp
);
385 void hists__filter_by_dso(struct hists
*hists
);
386 void hists__filter_by_thread(struct hists
*hists
);
387 void hists__filter_by_symbol(struct hists
*hists
);
388 void hists__filter_by_socket(struct hists
*hists
);
390 static inline bool hists__has_filter(struct hists
*hists
)
392 return hists
->thread_filter
|| hists
->dso_filter
||
393 hists
->symbol_filter_str
|| (hists
->socket_filter
> -1);
396 u16
hists__col_len(struct hists
*hists
, enum hist_column col
);
397 void hists__set_col_len(struct hists
*hists
, enum hist_column col
, u16 len
);
398 bool hists__new_col_len(struct hists
*hists
, enum hist_column col
, u16 len
);
399 void hists__reset_col_len(struct hists
*hists
);
400 void hists__calc_col_len(struct hists
*hists
, struct hist_entry
*he
);
402 void hists__match(struct hists
*leader
, struct hists
*other
);
403 int hists__link(struct hists
*leader
, struct hists
*other
);
404 int hists__unlink(struct hists
*hists
);
406 static inline float hist_entry__get_percent_limit(struct hist_entry
*he
)
408 u64 period
= he
->stat
.period
;
409 u64 total_period
= hists__total_period(he
->hists
);
411 if (unlikely(total_period
== 0))
414 if (symbol_conf
.cumulate_callchain
)
415 period
= he
->stat_acc
->period
;
417 return period
* 100.0 / total_period
;
425 static inline struct evsel
*hists_to_evsel(struct hists
*hists
)
427 struct hists_evsel
*hevsel
= container_of(hists
, struct hists_evsel
, hists
);
428 return &hevsel
->evsel
;
431 static inline struct hists
*evsel__hists(struct evsel
*evsel
)
433 struct hists_evsel
*hevsel
= (struct hists_evsel
*)evsel
;
434 return &hevsel
->hists
;
437 static __pure
inline bool hists__has_callchains(struct hists
*hists
)
439 return hists
->has_callchains
;
442 int hists__init(void);
443 int __hists__init(struct hists
*hists
, struct perf_hpp_list
*hpp_list
);
445 struct rb_root_cached
*hists__get_rotate_entries_in(struct hists
*hists
);
455 struct perf_hpp_fmt
{
457 int (*header
)(struct perf_hpp_fmt
*fmt
, struct perf_hpp
*hpp
,
458 struct hists
*hists
, int line
, int *span
);
459 int (*width
)(struct perf_hpp_fmt
*fmt
, struct perf_hpp
*hpp
,
460 struct hists
*hists
);
461 void (*init
)(struct perf_hpp_fmt
*fmt
, struct hist_entry
*he
);
462 int (*color
)(struct perf_hpp_fmt
*fmt
, struct perf_hpp
*hpp
,
463 struct hist_entry
*he
);
464 int (*entry
)(struct perf_hpp_fmt
*fmt
, struct perf_hpp
*hpp
,
465 struct hist_entry
*he
);
466 int64_t (*cmp
)(struct perf_hpp_fmt
*fmt
,
467 struct hist_entry
*a
, struct hist_entry
*b
);
468 int64_t (*collapse
)(struct perf_hpp_fmt
*fmt
,
469 struct hist_entry
*a
, struct hist_entry
*b
);
470 int64_t (*sort
)(struct perf_hpp_fmt
*fmt
,
471 struct hist_entry
*a
, struct hist_entry
*b
);
472 bool (*equal
)(struct perf_hpp_fmt
*a
, struct perf_hpp_fmt
*b
);
473 void (*free
)(struct perf_hpp_fmt
*fmt
);
475 struct list_head list
;
476 struct list_head sort_list
;
484 struct perf_hpp_list
{
485 struct list_head fields
;
486 struct list_head sorts
;
498 extern struct perf_hpp_list perf_hpp_list
;
500 struct perf_hpp_list_node
{
501 struct list_head list
;
502 struct perf_hpp_list hpp
;
507 void perf_hpp_list__column_register(struct perf_hpp_list
*list
,
508 struct perf_hpp_fmt
*format
);
509 void perf_hpp_list__register_sort_field(struct perf_hpp_list
*list
,
510 struct perf_hpp_fmt
*format
);
511 void perf_hpp_list__prepend_sort_field(struct perf_hpp_list
*list
,
512 struct perf_hpp_fmt
*format
);
514 static inline void perf_hpp__column_register(struct perf_hpp_fmt
*format
)
516 perf_hpp_list__column_register(&perf_hpp_list
, format
);
519 static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt
*format
)
521 perf_hpp_list__register_sort_field(&perf_hpp_list
, format
);
524 static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt
*format
)
526 perf_hpp_list__prepend_sort_field(&perf_hpp_list
, format
);
529 #define perf_hpp_list__for_each_format(_list, format) \
530 list_for_each_entry(format, &(_list)->fields, list)
532 #define perf_hpp_list__for_each_format_safe(_list, format, tmp) \
533 list_for_each_entry_safe(format, tmp, &(_list)->fields, list)
535 #define perf_hpp_list__for_each_sort_list(_list, format) \
536 list_for_each_entry(format, &(_list)->sorts, sort_list)
538 #define perf_hpp_list__for_each_sort_list_safe(_list, format, tmp) \
539 list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list)
541 #define hists__for_each_format(hists, format) \
542 perf_hpp_list__for_each_format((hists)->hpp_list, format)
544 #define hists__for_each_sort_list(hists, format) \
545 perf_hpp_list__for_each_sort_list((hists)->hpp_list, format)
547 extern struct perf_hpp_fmt perf_hpp__format
[];
550 /* Matches perf_hpp__format array. */
552 PERF_HPP__OVERHEAD_SYS
,
553 PERF_HPP__OVERHEAD_US
,
554 PERF_HPP__OVERHEAD_GUEST_SYS
,
555 PERF_HPP__OVERHEAD_GUEST_US
,
556 PERF_HPP__OVERHEAD_ACC
,
566 void perf_hpp__init(void);
567 void perf_hpp__cancel_cumulate(void);
568 void perf_hpp__setup_output_field(struct perf_hpp_list
*list
);
569 void perf_hpp__reset_output_field(struct perf_hpp_list
*list
);
570 void perf_hpp__append_sort_keys(struct perf_hpp_list
*list
);
571 int perf_hpp__setup_hists_formats(struct perf_hpp_list
*list
,
572 struct evlist
*evlist
);
575 bool perf_hpp__is_sort_entry(struct perf_hpp_fmt
*format
);
576 bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt
*format
);
577 bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt
*fmt
, struct hists
*hists
);
578 bool perf_hpp__is_trace_entry(struct perf_hpp_fmt
*fmt
);
579 bool perf_hpp__is_srcline_entry(struct perf_hpp_fmt
*fmt
);
580 bool perf_hpp__is_srcfile_entry(struct perf_hpp_fmt
*fmt
);
581 bool perf_hpp__is_thread_entry(struct perf_hpp_fmt
*fmt
);
582 bool perf_hpp__is_comm_entry(struct perf_hpp_fmt
*fmt
);
583 bool perf_hpp__is_dso_entry(struct perf_hpp_fmt
*fmt
);
584 bool perf_hpp__is_sym_entry(struct perf_hpp_fmt
*fmt
);
586 struct perf_hpp_fmt
*perf_hpp_fmt__dup(struct perf_hpp_fmt
*fmt
);
588 int hist_entry__filter(struct hist_entry
*he
, int type
, const void *arg
);
590 static inline bool perf_hpp__should_skip(struct perf_hpp_fmt
*format
,
596 if (perf_hpp__is_dynamic_entry(format
) &&
597 !perf_hpp__defined_dynamic_entry(format
, hists
))
603 void perf_hpp__reset_width(struct perf_hpp_fmt
*fmt
, struct hists
*hists
);
604 void perf_hpp__reset_sort_width(struct perf_hpp_fmt
*fmt
, struct hists
*hists
);
605 void perf_hpp__set_user_width(const char *width_list_str
);
606 void hists__reset_column_width(struct hists
*hists
);
608 enum perf_hpp_fmt_type
{
609 PERF_HPP_FMT_TYPE__RAW
,
610 PERF_HPP_FMT_TYPE__PERCENT
,
611 PERF_HPP_FMT_TYPE__AVERAGE
,
614 typedef u64 (*hpp_field_fn
)(struct hist_entry
*he
);
615 typedef int (*hpp_callback_fn
)(struct perf_hpp
*hpp
, bool front
);
616 typedef int (*hpp_snprint_fn
)(struct perf_hpp
*hpp
, const char *fmt
, ...);
618 int hpp__fmt(struct perf_hpp_fmt
*fmt
, struct perf_hpp
*hpp
,
619 struct hist_entry
*he
, hpp_field_fn get_field
,
620 const char *fmtstr
, hpp_snprint_fn print_fn
,
621 enum perf_hpp_fmt_type fmtype
);
622 int hpp__fmt_acc(struct perf_hpp_fmt
*fmt
, struct perf_hpp
*hpp
,
623 struct hist_entry
*he
, hpp_field_fn get_field
,
624 const char *fmtstr
, hpp_snprint_fn print_fn
,
625 enum perf_hpp_fmt_type fmtype
);
627 static inline void advance_hpp(struct perf_hpp
*hpp
, int inc
)
633 static inline size_t perf_hpp__use_color(void)
635 return !symbol_conf
.field_sep
;
638 static inline size_t perf_hpp__color_overhead(void)
640 return perf_hpp__use_color() ?
641 (COLOR_MAXLEN
+ sizeof(PERF_COLOR_RESET
)) * PERF_HPP__MAX_INDEX
647 struct hist_browser_timer
{
648 void (*timer
)(void *arg
);
660 struct hists block_hists
;
661 struct perf_hpp_list block_list
;
662 struct perf_hpp_fmt block_fmt
;
665 struct hist_entry he
;
668 #ifdef HAVE_SLANG_SUPPORT
669 #include "../ui/keysyms.h"
670 void attr_to_script(char *buf
, struct perf_event_attr
*attr
);
672 int map_symbol__tui_annotate(struct map_symbol
*ms
, struct evsel
*evsel
,
673 struct hist_browser_timer
*hbt
);
675 int hist_entry__tui_annotate(struct hist_entry
*he
, struct evsel
*evsel
,
676 struct hist_browser_timer
*hbt
);
678 int evlist__tui_browse_hists(struct evlist
*evlist
, const char *help
, struct hist_browser_timer
*hbt
,
679 float min_pcnt
, struct perf_env
*env
, bool warn_lost_event
);
681 int script_browse(const char *script_opt
, struct evsel
*evsel
);
683 void run_script(char *cmd
);
684 int res_sample_browse(struct res_sample
*res_samples
, int num_res
,
685 struct evsel
*evsel
, enum rstype rstype
);
686 void res_sample_init(void);
688 int block_hists_tui_browse(struct block_hist
*bh
, struct evsel
*evsel
,
689 float min_percent
, struct perf_env
*env
);
692 int evlist__tui_browse_hists(struct evlist
*evlist __maybe_unused
,
693 const char *help __maybe_unused
,
694 struct hist_browser_timer
*hbt __maybe_unused
,
695 float min_pcnt __maybe_unused
,
696 struct perf_env
*env __maybe_unused
,
697 bool warn_lost_event __maybe_unused
)
701 static inline int map_symbol__tui_annotate(struct map_symbol
*ms __maybe_unused
,
702 struct evsel
*evsel __maybe_unused
,
703 struct hist_browser_timer
*hbt __maybe_unused
)
708 static inline int hist_entry__tui_annotate(struct hist_entry
*he __maybe_unused
,
709 struct evsel
*evsel __maybe_unused
,
710 struct hist_browser_timer
*hbt __maybe_unused
)
715 static inline int script_browse(const char *script_opt __maybe_unused
,
716 struct evsel
*evsel __maybe_unused
)
721 static inline int res_sample_browse(struct res_sample
*res_samples __maybe_unused
,
722 int num_res __maybe_unused
,
723 struct evsel
*evsel __maybe_unused
,
724 enum rstype rstype __maybe_unused
)
729 static inline void res_sample_init(void) {}
731 static inline int block_hists_tui_browse(struct block_hist
*bh __maybe_unused
,
732 struct evsel
*evsel __maybe_unused
,
733 float min_percent __maybe_unused
,
734 struct perf_env
*env __maybe_unused
)
740 #define K_RIGHT -2000
741 #define K_SWITCH_INPUT_DATA -3000
742 #define K_RELOAD -4000
745 unsigned int hists__sort_list_width(struct hists
*hists
);
746 unsigned int hists__overhead_width(struct hists
*hists
);
748 void hist__account_cycles(struct branch_stack
*bs
, struct addr_location
*al
,
749 struct perf_sample
*sample
, bool nonany_branch_mode
,
750 u64
*total_cycles
, struct evsel
*evsel
);
753 int parse_filter_percentage(const struct option
*opt
, const char *arg
, int unset
);
754 int perf_hist_config(const char *var
, const char *value
);
756 void perf_hpp_list__init(struct perf_hpp_list
*list
);
758 enum hierarchy_move_dir
{
764 struct rb_node
*rb_hierarchy_last(struct rb_node
*node
);
765 struct rb_node
*__rb_hierarchy_next(struct rb_node
*node
,
766 enum hierarchy_move_dir hmd
);
767 struct rb_node
*rb_hierarchy_prev(struct rb_node
*node
);
769 static inline struct rb_node
*rb_hierarchy_next(struct rb_node
*node
)
771 return __rb_hierarchy_next(node
, HMD_NORMAL
);
774 #define HIERARCHY_INDENT 3
776 bool hist_entry__has_hierarchy_children(struct hist_entry
*he
, float limit
);
777 int hpp_color_scnprintf(struct perf_hpp
*hpp
, const char *fmt
, ...);
778 int __hpp__slsmg_color_printf(struct perf_hpp
*hpp
, const char *fmt
, ...);
779 int __hist_entry__snprintf(struct hist_entry
*he
, struct perf_hpp
*hpp
,
780 struct perf_hpp_list
*hpp_list
);
781 int hists__fprintf_headers(struct hists
*hists
, FILE *fp
);
782 int __hists__scnprintf_title(struct hists
*hists
, char *bf
, size_t size
, bool show_freq
);
784 static inline int hists__scnprintf_title(struct hists
*hists
, char *bf
, size_t size
)
786 return __hists__scnprintf_title(hists
, bf
, size
, true);
789 #endif /* __PERF_HIST_H */