Blame view

tools/perf/ui/browsers/hists.c 51 KB
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1
  #include <stdio.h>
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
2
3
4
  #include "../libslang.h"
  #include <stdlib.h>
  #include <string.h>
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
5
  #include <linux/rbtree.h>
aca7a94d6   Namhyung Kim   perf tools: Move ...
6
7
8
9
10
11
  #include "../../util/evsel.h"
  #include "../../util/evlist.h"
  #include "../../util/hist.h"
  #include "../../util/pstack.h"
  #include "../../util/sort.h"
  #include "../../util/util.h"
42337a222   Namhyung Kim   perf top: Handle ...
12
  #include "../../util/top.h"
68d807586   Namhyung Kim   perf report: Post...
13
  #include "../../arch/common.h"
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
14
15
16
17
  
  #include "../browser.h"
  #include "../helpline.h"
  #include "../util.h"
4610e4137   Arnaldo Carvalho de Melo   perf ui browser: ...
18
  #include "../ui.h"
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
19
  #include "map.h"
d755330c5   Jiri Olsa   perf tools: Fix s...
20
  #include "annotate.h"
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
21

d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
22
23
24
25
26
  struct hist_browser {
  	struct ui_browser   b;
  	struct hists	    *hists;
  	struct hist_entry   *he_selection;
  	struct map_symbol   *selection;
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
27
  	int		     print_seq;
a7cb8863d   Arnaldo Carvalho de Melo   perf hists browse...
28
  	bool		     show_dso;
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
29
  	bool		     show_headers;
064f19815   Namhyung Kim   perf report: Add ...
30
  	float		     min_pcnt;
112f761fc   Namhyung Kim   perf ui/tui: Rena...
31
  	u64		     nr_non_filtered_entries;
c3b789527   Namhyung Kim   perf hists/tui: C...
32
  	u64		     nr_callchain_rows;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
33
  };
f5951d56a   Namhyung Kim   perf hists browse...
34
  extern void hist_browser__init_hpp(void);
1e378ebd1   Taeung Song   perf top: Add a v...
35
36
37
  static int hists__browser_title(struct hists *hists,
  				struct hist_browser_timer *hbt,
  				char *bf, size_t size);
112f761fc   Namhyung Kim   perf ui/tui: Rena...
38
  static void hist_browser__update_nr_entries(struct hist_browser *hb);
81cce8de9   Arnaldo Carvalho de Melo   perf browsers: Ad...
39

c3b789527   Namhyung Kim   perf hists/tui: C...
40
  static struct rb_node *hists__filter_entries(struct rb_node *nd,
c3b789527   Namhyung Kim   perf hists/tui: C...
41
  					     float min_pcnt);
268397cb2   Namhyung Kim   perf top/tui: Upd...
42
43
44
45
  static bool hist_browser__has_filter(struct hist_browser *hb)
  {
  	return hists__has_filter(hb->hists) || hb->min_pcnt;
  }
c3b789527   Namhyung Kim   perf hists/tui: C...
46
47
48
49
50
51
52
53
54
55
56
  static u32 hist_browser__nr_entries(struct hist_browser *hb)
  {
  	u32 nr_entries;
  
  	if (hist_browser__has_filter(hb))
  		nr_entries = hb->nr_non_filtered_entries;
  	else
  		nr_entries = hb->hists->nr_entries;
  
  	return nr_entries + hb->nr_callchain_rows;
  }
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  static void hist_browser__update_rows(struct hist_browser *hb)
  {
  	struct ui_browser *browser = &hb->b;
  	u16 header_offset = hb->show_headers ? 1 : 0, index_row;
  
  	browser->rows = browser->height - header_offset;
  	/*
  	 * Verify if we were at the last line and that line isn't
  	 * visibe because we now show the header line(s).
  	 */
  	index_row = browser->index - browser->top_idx;
  	if (index_row >= browser->rows)
  		browser->index -= index_row - browser->rows + 1;
  }
357cfff1c   Arnaldo Carvalho de Melo   perf hists browse...
71
  static void hist_browser__refresh_dimensions(struct ui_browser *browser)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
72
  {
357cfff1c   Arnaldo Carvalho de Melo   perf hists browse...
73
  	struct hist_browser *hb = container_of(browser, struct hist_browser, b);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
74
  	/* 3 == +/- toggle symbol before actual hist_entry rendering */
357cfff1c   Arnaldo Carvalho de Melo   perf hists browse...
75
76
77
78
79
80
81
82
  	browser->width = 3 + (hists__sort_list_width(hb->hists) + sizeof("[k]"));
  	/*
   	 * FIXME: Just keeping existing behaviour, but this really should be
   	 *	  before updating browser->width, as it will invalidate the
   	 *	  calculation above. Fix this and the fallout in another
   	 *	  changeset.
   	 */
  	ui_browser__refresh_dimensions(browser);
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
83
  	hist_browser__update_rows(hb);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
84
  }
ca3ff33b5   Arnaldo Carvalho de Melo   perf hists browse...
85
86
  static void hist_browser__gotorc(struct hist_browser *browser, int row, int column)
  {
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
87
88
89
  	u16 header_offset = browser->show_headers ? 1 : 0;
  
  	ui_browser__gotorc(&browser->b, row + header_offset, column);
ca3ff33b5   Arnaldo Carvalho de Melo   perf hists browse...
90
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
91
  static void hist_browser__reset(struct hist_browser *browser)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
92
  {
c3b789527   Namhyung Kim   perf hists/tui: C...
93
94
95
96
97
  	/*
  	 * The hists__remove_entry_filter() already folds non-filtered
  	 * entries so we can assume it has 0 callchain rows.
  	 */
  	browser->nr_callchain_rows = 0;
268397cb2   Namhyung Kim   perf top/tui: Upd...
98
  	hist_browser__update_nr_entries(browser);
c3b789527   Namhyung Kim   perf hists/tui: C...
99
  	browser->b.nr_entries = hist_browser__nr_entries(browser);
357cfff1c   Arnaldo Carvalho de Melo   perf hists browse...
100
  	hist_browser__refresh_dimensions(&browser->b);
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
101
  	ui_browser__reset_index(&browser->b);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
102
103
104
105
106
107
  }
  
  static char tree__folded_sign(bool unfolded)
  {
  	return unfolded ? '-' : '+';
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
108
  static char map_symbol__folded(const struct map_symbol *ms)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
109
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
110
  	return ms->has_children ? tree__folded_sign(ms->unfolded) : ' ';
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
111
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
112
  static char hist_entry__folded(const struct hist_entry *he)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
113
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
114
  	return map_symbol__folded(&he->ms);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
115
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
116
  static char callchain_list__folded(const struct callchain_list *cl)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
117
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
118
  	return map_symbol__folded(&cl->ms);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
119
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
120
  static void map_symbol__set_folding(struct map_symbol *ms, bool unfold)
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
121
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
122
  	ms->unfolded = unfold ? ms->has_children : false;
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
123
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
124
  static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
125
126
127
  {
  	int n = 0;
  	struct rb_node *nd;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
128
  	for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) {
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  		struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
  		struct callchain_list *chain;
  		char folded_sign = ' '; /* No children */
  
  		list_for_each_entry(chain, &child->val, list) {
  			++n;
  			/* We need this because we may not have children */
  			folded_sign = callchain_list__folded(chain);
  			if (folded_sign == '+')
  				break;
  		}
  
  		if (folded_sign == '-') /* Have children and they're unfolded */
  			n += callchain_node__count_rows_rb_tree(child);
  	}
  
  	return n;
  }
  
  static int callchain_node__count_rows(struct callchain_node *node)
  {
  	struct callchain_list *chain;
  	bool unfolded = false;
  	int n = 0;
  
  	list_for_each_entry(chain, &node->val, list) {
  		++n;
  		unfolded = chain->ms.unfolded;
  	}
  
  	if (unfolded)
  		n += callchain_node__count_rows_rb_tree(node);
  
  	return n;
  }
  
  static int callchain__count_rows(struct rb_root *chain)
  {
  	struct rb_node *nd;
  	int n = 0;
  
  	for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
  		struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
  		n += callchain_node__count_rows(node);
  	}
  
  	return n;
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
177
  static bool map_symbol__toggle_fold(struct map_symbol *ms)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
178
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
179
  	if (!ms)
8493fe1da   Jiri Olsa   perf hists browse...
180
  		return false;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
181
  	if (!ms->has_children)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
182
  		return false;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
183
  	ms->unfolded = !ms->unfolded;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
184
185
  	return true;
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
186
  static void callchain_node__init_have_children_rb_tree(struct callchain_node *node)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
187
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
188
  	struct rb_node *nd = rb_first(&node->rb_root);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
189

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
190
  	for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) {
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
191
192
  		struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
  		struct callchain_list *chain;
293db47f4   Arnaldo Carvalho de Melo   perf hists browse...
193
  		bool first = true;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
194
195
196
197
198
  
  		list_for_each_entry(chain, &child->val, list) {
  			if (first) {
  				first = false;
  				chain->ms.has_children = chain->list.next != &child->val ||
293db47f4   Arnaldo Carvalho de Melo   perf hists browse...
199
  							 !RB_EMPTY_ROOT(&child->rb_root);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
200
201
  			} else
  				chain->ms.has_children = chain->list.next == &child->val &&
293db47f4   Arnaldo Carvalho de Melo   perf hists browse...
202
  							 !RB_EMPTY_ROOT(&child->rb_root);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
203
204
205
206
207
  		}
  
  		callchain_node__init_have_children_rb_tree(child);
  	}
  }
a7444af69   Namhyung Kim   perf tools: Colla...
208
209
  static void callchain_node__init_have_children(struct callchain_node *node,
  					       bool has_sibling)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
210
211
  {
  	struct callchain_list *chain;
a7444af69   Namhyung Kim   perf tools: Colla...
212
213
  	chain = list_entry(node->val.next, struct callchain_list, list);
  	chain->ms.has_children = has_sibling;
82162b5ae   Namhyung Kim   perf hists browse...
214
215
  	if (!list_empty(&node->val)) {
  		chain = list_entry(node->val.prev, struct callchain_list, list);
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
216
  		chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
82162b5ae   Namhyung Kim   perf hists browse...
217
  	}
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
218

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
219
  	callchain_node__init_have_children_rb_tree(node);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
220
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
221
  static void callchain__init_have_children(struct rb_root *root)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
222
  {
a7444af69   Namhyung Kim   perf tools: Colla...
223
224
  	struct rb_node *nd = rb_first(root);
  	bool has_sibling = nd && rb_next(nd);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
225

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
226
  	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
227
  		struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
a7444af69   Namhyung Kim   perf tools: Colla...
228
  		callchain_node__init_have_children(node, has_sibling);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
229
230
  	}
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
231
  static void hist_entry__init_have_children(struct hist_entry *he)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
232
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
233
234
235
236
  	if (!he->init_have_children) {
  		he->ms.has_children = !RB_EMPTY_ROOT(&he->sorted_chain);
  		callchain__init_have_children(&he->sorted_chain);
  		he->init_have_children = true;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
237
238
  	}
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
239
  static bool hist_browser__toggle_fold(struct hist_browser *browser)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
240
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
241
242
  	if (map_symbol__toggle_fold(browser->selection)) {
  		struct hist_entry *he = browser->he_selection;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
243
244
  
  		hist_entry__init_have_children(he);
c3b789527   Namhyung Kim   perf hists/tui: C...
245
246
  		browser->b.nr_entries -= he->nr_rows;
  		browser->nr_callchain_rows -= he->nr_rows;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
247
248
249
250
251
  
  		if (he->ms.unfolded)
  			he->nr_rows = callchain__count_rows(&he->sorted_chain);
  		else
  			he->nr_rows = 0;
c3b789527   Namhyung Kim   perf hists/tui: C...
252
253
254
  
  		browser->b.nr_entries += he->nr_rows;
  		browser->nr_callchain_rows += he->nr_rows;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
255
256
257
258
259
260
261
  
  		return true;
  	}
  
  	/* If it doesn't have children, no toggling performed */
  	return false;
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
262
  static int callchain_node__set_folding_rb_tree(struct callchain_node *node, bool unfold)
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
263
264
265
  {
  	int n = 0;
  	struct rb_node *nd;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
266
  	for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) {
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  		struct callchain_node *child = rb_entry(nd, struct callchain_node, rb_node);
  		struct callchain_list *chain;
  		bool has_children = false;
  
  		list_for_each_entry(chain, &child->val, list) {
  			++n;
  			map_symbol__set_folding(&chain->ms, unfold);
  			has_children = chain->ms.has_children;
  		}
  
  		if (has_children)
  			n += callchain_node__set_folding_rb_tree(child, unfold);
  	}
  
  	return n;
  }
  
  static int callchain_node__set_folding(struct callchain_node *node, bool unfold)
  {
  	struct callchain_list *chain;
  	bool has_children = false;
  	int n = 0;
  
  	list_for_each_entry(chain, &node->val, list) {
  		++n;
  		map_symbol__set_folding(&chain->ms, unfold);
  		has_children = chain->ms.has_children;
  	}
  
  	if (has_children)
  		n += callchain_node__set_folding_rb_tree(node, unfold);
  
  	return n;
  }
  
  static int callchain__set_folding(struct rb_root *chain, bool unfold)
  {
  	struct rb_node *nd;
  	int n = 0;
  
  	for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
  		struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
  		n += callchain_node__set_folding(node, unfold);
  	}
  
  	return n;
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
314
  static void hist_entry__set_folding(struct hist_entry *he, bool unfold)
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
315
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
316
317
  	hist_entry__init_have_children(he);
  	map_symbol__set_folding(&he->ms, unfold);
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
318

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
319
320
321
  	if (he->ms.has_children) {
  		int n = callchain__set_folding(&he->sorted_chain, unfold);
  		he->nr_rows = unfold ? n : 0;
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
322
  	} else
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
323
  		he->nr_rows = 0;
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
324
  }
