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