c3b789527   Namhyung Kim   perf hists/tui: C...
325
326
  static void
  __hist_browser__set_folding(struct hist_browser *browser, bool unfold)
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
327
328
  {
  	struct rb_node *nd;
c3b789527   Namhyung Kim   perf hists/tui: C...
329
  	struct hists *hists = browser->hists;
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
330

c3b789527   Namhyung Kim   perf hists/tui: C...
331
  	for (nd = rb_first(&hists->entries);
14135663f   Namhyung Kim   perf tools: Apply...
332
  	     (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
c3b789527   Namhyung Kim   perf hists/tui: C...
333
  	     nd = rb_next(nd)) {
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
334
335
  		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
  		hist_entry__set_folding(he, unfold);
c3b789527   Namhyung Kim   perf hists/tui: C...
336
  		browser->nr_callchain_rows += he->nr_rows;
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
337
338
  	}
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
339
  static void hist_browser__set_folding(struct hist_browser *browser, bool unfold)
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
340
  {
c3b789527   Namhyung Kim   perf hists/tui: C...
341
342
343
344
  	browser->nr_callchain_rows = 0;
  	__hist_browser__set_folding(browser, unfold);
  
  	browser->b.nr_entries = hist_browser__nr_entries(browser);
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
345
  	/* Go to the start, we may be way after valid entries after a collapse */
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
346
  	ui_browser__reset_index(&browser->b);
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
347
  }
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  static void ui_browser__warn_lost_events(struct ui_browser *browser)
  {
  	ui_browser__warning(browser, 4,
  		"Events are being lost, check IO/CPU overload!
  
  "
  		"You may want to run 'perf' using a RT scheduler policy:
  
  "
  		" perf top -r 80
  
  "
  		"Or reduce the sampling frequency.");
  }
dd00d486d   Jiri Olsa   perf hists browse...
362
  static int hist_browser__run(struct hist_browser *browser,
9783adf77   Namhyung Kim   perf tools: Intro...
363
  			     struct hist_browser_timer *hbt)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
364
  {
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
365
  	int key;
81cce8de9   Arnaldo Carvalho de Melo   perf browsers: Ad...
366
  	char title[160];
9783adf77   Namhyung Kim   perf tools: Intro...
367
  	int delay_secs = hbt ? hbt->refresh : 0;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
368

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
369
  	browser->b.entries = &browser->hists->entries;
c3b789527   Namhyung Kim   perf hists/tui: C...
370
  	browser->b.nr_entries = hist_browser__nr_entries(browser);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
371

1e378ebd1   Taeung Song   perf top: Add a v...
372
  	hists__browser_title(browser->hists, hbt, title, sizeof(title));
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
373

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
374
  	if (ui_browser__show(&browser->b, title,
59e8fe32f   Arnaldo Carvalho de Melo   perf ui browser: ...
375
  			     "Press '?' for help on key bindings") < 0)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
376
  		return -1;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
377
  	while (1) {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
378
  		key = ui_browser__run(&browser->b, delay_secs);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
379

b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
380
  		switch (key) {
fa5df9435   Namhyung Kim   perf top: Add --p...
381
382
  		case K_TIMER: {
  			u64 nr_entries;
9783adf77   Namhyung Kim   perf tools: Intro...
383
  			hbt->timer(hbt->arg);
fa5df9435   Namhyung Kim   perf top: Add --p...
384

c3b789527   Namhyung Kim   perf hists/tui: C...
385
  			if (hist_browser__has_filter(browser))
112f761fc   Namhyung Kim   perf ui/tui: Rena...
386
  				hist_browser__update_nr_entries(browser);
fa5df9435   Namhyung Kim   perf top: Add --p...
387

c3b789527   Namhyung Kim   perf hists/tui: C...
388
  			nr_entries = hist_browser__nr_entries(browser);
fa5df9435   Namhyung Kim   perf top: Add --p...
389
  			ui_browser__update_nr_entries(&browser->b, nr_entries);
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
390

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
391
392
393
394
395
  			if (browser->hists->stats.nr_lost_warned !=
  			    browser->hists->stats.nr_events[PERF_RECORD_LOST]) {
  				browser->hists->stats.nr_lost_warned =
  					browser->hists->stats.nr_events[PERF_RECORD_LOST];
  				ui_browser__warn_lost_events(&browser->b);
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
396
  			}
1e378ebd1   Taeung Song   perf top: Add a v...
397
398
  			hists__browser_title(browser->hists,
  					     hbt, title, sizeof(title));
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
399
  			ui_browser__show_title(&browser->b, title);
81cce8de9   Arnaldo Carvalho de Melo   perf browsers: Ad...
400
  			continue;
fa5df9435   Namhyung Kim   perf top: Add --p...
401
  		}
4694153c2   Arnaldo Carvalho de Melo   perf ui hist brow...
402
  		case 'D': { /* Debug */
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
403
  			static int seq;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
404
  			struct hist_entry *h = rb_entry(browser->b.top,
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
405
406
  							struct hist_entry, rb_node);
  			ui_helpline__pop();
62c95ae33   Arnaldo Carvalho de Melo   perf ui browser: ...
407
  			ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
408
409
  					   seq++, browser->b.nr_entries,
  					   browser->hists->nr_entries,
62c95ae33   Arnaldo Carvalho de Melo   perf ui browser: ...
410
  					   browser->b.rows,
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
411
412
  					   browser->b.index,
  					   browser->b.top_idx,
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
413
414
  					   h->row_offset, h->nr_rows);
  		}
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
415
416
417
  			break;
  		case 'C':
  			/* Collapse the whole world. */
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
418
  			hist_browser__set_folding(browser, false);
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
419
420
421
  			break;
  		case 'E':
  			/* Expand the whole world. */
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
422
  			hist_browser__set_folding(browser, true);
3c916cc28   Arnaldo Carvalho de Melo   perf hists browse...
423
  			break;
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
424
425
426
427
  		case 'H':
  			browser->show_headers = !browser->show_headers;
  			hist_browser__update_rows(browser);
  			break;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
428
  		case K_ENTER:
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
429
  			if (hist_browser__toggle_fold(browser))
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
430
431
432
  				break;
  			/* fall thru */
  		default:
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
433
  			goto out;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
434
435
  		}
  	}
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
436
  out:
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
437
  	ui_browser__hide(&browser->b);
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
438
  	return key;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
439
  }
39ee533fc   Namhyung Kim   perf hists browse...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
  struct callchain_print_arg {
  	/* for hists browser */
  	off_t	row_offset;
  	bool	is_current_entry;
  
  	/* for file dump */
  	FILE	*fp;
  	int	printed;
  };
  
  typedef void (*print_callchain_entry_fn)(struct hist_browser *browser,
  					 struct callchain_list *chain,
  					 const char *str, int offset,
  					 unsigned short row,
  					 struct callchain_print_arg *arg);
f4536ddd2   Namhyung Kim   perf hists browse...
455
456
  static void hist_browser__show_callchain_entry(struct hist_browser *browser,
  					       struct callchain_list *chain,
39ee533fc   Namhyung Kim   perf hists browse...
457
458
459
  					       const char *str, int offset,
  					       unsigned short row,
  					       struct callchain_print_arg *arg)
f4536ddd2   Namhyung Kim   perf hists browse...
460
461
  {
  	int color, width;
39ee533fc   Namhyung Kim   perf hists browse...
462
  	char folded_sign = callchain_list__folded(chain);
f4536ddd2   Namhyung Kim   perf hists browse...
463
464
465
466
467
468
  
  	color = HE_COLORSET_NORMAL;
  	width = browser->b.width - (offset + 2);
  	if (ui_browser__is_current_entry(&browser->b, row)) {
  		browser->selection = &chain->ms;
  		color = HE_COLORSET_SELECTED;
39ee533fc   Namhyung Kim   perf hists browse...
469
  		arg->is_current_entry = true;
f4536ddd2   Namhyung Kim   perf hists browse...
470
471
472
473
474
475
476
477
  	}
  
  	ui_browser__set_color(&browser->b, color);
  	hist_browser__gotorc(browser, row, 0);
  	slsmg_write_nstring(" ", offset);
  	slsmg_printf("%c ", folded_sign);
  	slsmg_write_nstring(str, width);
  }
39ee533fc   Namhyung Kim   perf hists browse...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused,
  						  struct callchain_list *chain,
  						  const char *str, int offset,
  						  unsigned short row __maybe_unused,
  						  struct callchain_print_arg *arg)
  {
  	char folded_sign = callchain_list__folded(chain);
  
  	arg->printed += fprintf(arg->fp, "%*s%c %s
  ", offset, " ",
  				folded_sign, str);
  }
  
  typedef bool (*check_output_full_fn)(struct hist_browser *browser,
  				     unsigned short row);
  
  static bool hist_browser__check_output_full(struct hist_browser *browser,
  					    unsigned short row)
  {
  	return browser->b.rows == row;
  }
  
  static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_unused,
  					  unsigned short row __maybe_unused)
  {
  	return false;
  }
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
505
  #define LEVEL_OFFSET_STEP 3
c09a7e755   Namhyung Kim   perf hists browse...
506
507
  static int hist_browser__show_callchain(struct hist_browser *browser,
  					struct rb_root *root, int level,
39ee533fc   Namhyung Kim   perf hists browse...
508
509
510
511
  					unsigned short row, u64 total,
  					print_callchain_entry_fn print,
  					struct callchain_print_arg *arg,
  					check_output_full_fn is_output_full)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
512
513
  {
  	struct rb_node *node;
f4536ddd2   Namhyung Kim   perf hists browse...
514
  	int first_row = row, offset = level * LEVEL_OFFSET_STEP;
36e15dd40   Namhyung Kim   perf hists browse...
515
  	u64 new_total;
4087d11cd   Namhyung Kim   perf hists browse...
516
  	bool need_percent;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
517

c09a7e755   Namhyung Kim   perf hists browse...
518
  	node = rb_first(root);
4087d11cd   Namhyung Kim   perf hists browse...
519
  	need_percent = !!rb_next(node);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
520
521
522
  	while (node) {
  		struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
  		struct rb_node *next = rb_next(node);
f08c3154a   Frederic Weisbecker   perf callchain: R...
523
  		u64 cumul = callchain_cumul_hits(child);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
524
525
526
527
  		struct callchain_list *chain;
  		char folded_sign = ' ';
  		int first = true;
  		int extra_offset = 0;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
528
  		list_for_each_entry(chain, &child->val, list) {
a7cb8863d   Arnaldo Carvalho de Melo   perf hists browse...
529
  			char bf[1024], *alloc_str;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
530
  			const char *str;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
531
  			bool was_first = first;
163caed90   Arnaldo Carvalho de Melo   perf hists browse...
532
  			if (first)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
533
  				first = false;
4087d11cd   Namhyung Kim   perf hists browse...
534
  			else if (need_percent)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
535
  				extra_offset = LEVEL_OFFSET_STEP;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
536
537
  
  			folded_sign = callchain_list__folded(chain);
39ee533fc   Namhyung Kim   perf hists browse...
538
539
  			if (arg->row_offset != 0) {
  				arg->row_offset--;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
540
541
542
543
  				goto do_next;
  			}
  
  			alloc_str = NULL;
a7cb8863d   Arnaldo Carvalho de Melo   perf hists browse...
544
545
  			str = callchain_list__sym_name(chain, bf, sizeof(bf),
  						       browser->show_dso);
c09a7e755   Namhyung Kim   perf hists browse...
546

4087d11cd   Namhyung Kim   perf hists browse...
547
  			if (was_first && need_percent) {
c09a7e755   Namhyung Kim   perf hists browse...
548
  				double percent = cumul * 100.0 / total;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
549
550
551
552
553
554
  
  				if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
  					str = "Not enough memory!";
  				else
  					str = alloc_str;
  			}
39ee533fc   Namhyung Kim   perf hists browse...
555
  			print(browser, chain, str, offset + extra_offset, row, arg);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
556
  			free(alloc_str);
39ee533fc   Namhyung Kim   perf hists browse...
557
  			if (is_output_full(browser, ++row))
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
558
559
560
561
562
563
564
565
  				goto out;
  do_next:
  			if (folded_sign == '+')
  				break;
  		}
  
  		if (folded_sign == '-') {
  			const int new_level = level + (extra_offset ? 2 : 1);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
566

c09a7e755   Namhyung Kim   perf hists browse...
567
568
569
570
  			if (callchain_param.mode == CHAIN_GRAPH_REL)
  				new_total = child->children_hit;
  			else
  				new_total = total;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
571

c09a7e755   Namhyung Kim   perf hists browse...
572
  			row += hist_browser__show_callchain(browser, &child->rb_root,
39ee533fc   Namhyung Kim   perf hists browse...
573
574
  							    new_level, row, new_total,
  							    print, arg, is_output_full);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
575
  		}
39ee533fc   Namhyung Kim   perf hists browse...
576
  		if (is_output_full(browser, row))
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
577
  			break;
c09a7e755   Namhyung Kim   perf hists browse...
578
  		node = next;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
579
  	}
c09a7e755   Namhyung Kim   perf hists browse...
580
  out:
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
581
582
  	return row - first_row;
  }
897014603   Namhyung Kim   perf hists browse...
583
584
585
586
587
  struct hpp_arg {
  	struct ui_browser *b;
  	char folded_sign;
  	bool current_entry;
  };
2f6d9009a   Namhyung Kim   perf ui/tui: Reus...
588
589
590
  static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
  {
  	struct hpp_arg *arg = hpp->ptr;
d675107ce   Namhyung Kim   perf tools: Make ...
591
  	int ret, len;
2f6d9009a   Namhyung Kim   perf ui/tui: Reus...
592
593
  	va_list args;
  	double percent;
371d8c402   Namhyung Kim   perf hists browse...
594

2f6d9009a   Namhyung Kim   perf ui/tui: Reus...
595
  	va_start(args, fmt);
d675107ce   Namhyung Kim   perf tools: Make ...
596
  	len = va_arg(args, int);
2f6d9009a   Namhyung Kim   perf ui/tui: Reus...
597
598
  	percent = va_arg(args, double);
  	va_end(args);
371d8c402   Namhyung Kim   perf hists browse...
599

2f6d9009a   Namhyung Kim   perf ui/tui: Reus...
600
  	ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
371d8c402   Namhyung Kim   perf hists browse...
601

d675107ce   Namhyung Kim   perf tools: Make ...
602
  	ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
2f6d9009a   Namhyung Kim   perf ui/tui: Reus...
603
  	slsmg_printf("%s", hpp->buf);
5aed9d249   Namhyung Kim   perf hists browse...
604

2f6d9009a   Namhyung Kim   perf ui/tui: Reus...
605
  	advance_hpp(hpp, ret);
5aed9d249   Namhyung Kim   perf hists browse...
606
607
  	return ret;
  }
fb821c9e7   Namhyung Kim   perf ui: Get rid ...
608
  #define __HPP_COLOR_PERCENT_FN(_type, _field)				\
5aed9d249   Namhyung Kim   perf hists browse...
609
610
611
612
613
  static u64 __hpp_get_##_field(struct hist_entry *he)			\
  {									\
  	return he->stat._field;						\
  }									\
  									\
2c5d4b4a0   Jiri Olsa   perf tools: Add s...
614
  static int								\
5b5916696   Namhyung Kim   perf report: Hono...
615
  hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt,		\
2c5d4b4a0   Jiri Olsa   perf tools: Add s...
616
617
  				struct perf_hpp *hpp,			\
  				struct hist_entry *he)			\
f5951d56a   Namhyung Kim   perf hists browse...
618
  {									\
5b5916696   Namhyung Kim   perf report: Hono...
619
620
  	return hpp__fmt(fmt, hpp, he, __hpp_get_##_field, " %*.2f%%",	\
  			__hpp__slsmg_color_printf, true);		\
f5951d56a   Namhyung Kim   perf hists browse...
621
  }
0434ddd21   Namhyung Kim   perf ui/browser: ...
622
623
624
625
626
627
628
  #define __HPP_COLOR_ACC_PERCENT_FN(_type, _field)			\
  static u64 __hpp_get_acc_##_field(struct hist_entry *he)		\
  {									\
  	return he->stat_acc->_field;					\
  }									\
  									\
  static int								\
5b5916696   Namhyung Kim   perf report: Hono...
629
  hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt,		\
0434ddd21   Namhyung Kim   perf ui/browser: ...
630
631
632
633
  				struct perf_hpp *hpp,			\
  				struct hist_entry *he)			\
  {									\
  	if (!symbol_conf.cumulate_callchain) {				\
5b5916696   Namhyung Kim   perf report: Hono...
634
  		int len = fmt->user_len ?: fmt->len;			\
d675107ce   Namhyung Kim   perf tools: Make ...
635
  		int ret = scnprintf(hpp->buf, hpp->size,		\
5b5916696   Namhyung Kim   perf report: Hono...
636
  				    "%*s", len, "N/A");			\
0434ddd21   Namhyung Kim   perf ui/browser: ...
637
638
639
640
  		slsmg_printf("%s", hpp->buf);				\
  									\
  		return ret;						\
  	}								\
5b5916696   Namhyung Kim   perf report: Hono...
641
642
  	return hpp__fmt(fmt, hpp, he, __hpp_get_acc_##_field,		\
  			" %*.2f%%", __hpp__slsmg_color_printf, true);	\
0434ddd21   Namhyung Kim   perf ui/browser: ...
643
  }
fb821c9e7   Namhyung Kim   perf ui: Get rid ...
644
645
646
647
648
  __HPP_COLOR_PERCENT_FN(overhead, period)
  __HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
  __HPP_COLOR_PERCENT_FN(overhead_us, period_us)
  __HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
  __HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
0434ddd21   Namhyung Kim   perf ui/browser: ...
649
  __HPP_COLOR_ACC_PERCENT_FN(overhead_acc, period)
f5951d56a   Namhyung Kim   perf hists browse...
650

5aed9d249   Namhyung Kim   perf hists browse...
651
  #undef __HPP_COLOR_PERCENT_FN
0434ddd21   Namhyung Kim   perf ui/browser: ...
652
  #undef __HPP_COLOR_ACC_PERCENT_FN
f5951d56a   Namhyung Kim   perf hists browse...
653
654
655
  
  void hist_browser__init_hpp(void)
  {
f5951d56a   Namhyung Kim   perf hists browse...
656
657
658
659
660
661
662
663
664
665
  	perf_hpp__format[PERF_HPP__OVERHEAD].color =
  				hist_browser__hpp_color_overhead;
  	perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color =
  				hist_browser__hpp_color_overhead_sys;
  	perf_hpp__format[PERF_HPP__OVERHEAD_US].color =
  				hist_browser__hpp_color_overhead_us;
  	perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color =
  				hist_browser__hpp_color_overhead_guest_sys;
  	perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color =
  				hist_browser__hpp_color_overhead_guest_us;
0434ddd21   Namhyung Kim   perf ui/browser: ...
666
667
  	perf_hpp__format[PERF_HPP__OVERHEAD_ACC].color =
  				hist_browser__hpp_color_overhead_acc;
f5951d56a   Namhyung Kim   perf hists browse...
668
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
669
  static int hist_browser__show_entry(struct hist_browser *browser,
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
670
671
672
673
  				    struct hist_entry *entry,
  				    unsigned short row)
  {
  	char s[256];
1240005e0   Jiri Olsa   perf hists: Intro...
674
  	int printed = 0;
67d259165   Namhyung Kim   perf hists browse...
675
  	int width = browser->b.width;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
676
  	char folded_sign = ' ';
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
677
  	bool current_entry = ui_browser__is_current_entry(&browser->b, row);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
678
  	off_t row_offset = entry->row_offset;
63a1a3d82   Namhyung Kim   perf hists browse...
679
  	bool first = true;
1240005e0   Jiri Olsa   perf hists: Intro...
680
  	struct perf_hpp_fmt *fmt;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
681
682
  
  	if (current_entry) {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
683
684
  		browser->he_selection = entry;
  		browser->selection = &entry->ms;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
685
686
687
  	}
  
  	if (symbol_conf.use_callchain) {
163caed90   Arnaldo Carvalho de Melo   perf hists browse...
688
  		hist_entry__init_have_children(entry);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
689
690
691
692
  		folded_sign = hist_entry__folded(entry);
  	}
  
  	if (row_offset == 0) {
897014603   Namhyung Kim   perf hists browse...
693
  		struct hpp_arg arg = {
fb821c9e7   Namhyung Kim   perf ui: Get rid ...
694
  			.b		= &browser->b,
897014603   Namhyung Kim   perf hists browse...
695
696
697
  			.folded_sign	= folded_sign,
  			.current_entry	= current_entry,
  		};
f5951d56a   Namhyung Kim   perf hists browse...
698
699
700
  		struct perf_hpp hpp = {
  			.buf		= s,
  			.size		= sizeof(s),
897014603   Namhyung Kim   perf hists browse...
701
  			.ptr		= &arg,
f5951d56a   Namhyung Kim   perf hists browse...
702
  		};
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
703

ca3ff33b5   Arnaldo Carvalho de Melo   perf hists browse...
704
  		hist_browser__gotorc(browser, row, 0);
c172f7422   Arnaldo Carvalho de Melo   perf ui browser: ...
705

1240005e0   Jiri Olsa   perf hists: Intro...
706
  		perf_hpp__for_each_format(fmt) {
e67d49a72   Namhyung Kim   perf tools: Skip ...
707
708
  			if (perf_hpp__should_skip(fmt))
  				continue;
fb821c9e7   Namhyung Kim   perf ui: Get rid ...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
  			if (current_entry && browser->b.navkeypressed) {
  				ui_browser__set_color(&browser->b,
  						      HE_COLORSET_SELECTED);
  			} else {
  				ui_browser__set_color(&browser->b,
  						      HE_COLORSET_NORMAL);
  			}
  
  			if (first) {
  				if (symbol_conf.use_callchain) {
  					slsmg_printf("%c ", folded_sign);
  					width -= 2;
  				}
  				first = false;
  			} else {
f5951d56a   Namhyung Kim   perf hists browse...
724
725
726
  				slsmg_printf("  ");
  				width -= 2;
  			}
c172f7422   Arnaldo Carvalho de Melo   perf ui browser: ...
727

1240005e0   Jiri Olsa   perf hists: Intro...
728
  			if (fmt->color) {
2c5d4b4a0   Jiri Olsa   perf tools: Add s...
729
  				width -= fmt->color(fmt, &hpp, entry);
f5951d56a   Namhyung Kim   perf hists browse...
730
  			} else {
2c5d4b4a0   Jiri Olsa   perf tools: Add s...
731
  				width -= fmt->entry(fmt, &hpp, entry);
f5951d56a   Namhyung Kim   perf hists browse...
732
733
  				slsmg_printf("%s", s);
  			}
2cf9cebf0   Arnaldo Carvalho de Melo   perf hists browse...
734
  		}
f5951d56a   Namhyung Kim   perf hists browse...
735
736
737
  		/* The scroll bar isn't being used */
  		if (!browser->b.navkeypressed)
  			width += 1;
26d8b3382   Namhyung Kim   perf tools: Conso...
738
  		slsmg_write_nstring("", width);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
739
740
741
742
  		++row;
  		++printed;
  	} else
  		--row_offset;
62c95ae33   Arnaldo Carvalho de Melo   perf ui browser: ...
743
  	if (folded_sign == '-' && row != browser->b.rows) {
c09a7e755   Namhyung Kim   perf hists browse...
744
  		u64 total = hists__total_period(entry->hists);
39ee533fc   Namhyung Kim   perf hists browse...
745
746
747
748
  		struct callchain_print_arg arg = {
  			.row_offset = row_offset,
  			.is_current_entry = current_entry,
  		};
c09a7e755   Namhyung Kim   perf hists browse...
749

4087d11cd   Namhyung Kim   perf hists browse...
750
751
752
753
754
755
  		if (callchain_param.mode == CHAIN_GRAPH_REL) {
  			if (symbol_conf.cumulate_callchain)
  				total = entry->stat_acc->period;
  			else
  				total = entry->stat.period;
  		}
c09a7e755   Namhyung Kim   perf hists browse...
756
  		printed += hist_browser__show_callchain(browser,
39ee533fc   Namhyung Kim   perf hists browse...
757
758
759
  					&entry->sorted_chain, 1, row, total,
  					hist_browser__show_callchain_entry, &arg,
  					hist_browser__check_output_full);
c09a7e755   Namhyung Kim   perf hists browse...
760

39ee533fc   Namhyung Kim   perf hists browse...
761
  		if (arg.is_current_entry)
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
762
  			browser->he_selection = entry;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
763
764
765
766
  	}
  
  	return printed;
  }
81a888fea   Jiri Olsa   perf hists browse...
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
  static int advance_hpp_check(struct perf_hpp *hpp, int inc)
  {
  	advance_hpp(hpp, inc);
  	return hpp->size <= 0;
  }
  
  static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
  {
  	struct perf_hpp dummy_hpp = {
  		.buf    = buf,
  		.size   = size,
  	};
  	struct perf_hpp_fmt *fmt;
  	size_t ret = 0;
  
  	if (symbol_conf.use_callchain) {
  		ret = scnprintf(buf, size, "  ");
  		if (advance_hpp_check(&dummy_hpp, ret))
  			return ret;
  	}
  
  	perf_hpp__for_each_format(fmt) {
  		if (perf_hpp__should_skip(fmt))
  			continue;
81a888fea   Jiri Olsa   perf hists browse...
791
792
793
794
795
796
797
798
799
800
801
  		ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
  		if (advance_hpp_check(&dummy_hpp, ret))
  			break;
  
  		ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, "  ");
  		if (advance_hpp_check(&dummy_hpp, ret))
  			break;
  	}
  
  	return ret;
  }
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
802
803
  static void hist_browser__show_headers(struct hist_browser *browser)
  {
81a888fea   Jiri Olsa   perf hists browse...
804
805
806
  	char headers[1024];
  
  	hists__scnprintf_headers(headers, sizeof(headers), browser->hists);
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
807
808
  	ui_browser__gotorc(&browser->b, 0, 0);
  	ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
81a888fea   Jiri Olsa   perf hists browse...
809
  	slsmg_write_nstring(headers, browser->b.width + 1);
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
810
  }
437cfe7a3   Arnaldo Carvalho de Melo   perf hists browse...
811
812
813
814
815
816
817
818
819
  static void ui_browser__hists_init_top(struct ui_browser *browser)
  {
  	if (browser->top == NULL) {
  		struct hist_browser *hb;
  
  		hb = container_of(browser, struct hist_browser, b);
  		browser->top = rb_first(&hb->hists->entries);
  	}
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
820
  static unsigned int hist_browser__refresh(struct ui_browser *browser)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
821
822
  {
  	unsigned row = 0;
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
823
  	u16 header_offset = 0;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
824
  	struct rb_node *nd;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
825
  	struct hist_browser *hb = container_of(browser, struct hist_browser, b);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
826

025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
827
828
829
830
  	if (hb->show_headers) {
  		hist_browser__show_headers(hb);
  		header_offset = 1;
  	}
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
831
  	ui_browser__hists_init_top(browser);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
832

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
833
  	for (nd = browser->top; nd; nd = rb_next(nd)) {
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
834
  		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
14135663f   Namhyung Kim   perf tools: Apply...
835
  		float percent;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
836
837
838
  
  		if (h->filtered)
  			continue;
14135663f   Namhyung Kim   perf tools: Apply...
839
  		percent = hist_entry__get_percent_limit(h);
064f19815   Namhyung Kim   perf report: Add ...
840
841
  		if (percent < hb->min_pcnt)
  			continue;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
842
  		row += hist_browser__show_entry(hb, h, row);
62c95ae33   Arnaldo Carvalho de Melo   perf ui browser: ...
843
  		if (row == browser->rows)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
844
845
  			break;
  	}
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
846
  	return row + header_offset;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
847
  }
064f19815   Namhyung Kim   perf report: Add ...
848
  static struct rb_node *hists__filter_entries(struct rb_node *nd,
064f19815   Namhyung Kim   perf report: Add ...
849
  					     float min_pcnt)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
850
851
852
  {
  	while (nd != NULL) {
  		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
14135663f   Namhyung Kim   perf tools: Apply...
853
  		float percent = hist_entry__get_percent_limit(h);
064f19815   Namhyung Kim   perf report: Add ...
854

c0f1527b7   Namhyung Kim   perf report/tui: ...
855
  		if (!h->filtered && percent >= min_pcnt)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
856
857
858
859
860
861
862
  			return nd;
  
  		nd = rb_next(nd);
  	}
  
  	return NULL;
  }
064f19815   Namhyung Kim   perf report: Add ...
863
  static struct rb_node *hists__filter_prev_entries(struct rb_node *nd,
064f19815   Namhyung Kim   perf report: Add ...
864
  						  float min_pcnt)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
865
866
867
  {
  	while (nd != NULL) {
  		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
14135663f   Namhyung Kim   perf tools: Apply...
868
  		float percent = hist_entry__get_percent_limit(h);
064f19815   Namhyung Kim   perf report: Add ...
869
870
  
  		if (!h->filtered && percent >= min_pcnt)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
871
872
873
874
875
876
877
  			return nd;
  
  		nd = rb_prev(nd);
  	}
  
  	return NULL;
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
878
  static void ui_browser__hists_seek(struct ui_browser *browser,
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
879
880
881
882
883
  				   off_t offset, int whence)
  {
  	struct hist_entry *h;
  	struct rb_node *nd;
  	bool first = true;
064f19815   Namhyung Kim   perf report: Add ...
884
885
886
  	struct hist_browser *hb;
  
  	hb = container_of(browser, struct hist_browser, b);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
887

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
888
  	if (browser->nr_entries == 0)
60098917c   Arnaldo Carvalho de Melo   perf hists browse...
889
  		return;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
890
  	ui_browser__hists_init_top(browser);
437cfe7a3   Arnaldo Carvalho de Melo   perf hists browse...
891

d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
892
893
  	switch (whence) {
  	case SEEK_SET:
064f19815   Namhyung Kim   perf report: Add ...
894
  		nd = hists__filter_entries(rb_first(browser->entries),
14135663f   Namhyung Kim   perf tools: Apply...
895
  					   hb->min_pcnt);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
896
897
  		break;
  	case SEEK_CUR:
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
898
  		nd = browser->top;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
899
900
  		goto do_offset;
  	case SEEK_END:
064f19815   Namhyung Kim   perf report: Add ...
901
  		nd = hists__filter_prev_entries(rb_last(browser->entries),
14135663f   Namhyung Kim   perf tools: Apply...
902
  						hb->min_pcnt);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
903
904
905
906
907
908
909
910
911
912
  		first = false;
  		break;
  	default:
  		return;
  	}
  
  	/*
  	 * Moves not relative to the first visible entry invalidates its
  	 * row_offset:
  	 */
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
913
  	h = rb_entry(browser->top, struct hist_entry, rb_node);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
  	h->row_offset = 0;
  
  	/*
  	 * Here we have to check if nd is expanded (+), if it is we can't go
  	 * the next top level hist_entry, instead we must compute an offset of
  	 * what _not_ to show and not change the first visible entry.
  	 *
  	 * This offset increments when we are going from top to bottom and
  	 * decreases when we're going from bottom to top.
  	 *
  	 * As we don't have backpointers to the top level in the callchains
  	 * structure, we need to always print the whole hist_entry callchain,
  	 * skipping the first ones that are before the first visible entry
  	 * and stop when we printed enough lines to fill the screen.
  	 */
  do_offset:
  	if (offset > 0) {
  		do {
  			h = rb_entry(nd, struct hist_entry, rb_node);
  			if (h->ms.unfolded) {
  				u16 remaining = h->nr_rows - h->row_offset;
  				if (offset > remaining) {
  					offset -= remaining;
  					h->row_offset = 0;
  				} else {
  					h->row_offset += offset;
  					offset = 0;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
941
  					browser->top = nd;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
942
943
944
  					break;
  				}
  			}
14135663f   Namhyung Kim   perf tools: Apply...
945
  			nd = hists__filter_entries(rb_next(nd), hb->min_pcnt);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
946
947
948
  			if (nd == NULL)
  				break;
  			--offset;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
949
  			browser->top = nd;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
950
951
952
953
954
955
956
957
958
959
960
961
  		} while (offset != 0);
  	} else if (offset < 0) {
  		while (1) {
  			h = rb_entry(nd, struct hist_entry, rb_node);
  			if (h->ms.unfolded) {
  				if (first) {
  					if (-offset > h->row_offset) {
  						offset += h->row_offset;
  						h->row_offset = 0;
  					} else {
  						h->row_offset += offset;
  						offset = 0;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
962
  						browser->top = nd;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
963
964
965
966
967
968
969
970
971
  						break;
  					}
  				} else {
  					if (-offset > h->nr_rows) {
  						offset += h->nr_rows;
  						h->row_offset = 0;
  					} else {
  						h->row_offset = h->nr_rows + offset;
  						offset = 0;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
972
  						browser->top = nd;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
973
974
975
976
  						break;
  					}
  				}
  			}
14135663f   Namhyung Kim   perf tools: Apply...
977
  			nd = hists__filter_prev_entries(rb_prev(nd),
064f19815   Namhyung Kim   perf report: Add ...
978
  							hb->min_pcnt);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
979
980
981
  			if (nd == NULL)
  				break;
  			++offset;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
982
  			browser->top = nd;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
983
984
985
986
987
988
989
990
991
992
993
994
995
996
  			if (offset == 0) {
  				/*
  				 * Last unfiltered hist_entry, check if it is
  				 * unfolded, if it is then we should have
  				 * row_offset at its last entry.
  				 */
  				h = rb_entry(nd, struct hist_entry, rb_node);
  				if (h->ms.unfolded)
  					h->row_offset = h->nr_rows;
  				break;
  			}
  			first = false;
  		}
  	} else {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
997
  		browser->top = nd;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
998
999
1000
1001
  		h = rb_entry(nd, struct hist_entry, rb_node);
  		h->row_offset = 0;
  	}
  }
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1002
  static int hist_browser__fprintf_callchain(struct hist_browser *browser,
39ee533fc   Namhyung Kim   perf hists browse...
1003
  					   struct hist_entry *he, FILE *fp)
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1004
  {
39ee533fc   Namhyung Kim   perf hists browse...
1005
1006
1007
1008
  	u64 total = hists__total_period(he->hists);
  	struct callchain_print_arg arg  = {
  		.fp = fp,
  	};
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1009

39ee533fc   Namhyung Kim   perf hists browse...
1010
1011
  	if (symbol_conf.cumulate_callchain)
  		total = he->stat_acc->period;
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1012

39ee533fc   Namhyung Kim   perf hists browse...
1013
1014
1015
1016
  	hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total,
  				     hist_browser__fprintf_callchain_entry, &arg,
  				     hist_browser__check_dump_full);
  	return arg.printed;
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1017
1018
1019
1020
1021
1022
  }
  
  static int hist_browser__fprintf_entry(struct hist_browser *browser,
  				       struct hist_entry *he, FILE *fp)
  {
  	char s[8192];
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1023
1024
  	int printed = 0;
  	char folded_sign = ' ';
26d8b3382   Namhyung Kim   perf tools: Conso...
1025
1026
1027
1028
1029
1030
1031
  	struct perf_hpp hpp = {
  		.buf = s,
  		.size = sizeof(s),
  	};
  	struct perf_hpp_fmt *fmt;
  	bool first = true;
  	int ret;
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1032
1033
1034
  
  	if (symbol_conf.use_callchain)
  		folded_sign = hist_entry__folded(he);
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1035
1036
  	if (symbol_conf.use_callchain)
  		printed += fprintf(fp, "%c ", folded_sign);
26d8b3382   Namhyung Kim   perf tools: Conso...
1037
  	perf_hpp__for_each_format(fmt) {
e67d49a72   Namhyung Kim   perf tools: Skip ...
1038
1039
  		if (perf_hpp__should_skip(fmt))
  			continue;
26d8b3382   Namhyung Kim   perf tools: Conso...
1040
1041
1042
1043
1044
  		if (!first) {
  			ret = scnprintf(hpp.buf, hpp.size, "  ");
  			advance_hpp(&hpp, ret);
  		} else
  			first = false;
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1045

26d8b3382   Namhyung Kim   perf tools: Conso...
1046
1047
1048
  		ret = fmt->entry(fmt, &hpp, he);
  		advance_hpp(&hpp, ret);
  	}
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1049
1050
1051
1052
  	printed += fprintf(fp, "%s
  ", rtrim(s));
  
  	if (folded_sign == '-')
39ee533fc   Namhyung Kim   perf hists browse...
1053
  		printed += hist_browser__fprintf_callchain(browser, he, fp);
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1054
1055
1056
1057
1058
1059
  
  	return printed;
  }
  
  static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)
  {
064f19815   Namhyung Kim   perf report: Add ...
1060
  	struct rb_node *nd = hists__filter_entries(rb_first(browser->b.entries),
064f19815   Namhyung Kim   perf report: Add ...
1061
  						   browser->min_pcnt);
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1062
1063
1064
1065
1066
1067
  	int printed = 0;
  
  	while (nd) {
  		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
  
  		printed += hist_browser__fprintf_entry(browser, h, fp);
14135663f   Namhyung Kim   perf tools: Apply...
1068
  		nd = hists__filter_entries(rb_next(nd), browser->min_pcnt);
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
  	}
  
  	return printed;
  }
  
  static int hist_browser__dump(struct hist_browser *browser)
  {
  	char filename[64];
  	FILE *fp;
  
  	while (1) {
  		scnprintf(filename, sizeof(filename), "perf.hist.%d", browser->print_seq);
  		if (access(filename, F_OK))
  			break;
  		/*
   		 * XXX: Just an arbitrary lazy upper limit
   		 */
  		if (++browser->print_seq == 8192) {
  			ui_helpline__fpush("Too many perf.hist.N files, nothing written!");
  			return -1;
  		}
  	}
  
  	fp = fopen(filename, "w");
  	if (fp == NULL) {
  		char bf[64];
4cc49d4dc   Kirill A. Shutemov   perf tools: use X...
1095
1096
  		const char *err = strerror_r(errno, bf, sizeof(bf));
  		ui_helpline__fpush("Couldn't write to %s: %s", filename, err);
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  		return -1;
  	}
  
  	++browser->print_seq;
  	hist_browser__fprintf(browser, fp);
  	fclose(fp);
  	ui_helpline__fpush("%s written!", filename);
  
  	return 0;
  }
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1107
1108
  static struct hist_browser *hist_browser__new(struct hists *hists)
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1109
  	struct hist_browser *browser = zalloc(sizeof(*browser));
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1110

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1111
1112
1113
  	if (browser) {
  		browser->hists = hists;
  		browser->b.refresh = hist_browser__refresh;
357cfff1c   Arnaldo Carvalho de Melo   perf hists browse...
1114
  		browser->b.refresh_dimensions = hist_browser__refresh_dimensions;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1115
1116
  		browser->b.seek = ui_browser__hists_seek;
  		browser->b.use_navkeypressed = true;
c83023676   Jiri Olsa   perf hists browse...
1117
  		browser->show_headers = symbol_conf.show_hist_headers;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1118
  	}
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1119
  	return browser;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1120
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1121
  static void hist_browser__delete(struct hist_browser *browser)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1122
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1123
  	free(browser);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1124
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1125
  static struct hist_entry *hist_browser__selected_entry(struct hist_browser *browser)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1126
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1127
  	return browser->he_selection;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1128
  }
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1129
  static struct thread *hist_browser__selected_thread(struct hist_browser *browser)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1130
  {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1131
  	return browser->he_selection->thread;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1132
  }
1e378ebd1   Taeung Song   perf top: Add a v...
1133
1134
1135
1136
1137
1138
1139
1140
1141
  /* Check whether the browser is for 'top' or 'report' */
  static inline bool is_report_browser(void *timer)
  {
  	return timer == NULL;
  }
  
  static int hists__browser_title(struct hists *hists,
  				struct hist_browser_timer *hbt,
  				char *bf, size_t size)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1142
  {
469917ce8   Arnaldo Carvalho de Melo   perf ui browser: ...
1143
1144
  	char unit;
  	int printed;
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1145
1146
1147
1148
  	const struct dso *dso = hists->dso_filter;
  	const struct thread *thread = hists->thread_filter;
  	unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
  	u64 nr_events = hists->stats.total_period;
717e263fc   Namhyung Kim   perf report: Show...
1149
  	struct perf_evsel *evsel = hists_to_evsel(hists);
dd00d486d   Jiri Olsa   perf hists browse...
1150
  	const char *ev_name = perf_evsel__name(evsel);
717e263fc   Namhyung Kim   perf report: Show...
1151
1152
  	char buf[512];
  	size_t buflen = sizeof(buf);
f21483305   Namhyung Kim   perf report: Add ...
1153
1154
1155
1156
  	if (symbol_conf.filter_relative) {
  		nr_samples = hists->stats.nr_non_filtered_samples;
  		nr_events = hists->stats.total_non_filtered_period;
  	}
759ff497e   Namhyung Kim   perf evsel: Intro...
1157
  	if (perf_evsel__is_group_event(evsel)) {
717e263fc   Namhyung Kim   perf report: Show...
1158
1159
1160
1161
1162
1163
  		struct perf_evsel *pos;
  
  		perf_evsel__group_desc(evsel, buf, buflen);
  		ev_name = buf;
  
  		for_each_group_member(pos, evsel) {
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1164
  			struct hists *pos_hists = evsel__hists(pos);
f21483305   Namhyung Kim   perf report: Add ...
1165
  			if (symbol_conf.filter_relative) {
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1166
1167
  				nr_samples += pos_hists->stats.nr_non_filtered_samples;
  				nr_events += pos_hists->stats.total_non_filtered_period;
f21483305   Namhyung Kim   perf report: Add ...
1168
  			} else {
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1169
1170
  				nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
  				nr_events += pos_hists->stats.total_period;
f21483305   Namhyung Kim   perf report: Add ...
1171
  			}
717e263fc   Namhyung Kim   perf report: Show...
1172
1173
  		}
  	}
cc6862809   Ashay Rane   perf report: Corr...
1174
1175
1176
  
  	nr_samples = convert_unit(nr_samples, &unit);
  	printed = scnprintf(bf, size,
e641f696e   Tom Huynh   perf hists browse...
1177
  			   "Samples: %lu%c of event '%s', Event count (approx.): %" PRIu64,
cc6862809   Ashay Rane   perf report: Corr...
1178
  			   nr_samples, unit, ev_name, nr_events);
469917ce8   Arnaldo Carvalho de Melo   perf ui browser: ...
1179

d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1180

05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1181
  	if (hists->uid_filter_str)
0d37aa34f   Arnaldo Carvalho de Melo   perf tools: Intro...
1182
  		printed += snprintf(bf + printed, size - printed,
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1183
  				    ", UID: %s", hists->uid_filter_str);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1184
  	if (thread)
e7f01d1e3   Arnaldo Carvalho de Melo   perf tools: Use s...
1185
  		printed += scnprintf(bf + printed, size - printed,
469917ce8   Arnaldo Carvalho de Melo   perf ui browser: ...
1186
  				    ", Thread: %s(%d)",
b9c5143a0   Frederic Weisbecker   perf tools: Use a...
1187
  				     (thread->comm_set ? thread__comm_str(thread) : ""),
380512345   Adrian Hunter   perf tools: struc...
1188
  				    thread->tid);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1189
  	if (dso)
e7f01d1e3   Arnaldo Carvalho de Melo   perf tools: Use s...
1190
  		printed += scnprintf(bf + printed, size - printed,
469917ce8   Arnaldo Carvalho de Melo   perf ui browser: ...
1191
  				    ", DSO: %s", dso->short_name);
1e378ebd1   Taeung Song   perf top: Add a v...
1192
1193
1194
1195
1196
1197
  	if (!is_report_browser(hbt)) {
  		struct perf_top *top = hbt->arg;
  
  		if (top->zero)
  			printed += scnprintf(bf + printed, size - printed, " [z]");
  	}
469917ce8   Arnaldo Carvalho de Melo   perf ui browser: ...
1198
  	return printed;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1199
  }
24bff2dc0   Stephane Eranian   perf report: Fix ...
1200
1201
1202
  static inline void free_popup_options(char **options, int n)
  {
  	int i;
046625231   Arnaldo Carvalho de Melo   perf tools: Intro...
1203
1204
  	for (i = 0; i < n; ++i)
  		zfree(&options[i]);
24bff2dc0   Stephane Eranian   perf report: Fix ...
1205
  }
341487ab5   Feng Tang   perf hists browse...
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
  /*
   * Only runtime switching of perf data file will make "input_name" point
   * to a malloced buffer. So add "is_input_name_malloced" flag to decide
   * whether we need to call free() for current "input_name" during the switch.
   */
  static bool is_input_name_malloced = false;
  
  static int switch_data_file(void)
  {
  	char *pwd, *options[32], *abs_path[32], *tmp;
  	DIR *pwd_dir;
  	int nr_options = 0, choice = -1, ret = -1;
  	struct dirent *dent;
  
  	pwd = getenv("PWD");
  	if (!pwd)
  		return ret;
  
  	pwd_dir = opendir(pwd);
  	if (!pwd_dir)
  		return ret;
  
  	memset(options, 0, sizeof(options));
  	memset(options, 0, sizeof(abs_path));
  
  	while ((dent = readdir(pwd_dir))) {
  		char path[PATH_MAX];
  		u64 magic;
  		char *name = dent->d_name;
  		FILE *file;
  
  		if (!(dent->d_type == DT_REG))
  			continue;
  
  		snprintf(path, sizeof(path), "%s/%s", pwd, name);
  
  		file = fopen(path, "r");
  		if (!file)
  			continue;
  
  		if (fread(&magic, 1, 8, file) < 8)
  			goto close_file_and_continue;
  
  		if (is_perf_magic(magic)) {
  			options[nr_options] = strdup(name);
  			if (!options[nr_options])
  				goto close_file_and_continue;
  
  			abs_path[nr_options] = strdup(path);
  			if (!abs_path[nr_options]) {
74cf249d5   Arnaldo Carvalho de Melo   perf tools: Use z...
1256
  				zfree(&options[nr_options]);
341487ab5   Feng Tang   perf hists browse...
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
  				ui__warning("Can't search all data files due to memory shortage.
  ");
  				fclose(file);
  				break;
  			}
  
  			nr_options++;
  		}
  
  close_file_and_continue:
  		fclose(file);
  		if (nr_options >= 32) {
  			ui__warning("Too many perf data files in PWD!
  "
  				    "Only the first 32 files will be listed.
  ");
  			break;
  		}
  	}
  	closedir(pwd_dir);
  
  	if (nr_options) {
  		choice = ui__popup_menu(nr_options, options);
  		if (choice < nr_options && choice >= 0) {
  			tmp = strdup(abs_path[choice]);
  			if (tmp) {
  				if (is_input_name_malloced)
  					free((void *)input_name);
  				input_name = tmp;
  				is_input_name_malloced = true;
  				ret = 0;
  			} else
  				ui__warning("Data switch failed due to memory shortage!
  ");
  		}
  	}
  
  	free_popup_options(options, nr_options);
  	free_popup_options(abs_path, nr_options);
  	return ret;
  }
112f761fc   Namhyung Kim   perf ui/tui: Rena...
1298
  static void hist_browser__update_nr_entries(struct hist_browser *hb)
064f19815   Namhyung Kim   perf report: Add ...
1299
1300
1301
  {
  	u64 nr_entries = 0;
  	struct rb_node *nd = rb_first(&hb->hists->entries);
268397cb2   Namhyung Kim   perf top/tui: Upd...
1302
1303
1304
1305
  	if (hb->min_pcnt == 0) {
  		hb->nr_non_filtered_entries = hb->hists->nr_non_filtered_entries;
  		return;
  	}
14135663f   Namhyung Kim   perf tools: Apply...
1306
  	while ((nd = hists__filter_entries(nd, hb->min_pcnt)) != NULL) {
064f19815   Namhyung Kim   perf report: Add ...
1307
  		nr_entries++;
c481f9301   Namhyung Kim   perf ui/tui: Fix ...
1308
  		nd = rb_next(nd);
064f19815   Namhyung Kim   perf report: Add ...
1309
  	}
112f761fc   Namhyung Kim   perf ui/tui: Rena...
1310
  	hb->nr_non_filtered_entries = nr_entries;
064f19815   Namhyung Kim   perf report: Add ...
1311
  }
341487ab5   Feng Tang   perf hists browse...
1312

34958544b   Arnaldo Carvalho de Melo   perf annotate bro...
1313
  static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
dd00d486d   Jiri Olsa   perf hists browse...
1314
  				    const char *helpline,
81cce8de9   Arnaldo Carvalho de Melo   perf browsers: Ad...
1315
  				    bool left_exits,
68d807586   Namhyung Kim   perf report: Post...
1316
  				    struct hist_browser_timer *hbt,
064f19815   Namhyung Kim   perf report: Add ...
1317
  				    float min_pcnt,
68d807586   Namhyung Kim   perf report: Post...
1318
  				    struct perf_session_env *env)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1319
  {
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1320
  	struct hists *hists = evsel__hists(evsel);
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1321
  	struct hist_browser *browser = hist_browser__new(hists);
a68c2c581   Stephane Eranian   perf report: Enab...
1322
  	struct branch_info *bi;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1323
  	struct pstack *fstack;
24bff2dc0   Stephane Eranian   perf report: Fix ...
1324
1325
  	char *options[16];
  	int nr_options = 0;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1326
  	int key = -1;
938a23ae7   Namhyung Kim   perf ui browser: ...
1327
  	char buf[64];
cdbab7c20   Feng Tang   perf hists browse...
1328
  	char script_opt[64];
9783adf77   Namhyung Kim   perf tools: Intro...
1329
  	int delay_secs = hbt ? hbt->refresh : 0;
59dc9f253   Namhyung Kim   perf tools: Fix c...
1330
  	struct perf_hpp_fmt *fmt;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1331

e8e684a58   Namhyung Kim   perf ui/tui: Spli...
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
  #define HIST_BROWSER_HELP_COMMON					\
  	"h/?/F1        Show this window
  "				\
  	"UP/DOWN/PGUP
  "						\
  	"PGDN/SPACE    Navigate
  "					\
  	"q/ESC/CTRL+C  Exit browser
  
  "				\
  	"For multiple event sessions:
  
  "				\
  	"TAB/UNTAB     Switch events
  
  "				\
  	"For symbolic views (--sort has sym):
  
  "			\
  	"->            Zoom into DSO/Threads & Annotate current symbol
  " \
  	"<-            Zoom out
  "					\
  	"a             Annotate current symbol
  "			\
  	"C             Collapse all callchains
  "			\
  	"d             Zoom into current DSO
  "				\
  	"E             Expand all callchains
  "				\
105eb30f1   Namhyung Kim   perf ui/tui: Add ...
1363
1364
  	"F             Toggle percentage of filtered entries
  "		\
025bf7ea0   Arnaldo Carvalho de Melo   perf hists browse...
1365
1366
  	"H             Display column headers
  "			\
e8e684a58   Namhyung Kim   perf ui/tui: Spli...
1367
1368
1369
  
  	/* help messages are sorted by lexical order of the hotkey */
  	const char report_help[] = HIST_BROWSER_HELP_COMMON
6dd601354   Namhyung Kim   perf ui/tui: Impl...
1370
1371
  	"i             Show header information
  "
e8e684a58   Namhyung Kim   perf ui/tui: Spli...
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
  	"P             Print histograms to perf.hist.N
  "
  	"r             Run available scripts
  "
  	"s             Switch to another data file in PWD
  "
  	"t             Zoom into current Thread
  "
  	"V             Verbose (DSO names in callchains, etc)
  "
  	"/             Filter symbol by name";
  	const char top_help[] = HIST_BROWSER_HELP_COMMON
  	"P             Print histograms to perf.hist.N
  "
  	"t             Zoom into current Thread
  "
  	"V             Verbose (DSO names in callchains, etc)
  "
42337a222   Namhyung Kim   perf top: Handle ...
1390
1391
  	"z             Toggle zeroing of samples
  "
e8e684a58   Namhyung Kim   perf ui/tui: Spli...
1392
  	"/             Filter symbol by name";
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1393
1394
  	if (browser == NULL)
  		return -1;
064f19815   Namhyung Kim   perf report: Add ...
1395
1396
  	if (min_pcnt) {
  		browser->min_pcnt = min_pcnt;
112f761fc   Namhyung Kim   perf ui/tui: Rena...
1397
  		hist_browser__update_nr_entries(browser);
064f19815   Namhyung Kim   perf report: Add ...
1398
  	}
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1399
1400
1401
1402
1403
  	fstack = pstack__new(2);
  	if (fstack == NULL)
  		goto out;
  
  	ui_helpline__push(helpline);
24bff2dc0   Stephane Eranian   perf report: Fix ...
1404
  	memset(options, 0, sizeof(options));
59dc9f253   Namhyung Kim   perf tools: Fix c...
1405
1406
  	perf_hpp__for_each_format(fmt)
  		perf_hpp__reset_width(fmt, hists);
5b5916696   Namhyung Kim   perf report: Hono...
1407
1408
  	if (symbol_conf.col_width_list_str)
  		perf_hpp__set_user_width(symbol_conf.col_width_list_str);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1409
  	while (1) {
60098917c   Arnaldo Carvalho de Melo   perf hists browse...
1410
1411
  		const struct thread *thread = NULL;
  		const struct dso *dso = NULL;
24bff2dc0   Stephane Eranian   perf report: Fix ...
1412
  		int choice = 0,
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1413
  		    annotate = -2, zoom_dso = -2, zoom_thread = -2,
a68c2c581   Stephane Eranian   perf report: Enab...
1414
  		    annotate_f = -2, annotate_t = -2, browse_map = -2;
341487ab5   Feng Tang   perf hists browse...
1415
1416
  		int scripts_comm = -2, scripts_symbol = -2,
  		    scripts_all = -2, switch_data = -2;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1417

24bff2dc0   Stephane Eranian   perf report: Fix ...
1418
  		nr_options = 0;
dd00d486d   Jiri Olsa   perf hists browse...
1419
  		key = hist_browser__run(browser, hbt);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1420

60098917c   Arnaldo Carvalho de Melo   perf hists browse...
1421
1422
1423
1424
  		if (browser->he_selection != NULL) {
  			thread = hist_browser__selected_thread(browser);
  			dso = browser->selection->map ? browser->selection->map->dso : NULL;
  		}
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1425
  		switch (key) {
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1426
1427
  		case K_TAB:
  		case K_UNTAB:
e4419b8ed   David Ahern   perf hists browse...
1428
1429
  			if (nr_events == 1)
  				continue;
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1430
1431
1432
1433
1434
1435
  			/*
  			 * Exit the browser, let hists__browser_tree
  			 * go to the next or previous
  			 */
  			goto out_free_stack;
  		case 'a':
9c796ec8d   Arnaldo Carvalho de Melo   perf hists browse...
1436
  			if (!sort__has_sym) {
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
1437
  				ui_browser__warning(&browser->b, delay_secs * 2,
a6e51f9fa   Arnaldo Carvalho de Melo   perf hists browse...
1438
  			"Annotation is only available for symbolic views, "
a68c2c581   Stephane Eranian   perf report: Enab...
1439
  			"include \"sym*\" in --sort to use it.");
a6e51f9fa   Arnaldo Carvalho de Melo   perf hists browse...
1440
1441
  				continue;
  			}
60098917c   Arnaldo Carvalho de Melo   perf hists browse...
1442
  			if (browser->selection == NULL ||
db9a9cbc8   Lin Ming   perf hists browse...
1443
  			    browser->selection->sym == NULL ||
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1444
  			    browser->selection->map->dso->annotate_warned)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1445
  				continue;
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1446
  			goto do_annotate;
aff3f3f68   Arnaldo Carvalho de Melo   perf hists browse...
1447
1448
1449
  		case 'P':
  			hist_browser__dump(browser);
  			continue;
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1450
1451
  		case 'd':
  			goto zoom_dso;
a7cb8863d   Arnaldo Carvalho de Melo   perf hists browse...
1452
1453
1454
  		case 'V':
  			browser->show_dso = !browser->show_dso;
  			continue;
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1455
1456
  		case 't':
  			goto zoom_thread;
5a5626b1b   Arnaldo Carvalho de Melo   perf hists browse...
1457
  		case '/':
938a23ae7   Namhyung Kim   perf ui browser: ...
1458
1459
1460
1461
  			if (ui_browser__input_window("Symbol to show",
  					"Please enter the name of symbol you want to see",
  					buf, "ENTER: OK, ESC: Cancel",
  					delay_secs * 2) == K_ENTER) {
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1462
1463
  				hists->symbol_filter_str = *buf ? buf : NULL;
  				hists__filter_by_symbol(hists);
938a23ae7   Namhyung Kim   perf ui browser: ...
1464
1465
1466
  				hist_browser__reset(browser);
  			}
  			continue;
cdbab7c20   Feng Tang   perf hists browse...
1467
  		case 'r':
9783adf77   Namhyung Kim   perf tools: Intro...
1468
  			if (is_report_browser(hbt))
c77d8d703   Feng Tang   perf browser: Don...
1469
1470
  				goto do_scripts;
  			continue;
341487ab5   Feng Tang   perf hists browse...
1471
1472
1473
1474
  		case 's':
  			if (is_report_browser(hbt))
  				goto do_data_switch;
  			continue;
6dd601354   Namhyung Kim   perf ui/tui: Impl...
1475
1476
1477
1478
1479
  		case 'i':
  			/* env->arch is NULL for live-mode (i.e. perf top) */
  			if (env->arch)
  				tui__header_window(env);
  			continue;
105eb30f1   Namhyung Kim   perf ui/tui: Add ...
1480
1481
1482
  		case 'F':
  			symbol_conf.filter_relative ^= 1;
  			continue;
42337a222   Namhyung Kim   perf top: Handle ...
1483
1484
1485
1486
1487
1488
1489
  		case 'z':
  			if (!is_report_browser(hbt)) {
  				struct perf_top *top = hbt->arg;
  
  				top->zero = !top->zero;
  			}
  			continue;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1490
  		case K_F1:
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1491
1492
  		case 'h':
  		case '?':
4610e4137   Arnaldo Carvalho de Melo   perf ui browser: ...
1493
  			ui_browser__help_window(&browser->b,
e8e684a58   Namhyung Kim   perf ui/tui: Spli...
1494
  				is_report_browser(hbt) ? report_help : top_help);
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1495
  			continue;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1496
1497
  		case K_ENTER:
  		case K_RIGHT:
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1498
1499
  			/* menu */
  			break;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1500
  		case K_LEFT: {
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1501
  			const void *top;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1502

7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1503
1504
1505
1506
1507
1508
  			if (pstack__empty(fstack)) {
  				/*
  				 * Go back to the perf_evsel_menu__run or other user
  				 */
  				if (left_exits)
  					goto out_free_stack;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1509
  				continue;
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1510
  			}
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1511
  			top = pstack__pop(fstack);
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1512
  			if (top == &browser->hists->dso_filter)
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1513
  				goto zoom_out_dso;
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1514
  			if (top == &browser->hists->thread_filter)
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1515
1516
1517
  				goto zoom_out_thread;
  			continue;
  		}
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1518
  		case K_ESC:
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1519
  			if (!left_exits &&
4610e4137   Arnaldo Carvalho de Melo   perf ui browser: ...
1520
1521
  			    !ui_browser__dialog_yesno(&browser->b,
  					       "Do you really want to exit?"))
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1522
1523
  				continue;
  			/* Fall thru */
ed7e5662d   Arnaldo Carvalho de Melo   perf ui browser: ...
1524
1525
  		case 'q':
  		case CTRL('c'):
b50e003db   Arnaldo Carvalho de Melo   perf ui browser: ...
1526
  			goto out_free_stack;
ed7e5662d   Arnaldo Carvalho de Melo   perf ui browser: ...
1527
1528
  		default:
  			continue;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1529
  		}
9c796ec8d   Arnaldo Carvalho de Melo   perf hists browse...
1530
  		if (!sort__has_sym)
724c9c9f2   Arnaldo Carvalho de Melo   perf hists browse...
1531
  			goto add_exit_option;
55369fc17   Namhyung Kim   perf sort: Introd...
1532
  		if (sort__mode == SORT_MODE__BRANCH) {
a68c2c581   Stephane Eranian   perf report: Enab...
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
  			bi = browser->he_selection->branch_info;
  			if (browser->selection != NULL &&
  			    bi &&
  			    bi->from.sym != NULL &&
  			    !bi->from.map->dso->annotate_warned &&
  				asprintf(&options[nr_options], "Annotate %s",
  					 bi->from.sym->name) > 0)
  				annotate_f = nr_options++;
  
  			if (browser->selection != NULL &&
  			    bi &&
  			    bi->to.sym != NULL &&
  			    !bi->to.map->dso->annotate_warned &&
8bcd65fd2   Stephane Eranian   perf report: Remo...
1546
1547
  			    (bi->to.sym != bi->from.sym ||
  			     bi->to.map->dso != bi->from.map->dso) &&
a68c2c581   Stephane Eranian   perf report: Enab...
1548
1549
1550
1551
  				asprintf(&options[nr_options], "Annotate %s",
  					 bi->to.sym->name) > 0)
  				annotate_t = nr_options++;
  		} else {
a68c2c581   Stephane Eranian   perf report: Enab...
1552
1553
  			if (browser->selection != NULL &&
  			    browser->selection->sym != NULL &&
d755330c5   Jiri Olsa   perf tools: Fix s...
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
  			    !browser->selection->map->dso->annotate_warned) {
  				struct annotation *notes;
  
  				notes = symbol__annotation(browser->selection->sym);
  
  				if (notes->src &&
  				    asprintf(&options[nr_options], "Annotate %s",
  						 browser->selection->sym->name) > 0)
  					annotate = nr_options++;
  			}
a68c2c581   Stephane Eranian   perf report: Enab...
1564
  		}
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1565
1566
1567
  
  		if (thread != NULL &&
  		    asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1568
  			     (browser->hists->thread_filter ? "out of" : "into"),
b9c5143a0   Frederic Weisbecker   perf tools: Use a...
1569
  			     (thread->comm_set ? thread__comm_str(thread) : ""),
380512345   Adrian Hunter   perf tools: struc...
1570
  			     thread->tid) > 0)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1571
1572
1573
1574
  			zoom_thread = nr_options++;
  
  		if (dso != NULL &&
  		    asprintf(&options[nr_options], "Zoom %s %s DSO",
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1575
  			     (browser->hists->dso_filter ? "out of" : "into"),
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1576
1577
  			     (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
  			zoom_dso = nr_options++;
60098917c   Arnaldo Carvalho de Melo   perf hists browse...
1578
1579
  		if (browser->selection != NULL &&
  		    browser->selection->map != NULL &&
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1580
1581
  		    asprintf(&options[nr_options], "Browse map details") > 0)
  			browse_map = nr_options++;
cdbab7c20   Feng Tang   perf hists browse...
1582
1583
1584
1585
1586
1587
  
  		/* perf script support */
  		if (browser->he_selection) {
  			struct symbol *sym;
  
  			if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]",
b9c5143a0   Frederic Weisbecker   perf tools: Use a...
1588
  				     thread__comm_str(browser->he_selection->thread)) > 0)
cdbab7c20   Feng Tang   perf hists browse...
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
  				scripts_comm = nr_options++;
  
  			sym = browser->he_selection->ms.sym;
  			if (sym && sym->namelen &&
  				asprintf(&options[nr_options], "Run scripts for samples of symbol [%s]",
  						sym->name) > 0)
  				scripts_symbol = nr_options++;
  		}
  
  		if (asprintf(&options[nr_options], "Run scripts for all samples") > 0)
  			scripts_all = nr_options++;
341487ab5   Feng Tang   perf hists browse...
1600
1601
1602
  		if (is_report_browser(hbt) && asprintf(&options[nr_options],
  				"Switch to another data file in PWD") > 0)
  			switch_data = nr_options++;
724c9c9f2   Arnaldo Carvalho de Melo   perf hists browse...
1603
  add_exit_option:
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1604
  		options[nr_options++] = (char *)"Exit";
24bff2dc0   Stephane Eranian   perf report: Fix ...
1605
  retry_popup_menu:
1e6dd077a   Arnaldo Carvalho de Melo   perf ui: Complete...
1606
  		choice = ui__popup_menu(nr_options, options);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1607

d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1608
1609
  		if (choice == nr_options - 1)
  			break;
24bff2dc0   Stephane Eranian   perf report: Fix ...
1610
1611
  		if (choice == -1) {
  			free_popup_options(options, nr_options - 1);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1612
  			continue;
24bff2dc0   Stephane Eranian   perf report: Fix ...
1613
  		}
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1614

a68c2c581   Stephane Eranian   perf report: Enab...
1615
  		if (choice == annotate || choice == annotate_t || choice == annotate_f) {
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1616
  			struct hist_entry *he;
d755330c5   Jiri Olsa   perf tools: Fix s...
1617
  			struct annotation *notes;
4610e4137   Arnaldo Carvalho de Melo   perf ui browser: ...
1618
  			int err;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1619
  do_annotate:
68d807586   Namhyung Kim   perf report: Post...
1620
1621
  			if (!objdump_path && perf_session_env__lookup_objdump(env))
  				continue;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1622
1623
1624
  			he = hist_browser__selected_entry(browser);
  			if (he == NULL)
  				continue;
a68c2c581   Stephane Eranian   perf report: Enab...
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
  
  			/*
  			 * we stash the branch_info symbol + map into the
  			 * the ms so we don't have to rewrite all the annotation
  			 * code to use branch_info.
  			 * in branch mode, the ms struct is not used
  			 */
  			if (choice == annotate_f) {
  				he->ms.sym = he->branch_info->from.sym;
  				he->ms.map = he->branch_info->from.map;
  			}  else if (choice == annotate_t) {
  				he->ms.sym = he->branch_info->to.sym;
  				he->ms.map = he->branch_info->to.map;
  			}
d755330c5   Jiri Olsa   perf tools: Fix s...
1639
1640
1641
  			notes = symbol__annotation(he->ms.sym);
  			if (!notes->src)
  				continue;
df71d95f8   Arnaldo Carvalho de Melo   perf hists: Don't...
1642
1643
1644
1645
  			/*
  			 * Don't let this be freed, say, by hists__decay_entry.
  			 */
  			he->used = true;
db8fd07a5   Namhyung Kim   perf annotate: Pa...
1646
  			err = hist_entry__tui_annotate(he, evsel, hbt);
df71d95f8   Arnaldo Carvalho de Melo   perf hists: Don't...
1647
  			he->used = false;
24bff2dc0   Stephane Eranian   perf report: Fix ...
1648
1649
1650
1651
1652
1653
1654
  			/*
  			 * offer option to annotate the other branch source or target
  			 * (if they exists) when returning from annotate
  			 */
  			if ((err == 'q' || err == CTRL('c'))
  			    && annotate_t != -2 && annotate_f != -2)
  				goto retry_popup_menu;
900e14a8f   Arnaldo Carvalho de Melo   perf hists browse...
1655
  			ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
4610e4137   Arnaldo Carvalho de Melo   perf ui browser: ...
1656
1657
  			if (err)
  				ui_browser__handle_resize(&browser->b);
24bff2dc0   Stephane Eranian   perf report: Fix ...
1658

d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1659
1660
1661
1662
  		} else if (choice == browse_map)
  			map__browse(browser->selection->map);
  		else if (choice == zoom_dso) {
  zoom_dso:
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1663
1664
  			if (browser->hists->dso_filter) {
  				pstack__remove(fstack, &browser->hists->dso_filter);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1665
1666
  zoom_out_dso:
  				ui_helpline__pop();
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1667
  				browser->hists->dso_filter = NULL;
f29984226   Jiri Olsa   perf tools: Move ...
1668
  				perf_hpp__set_elide(HISTC_DSO, false);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1669
1670
1671
1672
1673
  			} else {
  				if (dso == NULL)
  					continue;
  				ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
  						   dso->kernel ? "the Kernel" : dso->short_name);
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1674
  				browser->hists->dso_filter = dso;
f29984226   Jiri Olsa   perf tools: Move ...
1675
  				perf_hpp__set_elide(HISTC_DSO, true);
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1676
  				pstack__push(fstack, &browser->hists->dso_filter);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1677
  			}
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1678
  			hists__filter_by_dso(hists);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1679
1680
1681
  			hist_browser__reset(browser);
  		} else if (choice == zoom_thread) {
  zoom_thread:
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1682
1683
  			if (browser->hists->thread_filter) {
  				pstack__remove(fstack, &browser->hists->thread_filter);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1684
1685
  zoom_out_thread:
  				ui_helpline__pop();
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1686
  				browser->hists->thread_filter = NULL;
f29984226   Jiri Olsa   perf tools: Move ...
1687
  				perf_hpp__set_elide(HISTC_THREAD, false);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1688
1689
  			} else {
  				ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
b9c5143a0   Frederic Weisbecker   perf tools: Use a...
1690
  						   thread->comm_set ? thread__comm_str(thread) : "",
380512345   Adrian Hunter   perf tools: struc...
1691
  						   thread->tid);
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1692
  				browser->hists->thread_filter = thread;
f29984226   Jiri Olsa   perf tools: Move ...
1693
  				perf_hpp__set_elide(HISTC_THREAD, false);
d7b76f093   Arnaldo Carvalho de Melo   perf hists: Move ...
1694
  				pstack__push(fstack, &browser->hists->thread_filter);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1695
  			}
05e8b0804   Arnaldo Carvalho de Melo   perf ui browser: ...
1696
  			hists__filter_by_thread(hists);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1697
1698
  			hist_browser__reset(browser);
  		}
cdbab7c20   Feng Tang   perf hists browse...
1699
1700
1701
1702
1703
1704
1705
  		/* perf scripts support */
  		else if (choice == scripts_all || choice == scripts_comm ||
  				choice == scripts_symbol) {
  do_scripts:
  			memset(script_opt, 0, 64);
  
  			if (choice == scripts_comm)
b9c5143a0   Frederic Weisbecker   perf tools: Use a...
1706
  				sprintf(script_opt, " -c %s ", thread__comm_str(browser->he_selection->thread));
cdbab7c20   Feng Tang   perf hists browse...
1707
1708
1709
1710
1711
1712
  
  			if (choice == scripts_symbol)
  				sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name);
  
  			script_browse(script_opt);
  		}
341487ab5   Feng Tang   perf hists browse...
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
  		/* Switch to another data file */
  		else if (choice == switch_data) {
  do_data_switch:
  			if (!switch_data_file()) {
  				key = K_SWITCH_INPUT_DATA;
  				break;
  			} else
  				ui__warning("Won't switch the data files due to
  "
  					"no valid data file get selected!
  ");
  		}
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1725
1726
1727
1728
1729
  	}
  out_free_stack:
  	pstack__delete(fstack);
  out:
  	hist_browser__delete(browser);
24bff2dc0   Stephane Eranian   perf report: Fix ...
1730
  	free_popup_options(options, nr_options - 1);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1731
1732
  	return key;
  }
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1733
1734
1735
  struct perf_evsel_menu {
  	struct ui_browser b;
  	struct perf_evsel *selection;
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
1736
  	bool lost_events, lost_events_warned;
064f19815   Namhyung Kim   perf report: Add ...
1737
  	float min_pcnt;
68d807586   Namhyung Kim   perf report: Post...
1738
  	struct perf_session_env *env;
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1739
1740
1741
1742
1743
1744
1745
1746
  };
  
  static void perf_evsel_menu__write(struct ui_browser *browser,
  				   void *entry, int row)
  {
  	struct perf_evsel_menu *menu = container_of(browser,
  						    struct perf_evsel_menu, b);
  	struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1747
  	struct hists *hists = evsel__hists(evsel);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1748
  	bool current_entry = ui_browser__is_current_entry(browser, row);
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1749
  	unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];
7289f83cc   Arnaldo Carvalho de Melo   perf tools: Move ...
1750
  	const char *ev_name = perf_evsel__name(evsel);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1751
  	char bf[256], unit;
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
1752
1753
  	const char *warn = " ";
  	size_t printed;
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1754
1755
1756
  
  	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
  						       HE_COLORSET_NORMAL);
759ff497e   Namhyung Kim   perf evsel: Intro...
1757
  	if (perf_evsel__is_group_event(evsel)) {
717e263fc   Namhyung Kim   perf report: Show...
1758
1759
1760
1761
1762
  		struct perf_evsel *pos;
  
  		ev_name = perf_evsel__group_name(evsel);
  
  		for_each_group_member(pos, evsel) {
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1763
1764
  			struct hists *pos_hists = evsel__hists(pos);
  			nr_events += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
717e263fc   Namhyung Kim   perf report: Show...
1765
1766
  		}
  	}
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1767
  	nr_events = convert_unit(nr_events, &unit);
e7f01d1e3   Arnaldo Carvalho de Melo   perf tools: Use s...
1768
  	printed = scnprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
1769
1770
  			   unit, unit == ' ' ? "" : " ", ev_name);
  	slsmg_printf("%s", bf);
4ea062ed4   Arnaldo Carvalho de Melo   perf evsel: Add h...
1771
  	nr_events = hists->stats.nr_events[PERF_RECORD_LOST];
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
1772
1773
1774
1775
1776
  	if (nr_events != 0) {
  		menu->lost_events = true;
  		if (!current_entry)
  			ui_browser__set_color(browser, HE_COLORSET_TOP);
  		nr_events = convert_unit(nr_events, &unit);
e7f01d1e3   Arnaldo Carvalho de Melo   perf tools: Use s...
1777
1778
  		printed += scnprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!",
  				     nr_events, unit, unit == ' ' ? "" : " ");
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
1779
1780
1781
1782
  		warn = bf;
  	}
  
  	slsmg_write_nstring(warn, browser->width - printed);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1783
1784
1785
1786
  
  	if (current_entry)
  		menu->selection = evsel;
  }
34958544b   Arnaldo Carvalho de Melo   perf annotate bro...
1787
1788
  static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
  				int nr_events, const char *help,
9783adf77   Namhyung Kim   perf tools: Intro...
1789
  				struct hist_browser_timer *hbt)
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1790
  {
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1791
  	struct perf_evlist *evlist = menu->b.priv;
e248de331   Arnaldo Carvalho de Melo   perf tools: Impro...
1792
  	struct perf_evsel *pos;
dd00d486d   Jiri Olsa   perf hists browse...
1793
  	const char *title = "Available samples";
9783adf77   Namhyung Kim   perf tools: Intro...
1794
  	int delay_secs = hbt ? hbt->refresh : 0;
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1795
  	int key;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1796

7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1797
1798
1799
  	if (ui_browser__show(&menu->b, title,
  			     "ESC: exit, ENTER|->: Browse histograms") < 0)
  		return -1;
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1800
  	while (1) {
3af6e3386   Arnaldo Carvalho de Melo   perf ui browser: ...
1801
  		key = ui_browser__run(&menu->b, delay_secs);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1802
1803
  
  		switch (key) {
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1804
  		case K_TIMER:
9783adf77   Namhyung Kim   perf tools: Intro...
1805
  			hbt->timer(hbt->arg);
7b27509fc   Arnaldo Carvalho de Melo   perf hists browse...
1806
1807
1808
1809
1810
  
  			if (!menu->lost_events_warned && menu->lost_events) {
  				ui_browser__warn_lost_events(&menu->b);
  				menu->lost_events_warned = true;
  			}
81cce8de9   Arnaldo Carvalho de Melo   perf browsers: Ad...
1811
  			continue;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1812
1813
  		case K_RIGHT:
  		case K_ENTER:
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1814
1815
1816
1817
  			if (!menu->selection)
  				continue;
  			pos = menu->selection;
  browse_hists:
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1818
1819
1820
1821
1822
  			perf_evlist__set_selected(evlist, pos);
  			/*
  			 * Give the calling tool a chance to populate the non
  			 * default evsel resorted hists tree.
  			 */
9783adf77   Namhyung Kim   perf tools: Intro...
1823
1824
  			if (hbt)
  				hbt->timer(hbt->arg);
34958544b   Arnaldo Carvalho de Melo   perf annotate bro...
1825
  			key = perf_evsel__hists_browse(pos, nr_events, help,
dd00d486d   Jiri Olsa   perf hists browse...
1826
  						       true, hbt,
064f19815   Namhyung Kim   perf report: Add ...
1827
  						       menu->min_pcnt,
68d807586   Namhyung Kim   perf report: Post...
1828
  						       menu->env);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1829
  			ui_browser__show_title(&menu->b, title);
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1830
  			switch (key) {
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1831
  			case K_TAB:
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1832
  				if (pos->node.next == &evlist->entries)
9a354cdc2   Arnaldo Carvalho de Melo   perf tools: Use p...
1833
  					pos = perf_evlist__first(evlist);
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1834
  				else
9a354cdc2   Arnaldo Carvalho de Melo   perf tools: Use p...
1835
  					pos = perf_evsel__next(pos);
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1836
  				goto browse_hists;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1837
  			case K_UNTAB:
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1838
  				if (pos->node.prev == &evlist->entries)
9a354cdc2   Arnaldo Carvalho de Melo   perf tools: Use p...
1839
  					pos = perf_evlist__last(evlist);
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1840
  				else
d87fcb4a2   Arnaldo Carvalho de Melo   perf evsel: Intro...
1841
  					pos = perf_evsel__prev(pos);
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1842
  				goto browse_hists;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1843
  			case K_ESC:
4610e4137   Arnaldo Carvalho de Melo   perf ui browser: ...
1844
1845
  				if (!ui_browser__dialog_yesno(&menu->b,
  						"Do you really want to exit?"))
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1846
1847
  					continue;
  				/* Fall thru */
341487ab5   Feng Tang   perf hists browse...
1848
  			case K_SWITCH_INPUT_DATA:
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1849
1850
1851
1852
1853
1854
  			case 'q':
  			case CTRL('c'):
  				goto out;
  			default:
  				continue;
  			}
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1855
  		case K_LEFT:
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1856
  			continue;
cf9580036   Arnaldo Carvalho de Melo   perf ui browser: ...
1857
  		case K_ESC:
4610e4137   Arnaldo Carvalho de Melo   perf ui browser: ...
1858
1859
  			if (!ui_browser__dialog_yesno(&menu->b,
  					       "Do you really want to exit?"))
ed7e5662d   Arnaldo Carvalho de Melo   perf ui browser: ...
1860
1861
  				continue;
  			/* Fall thru */
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1862
1863
1864
  		case 'q':
  		case CTRL('c'):
  			goto out;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1865
  		default:
18eaf0b8e   Arnaldo Carvalho de Melo   perf hists browse...
1866
  			continue;
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1867
1868
  		}
  	}
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1869
1870
1871
1872
  out:
  	ui_browser__hide(&menu->b);
  	return key;
  }
316c7136f   Arnaldo Carvalho de Melo   perf tools: Finis...
1873
  static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
fc24d7c25   Namhyung Kim   perf report: Bypa...
1874
1875
1876
1877
1878
1879
1880
1881
1882
  				 void *entry)
  {
  	struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
  
  	if (symbol_conf.event_group && !perf_evsel__is_group_leader(evsel))
  		return true;
  
  	return false;
  }
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1883
  static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
fc24d7c25   Namhyung Kim   perf report: Bypa...
1884
  					   int nr_entries, const char *help,
68d807586   Namhyung Kim   perf report: Post...
1885
  					   struct hist_browser_timer *hbt,
064f19815   Namhyung Kim   perf report: Add ...
1886
  					   float min_pcnt,
68d807586   Namhyung Kim   perf report: Post...
1887
  					   struct perf_session_env *env)
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1888
1889
1890
1891
1892
1893
1894
1895
  {
  	struct perf_evsel *pos;
  	struct perf_evsel_menu menu = {
  		.b = {
  			.entries    = &evlist->entries,
  			.refresh    = ui_browser__list_head_refresh,
  			.seek	    = ui_browser__list_head_seek,
  			.write	    = perf_evsel_menu__write,
fc24d7c25   Namhyung Kim   perf report: Bypa...
1896
1897
  			.filter	    = filter_group_entries,
  			.nr_entries = nr_entries,
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1898
1899
  			.priv	    = evlist,
  		},
064f19815   Namhyung Kim   perf report: Add ...
1900
  		.min_pcnt = min_pcnt,
68d807586   Namhyung Kim   perf report: Post...
1901
  		.env = env,
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1902
1903
1904
  	};
  
  	ui_helpline__push("Press ESC to exit");
0050f7aa1   Arnaldo Carvalho de Melo   perf evlist: Intr...
1905
  	evlist__for_each(evlist, pos) {
7289f83cc   Arnaldo Carvalho de Melo   perf tools: Move ...
1906
  		const char *ev_name = perf_evsel__name(pos);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1907
1908
1909
1910
  		size_t line_len = strlen(ev_name) + 7;
  
  		if (menu.b.width < line_len)
  			menu.b.width = line_len;
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1911
  	}
fc24d7c25   Namhyung Kim   perf report: Bypa...
1912
  	return perf_evsel_menu__run(&menu, nr_entries, help, hbt);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1913
  }
81cce8de9   Arnaldo Carvalho de Melo   perf browsers: Ad...
1914
  int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
68d807586   Namhyung Kim   perf report: Post...
1915
  				  struct hist_browser_timer *hbt,
064f19815   Namhyung Kim   perf report: Add ...
1916
  				  float min_pcnt,
68d807586   Namhyung Kim   perf report: Post...
1917
  				  struct perf_session_env *env)
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1918
  {
fc24d7c25   Namhyung Kim   perf report: Bypa...
1919
1920
1921
1922
  	int nr_entries = evlist->nr_entries;
  
  single_entry:
  	if (nr_entries == 1) {
9a354cdc2   Arnaldo Carvalho de Melo   perf tools: Use p...
1923
  		struct perf_evsel *first = perf_evlist__first(evlist);
fc24d7c25   Namhyung Kim   perf report: Bypa...
1924
1925
  
  		return perf_evsel__hists_browse(first, nr_entries, help,
dd00d486d   Jiri Olsa   perf hists browse...
1926
  						false, hbt, min_pcnt,
064f19815   Namhyung Kim   perf report: Add ...
1927
  						env);
7f0030b21   Arnaldo Carvalho de Melo   perf report tui: ...
1928
  	}
fc24d7c25   Namhyung Kim   perf report: Bypa...
1929
1930
1931
1932
  	if (symbol_conf.event_group) {
  		struct perf_evsel *pos;
  
  		nr_entries = 0;
0050f7aa1   Arnaldo Carvalho de Melo   perf evlist: Intr...
1933
  		evlist__for_each(evlist, pos) {
fc24d7c25   Namhyung Kim   perf report: Bypa...
1934
1935
  			if (perf_evsel__is_group_leader(pos))
  				nr_entries++;
0050f7aa1   Arnaldo Carvalho de Melo   perf evlist: Intr...
1936
  		}
fc24d7c25   Namhyung Kim   perf report: Bypa...
1937
1938
1939
1940
1941
1942
  
  		if (nr_entries == 1)
  			goto single_entry;
  	}
  
  	return __perf_evlist__tui_browse_hists(evlist, nr_entries, help,
064f19815   Namhyung Kim   perf report: Add ...
1943
  					       hbt, min_pcnt, env);
d1b4f2491   Arnaldo Carvalho de Melo   perf ui: Move his...
1944
  }