blob: 3c1b75c8b9a65e15834ee31c07dabb3f19b5fe4c [file] [log] [blame]
John Kacurdd68ada2009-09-24 18:02:49 +02001#include "sort.h"
Arnaldo Carvalho de Melo8a6c5b22010-07-20 14:42:52 -03002#include "hist.h"
Namhyung Kim4dfced32013-09-13 16:28:57 +09003#include "comm.h"
Namhyung Kim08e71542013-04-03 21:26:19 +09004#include "symbol.h"
John Kacurdd68ada2009-09-24 18:02:49 +02005
6regex_t parent_regex;
Arnaldo Carvalho de Meloedb7c602010-05-17 16:22:41 -03007const char default_parent_pattern[] = "^sys_|^do_page_fault";
8const char *parent_pattern = default_parent_pattern;
9const char default_sort_order[] = "comm,dso,symbol";
10const char *sort_order = default_sort_order;
Greg Priceb21484f2012-12-06 21:48:05 -080011regex_t ignore_callees_regex;
12int have_ignore_callees = 0;
Frederic Weisbeckeraf0a6fa2009-10-22 23:23:22 +020013int sort__need_collapse = 0;
14int sort__has_parent = 0;
Namhyung Kim1af556402012-09-14 17:35:27 +090015int sort__has_sym = 0;
Namhyung Kim55369fc2013-04-01 20:35:20 +090016enum sort_mode sort__mode = SORT_MODE__NORMAL;
Frederic Weisbeckera4fb5812009-10-22 23:23:23 +020017
18enum sort_type sort__first_dimension;
John Kacurdd68ada2009-09-24 18:02:49 +020019
John Kacurdd68ada2009-09-24 18:02:49 +020020LIST_HEAD(hist_entry__sort_list);
21
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030022static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
John Kacurdd68ada2009-09-24 18:02:49 +020023{
24 int n;
25 va_list ap;
26
27 va_start(ap, fmt);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030028 n = vsnprintf(bf, size, fmt, ap);
Jiri Olsa0ca0c132012-09-06 17:46:56 +020029 if (symbol_conf.field_sep && n > 0) {
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030030 char *sep = bf;
John Kacurdd68ada2009-09-24 18:02:49 +020031
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030032 while (1) {
Jiri Olsa0ca0c132012-09-06 17:46:56 +020033 sep = strchr(sep, *symbol_conf.field_sep);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030034 if (sep == NULL)
35 break;
36 *sep = '.';
John Kacurdd68ada2009-09-24 18:02:49 +020037 }
John Kacurdd68ada2009-09-24 18:02:49 +020038 }
39 va_end(ap);
Anton Blanchardb8327962012-03-07 11:42:49 +110040
41 if (n >= (int)size)
42 return size - 1;
John Kacurdd68ada2009-09-24 18:02:49 +020043 return n;
44}
45
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020046static int64_t cmp_null(const void *l, const void *r)
Frederic Weisbecker872a8782011-06-29 03:14:52 +020047{
48 if (!l && !r)
49 return 0;
50 else if (!l)
51 return -1;
52 else
53 return 1;
54}
55
56/* --sort pid */
57
58static int64_t
59sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
60{
Adrian Hunter38051232013-07-04 16:20:31 +030061 return right->thread->tid - left->thread->tid;
Frederic Weisbecker872a8782011-06-29 03:14:52 +020062}
63
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -030064static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030065 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +020066{
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020067 const char *comm = thread__comm_str(he->thread);
Namhyung Kimfb29a332012-12-27 18:11:40 +090068 return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020069 comm ?: "", he->thread->tid);
John Kacurdd68ada2009-09-24 18:02:49 +020070}
71
Frederic Weisbecker872a8782011-06-29 03:14:52 +020072struct sort_entry sort_thread = {
73 .se_header = "Command: Pid",
74 .se_cmp = sort__thread_cmp,
75 .se_snprintf = hist_entry__thread_snprintf,
76 .se_width_idx = HISTC_THREAD,
77};
78
79/* --sort comm */
80
81static int64_t
82sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
83{
Frederic Weisbeckerfedd63d2013-09-11 17:18:09 +020084 /* Compare the addr that should be unique among comm */
Namhyung Kim4dfced32013-09-13 16:28:57 +090085 return comm__str(right->comm) - comm__str(left->comm);
Frederic Weisbecker872a8782011-06-29 03:14:52 +020086}
87
88static int64_t
89sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
90{
Namhyung Kim4dfced32013-09-13 16:28:57 +090091 /* Compare the addr that should be unique among comm */
92 return comm__str(right->comm) - comm__str(left->comm);
Frederic Weisbecker872a8782011-06-29 03:14:52 +020093}
94
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -030095static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030096 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +020097{
Namhyung Kim4dfced32013-09-13 16:28:57 +090098 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm));
John Kacurdd68ada2009-09-24 18:02:49 +020099}
100
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900101struct sort_entry sort_comm = {
102 .se_header = "Command",
103 .se_cmp = sort__comm_cmp,
104 .se_collapse = sort__comm_collapse,
105 .se_snprintf = hist_entry__comm_snprintf,
106 .se_width_idx = HISTC_COMM,
107};
108
109/* --sort dso */
110
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100111static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
John Kacurdd68ada2009-09-24 18:02:49 +0200112{
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100113 struct dso *dso_l = map_l ? map_l->dso : NULL;
114 struct dso *dso_r = map_r ? map_r->dso : NULL;
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300115 const char *dso_name_l, *dso_name_r;
John Kacurdd68ada2009-09-24 18:02:49 +0200116
117 if (!dso_l || !dso_r)
118 return cmp_null(dso_l, dso_r);
119
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300120 if (verbose) {
121 dso_name_l = dso_l->long_name;
122 dso_name_r = dso_r->long_name;
123 } else {
124 dso_name_l = dso_l->short_name;
125 dso_name_r = dso_r->short_name;
126 }
127
128 return strcmp(dso_name_l, dso_name_r);
John Kacurdd68ada2009-09-24 18:02:49 +0200129}
130
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100131static int64_t
132sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
John Kacurdd68ada2009-09-24 18:02:49 +0200133{
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100134 return _sort__dso_cmp(left->ms.map, right->ms.map);
135}
136
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100137static int _hist_entry__dso_snprintf(struct map *map, char *bf,
138 size_t size, unsigned int width)
139{
140 if (map && map->dso) {
141 const char *dso_name = !verbose ? map->dso->short_name :
142 map->dso->long_name;
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300143 return repsep_snprintf(bf, size, "%-*s", width, dso_name);
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300144 }
John Kacurdd68ada2009-09-24 18:02:49 +0200145
Ian Munsie1437a302010-12-06 13:37:04 +1100146 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
John Kacurdd68ada2009-09-24 18:02:49 +0200147}
148
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300149static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100150 size_t size, unsigned int width)
151{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300152 return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100153}
154
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900155struct sort_entry sort_dso = {
156 .se_header = "Shared Object",
157 .se_cmp = sort__dso_cmp,
158 .se_snprintf = hist_entry__dso_snprintf,
159 .se_width_idx = HISTC_DSO,
160};
161
162/* --sort symbol */
163
Namhyung Kim51f27d12013-02-06 14:57:15 +0900164static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900165{
Namhyung Kim51f27d12013-02-06 14:57:15 +0900166 u64 ip_l, ip_r;
167
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900168 if (!sym_l || !sym_r)
169 return cmp_null(sym_l, sym_r);
170
171 if (sym_l == sym_r)
172 return 0;
173
174 ip_l = sym_l->start;
175 ip_r = sym_r->start;
176
177 return (int64_t)(ip_r - ip_l);
178}
179
180static int64_t
181sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
182{
Namhyung Kim09600e02013-10-15 11:01:56 +0900183 int64_t ret;
184
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900185 if (!left->ms.sym && !right->ms.sym)
186 return right->level - left->level;
187
Namhyung Kim09600e02013-10-15 11:01:56 +0900188 /*
189 * comparing symbol address alone is not enough since it's a
190 * relative address within a dso.
191 */
192 ret = sort__dso_cmp(left, right);
193 if (ret != 0)
194 return ret;
195
Namhyung Kim51f27d12013-02-06 14:57:15 +0900196 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900197}
198
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100199static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
200 u64 ip, char level, char *bf, size_t size,
Namhyung Kim43355522012-12-27 18:11:39 +0900201 unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100202{
203 size_t ret = 0;
204
205 if (verbose) {
206 char o = map ? dso__symtab_origin(map->dso) : '!';
207 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
Namhyung Kimded19d52013-04-01 20:35:19 +0900208 BITS_PER_LONG / 4 + 2, ip, o);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100209 }
210
211 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
Stephane Eranian98a3b322013-01-24 16:10:35 +0100212 if (sym && map) {
213 if (map->type == MAP__VARIABLE) {
214 ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
215 ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
Namhyung Kim62667742013-01-24 16:10:42 +0100216 ip - map->unmap_ip(map, sym->start));
Stephane Eranian98a3b322013-01-24 16:10:35 +0100217 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
218 width - ret, "");
219 } else {
220 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
221 width - ret,
222 sym->name);
223 }
224 } else {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100225 size_t len = BITS_PER_LONG / 4;
226 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
227 len, ip);
228 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
229 width - ret, "");
230 }
231
232 return ret;
233}
234
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300235static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900236 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100237{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300238 return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
239 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100240}
John Kacurdd68ada2009-09-24 18:02:49 +0200241
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200242struct sort_entry sort_sym = {
243 .se_header = "Symbol",
244 .se_cmp = sort__sym_cmp,
245 .se_snprintf = hist_entry__sym_snprintf,
246 .se_width_idx = HISTC_SYMBOL,
247};
John Kacurdd68ada2009-09-24 18:02:49 +0200248
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300249/* --sort srcline */
250
251static int64_t
252sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
253{
Namhyung Kim4adcc432013-09-11 14:09:33 +0900254 if (!left->srcline) {
255 if (!left->ms.map)
256 left->srcline = SRCLINE_UNKNOWN;
257 else {
258 struct map *map = left->ms.map;
259 left->srcline = get_srcline(map->dso,
260 map__rip_2objdump(map, left->ip));
261 }
262 }
263 if (!right->srcline) {
264 if (!right->ms.map)
265 right->srcline = SRCLINE_UNKNOWN;
266 else {
267 struct map *map = right->ms.map;
268 right->srcline = get_srcline(map->dso,
269 map__rip_2objdump(map, right->ip));
270 }
271 }
272 return strcmp(left->srcline, right->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300273}
274
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300275static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300276 size_t size,
277 unsigned int width __maybe_unused)
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300278{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300279 return repsep_snprintf(bf, size, "%s", he->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300280}
281
282struct sort_entry sort_srcline = {
283 .se_header = "Source:Line",
284 .se_cmp = sort__srcline_cmp,
285 .se_snprintf = hist_entry__srcline_snprintf,
286 .se_width_idx = HISTC_SRCLINE,
287};
288
John Kacurdd68ada2009-09-24 18:02:49 +0200289/* --sort parent */
290
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200291static int64_t
John Kacurdd68ada2009-09-24 18:02:49 +0200292sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
293{
294 struct symbol *sym_l = left->parent;
295 struct symbol *sym_r = right->parent;
296
297 if (!sym_l || !sym_r)
298 return cmp_null(sym_l, sym_r);
299
300 return strcmp(sym_l->name, sym_r->name);
301}
302
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300303static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300304 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +0200305{
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300306 return repsep_snprintf(bf, size, "%-*s", width,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300307 he->parent ? he->parent->name : "[other]");
John Kacurdd68ada2009-09-24 18:02:49 +0200308}
309
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200310struct sort_entry sort_parent = {
311 .se_header = "Parent symbol",
312 .se_cmp = sort__parent_cmp,
313 .se_snprintf = hist_entry__parent_snprintf,
314 .se_width_idx = HISTC_PARENT,
315};
316
Arun Sharmaf60f3592010-06-04 11:27:10 -0300317/* --sort cpu */
318
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200319static int64_t
Arun Sharmaf60f3592010-06-04 11:27:10 -0300320sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
321{
322 return right->cpu - left->cpu;
323}
324
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300325static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
326 size_t size, unsigned int width)
Arun Sharmaf60f3592010-06-04 11:27:10 -0300327{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300328 return repsep_snprintf(bf, size, "%*d", width, he->cpu);
Arun Sharmaf60f3592010-06-04 11:27:10 -0300329}
330
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200331struct sort_entry sort_cpu = {
332 .se_header = "CPU",
333 .se_cmp = sort__cpu_cmp,
334 .se_snprintf = hist_entry__cpu_snprintf,
335 .se_width_idx = HISTC_CPU,
336};
337
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900338/* sort keys for branch stacks */
339
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100340static int64_t
341sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
342{
343 return _sort__dso_cmp(left->branch_info->from.map,
344 right->branch_info->from.map);
345}
346
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300347static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100348 size_t size, unsigned int width)
349{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300350 return _hist_entry__dso_snprintf(he->branch_info->from.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100351 bf, size, width);
352}
353
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100354static int64_t
355sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
356{
357 return _sort__dso_cmp(left->branch_info->to.map,
358 right->branch_info->to.map);
359}
360
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300361static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100362 size_t size, unsigned int width)
363{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300364 return _hist_entry__dso_snprintf(he->branch_info->to.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100365 bf, size, width);
366}
367
368static int64_t
369sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
370{
371 struct addr_map_symbol *from_l = &left->branch_info->from;
372 struct addr_map_symbol *from_r = &right->branch_info->from;
373
374 if (!from_l->sym && !from_r->sym)
375 return right->level - left->level;
376
Namhyung Kim51f27d12013-02-06 14:57:15 +0900377 return _sort__sym_cmp(from_l->sym, from_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100378}
379
380static int64_t
381sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
382{
383 struct addr_map_symbol *to_l = &left->branch_info->to;
384 struct addr_map_symbol *to_r = &right->branch_info->to;
385
386 if (!to_l->sym && !to_r->sym)
387 return right->level - left->level;
388
Namhyung Kim51f27d12013-02-06 14:57:15 +0900389 return _sort__sym_cmp(to_l->sym, to_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100390}
391
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300392static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900393 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100394{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300395 struct addr_map_symbol *from = &he->branch_info->from;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100396 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300397 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100398
399}
400
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300401static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900402 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100403{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300404 struct addr_map_symbol *to = &he->branch_info->to;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100405 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300406 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100407
408}
409
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900410struct sort_entry sort_dso_from = {
411 .se_header = "Source Shared Object",
412 .se_cmp = sort__dso_from_cmp,
413 .se_snprintf = hist_entry__dso_from_snprintf,
414 .se_width_idx = HISTC_DSO_FROM,
415};
416
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100417struct sort_entry sort_dso_to = {
418 .se_header = "Target Shared Object",
419 .se_cmp = sort__dso_to_cmp,
420 .se_snprintf = hist_entry__dso_to_snprintf,
421 .se_width_idx = HISTC_DSO_TO,
422};
423
424struct sort_entry sort_sym_from = {
425 .se_header = "Source Symbol",
426 .se_cmp = sort__sym_from_cmp,
427 .se_snprintf = hist_entry__sym_from_snprintf,
428 .se_width_idx = HISTC_SYMBOL_FROM,
429};
430
431struct sort_entry sort_sym_to = {
432 .se_header = "Target Symbol",
433 .se_cmp = sort__sym_to_cmp,
434 .se_snprintf = hist_entry__sym_to_snprintf,
435 .se_width_idx = HISTC_SYMBOL_TO,
436};
437
438static int64_t
439sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
440{
441 const unsigned char mp = left->branch_info->flags.mispred !=
442 right->branch_info->flags.mispred;
443 const unsigned char p = left->branch_info->flags.predicted !=
444 right->branch_info->flags.predicted;
445
446 return mp || p;
447}
448
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300449static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100450 size_t size, unsigned int width){
451 static const char *out = "N/A";
452
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300453 if (he->branch_info->flags.predicted)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100454 out = "N";
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300455 else if (he->branch_info->flags.mispred)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100456 out = "Y";
457
458 return repsep_snprintf(bf, size, "%-*s", width, out);
459}
460
Stephane Eranian98a3b322013-01-24 16:10:35 +0100461/* --sort daddr_sym */
462static int64_t
463sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
464{
465 uint64_t l = 0, r = 0;
466
467 if (left->mem_info)
468 l = left->mem_info->daddr.addr;
469 if (right->mem_info)
470 r = right->mem_info->daddr.addr;
471
472 return (int64_t)(r - l);
473}
474
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300475static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100476 size_t size, unsigned int width)
477{
478 uint64_t addr = 0;
479 struct map *map = NULL;
480 struct symbol *sym = NULL;
481
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300482 if (he->mem_info) {
483 addr = he->mem_info->daddr.addr;
484 map = he->mem_info->daddr.map;
485 sym = he->mem_info->daddr.sym;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100486 }
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300487 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100488 width);
489}
490
491static int64_t
492sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
493{
494 struct map *map_l = NULL;
495 struct map *map_r = NULL;
496
497 if (left->mem_info)
498 map_l = left->mem_info->daddr.map;
499 if (right->mem_info)
500 map_r = right->mem_info->daddr.map;
501
502 return _sort__dso_cmp(map_l, map_r);
503}
504
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300505static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100506 size_t size, unsigned int width)
507{
508 struct map *map = NULL;
509
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300510 if (he->mem_info)
511 map = he->mem_info->daddr.map;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100512
513 return _hist_entry__dso_snprintf(map, bf, size, width);
514}
515
516static int64_t
517sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
518{
519 union perf_mem_data_src data_src_l;
520 union perf_mem_data_src data_src_r;
521
522 if (left->mem_info)
523 data_src_l = left->mem_info->data_src;
524 else
525 data_src_l.mem_lock = PERF_MEM_LOCK_NA;
526
527 if (right->mem_info)
528 data_src_r = right->mem_info->data_src;
529 else
530 data_src_r.mem_lock = PERF_MEM_LOCK_NA;
531
532 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
533}
534
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300535static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100536 size_t size, unsigned int width)
537{
538 const char *out;
539 u64 mask = PERF_MEM_LOCK_NA;
540
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300541 if (he->mem_info)
542 mask = he->mem_info->data_src.mem_lock;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100543
544 if (mask & PERF_MEM_LOCK_NA)
545 out = "N/A";
546 else if (mask & PERF_MEM_LOCK_LOCKED)
547 out = "Yes";
548 else
549 out = "No";
550
551 return repsep_snprintf(bf, size, "%-*s", width, out);
552}
553
554static int64_t
555sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
556{
557 union perf_mem_data_src data_src_l;
558 union perf_mem_data_src data_src_r;
559
560 if (left->mem_info)
561 data_src_l = left->mem_info->data_src;
562 else
563 data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
564
565 if (right->mem_info)
566 data_src_r = right->mem_info->data_src;
567 else
568 data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
569
570 return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
571}
572
573static const char * const tlb_access[] = {
574 "N/A",
575 "HIT",
576 "MISS",
577 "L1",
578 "L2",
579 "Walker",
580 "Fault",
581};
582#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
583
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300584static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100585 size_t size, unsigned int width)
586{
587 char out[64];
588 size_t sz = sizeof(out) - 1; /* -1 for null termination */
589 size_t l = 0, i;
590 u64 m = PERF_MEM_TLB_NA;
591 u64 hit, miss;
592
593 out[0] = '\0';
594
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300595 if (he->mem_info)
596 m = he->mem_info->data_src.mem_dtlb;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100597
598 hit = m & PERF_MEM_TLB_HIT;
599 miss = m & PERF_MEM_TLB_MISS;
600
601 /* already taken care of */
602 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
603
604 for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
605 if (!(m & 0x1))
606 continue;
607 if (l) {
608 strcat(out, " or ");
609 l += 4;
610 }
611 strncat(out, tlb_access[i], sz - l);
612 l += strlen(tlb_access[i]);
613 }
614 if (*out == '\0')
615 strcpy(out, "N/A");
616 if (hit)
617 strncat(out, " hit", sz - l);
618 if (miss)
619 strncat(out, " miss", sz - l);
620
621 return repsep_snprintf(bf, size, "%-*s", width, out);
622}
623
624static int64_t
625sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
626{
627 union perf_mem_data_src data_src_l;
628 union perf_mem_data_src data_src_r;
629
630 if (left->mem_info)
631 data_src_l = left->mem_info->data_src;
632 else
633 data_src_l.mem_lvl = PERF_MEM_LVL_NA;
634
635 if (right->mem_info)
636 data_src_r = right->mem_info->data_src;
637 else
638 data_src_r.mem_lvl = PERF_MEM_LVL_NA;
639
640 return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
641}
642
643static const char * const mem_lvl[] = {
644 "N/A",
645 "HIT",
646 "MISS",
647 "L1",
648 "LFB",
649 "L2",
650 "L3",
651 "Local RAM",
652 "Remote RAM (1 hop)",
653 "Remote RAM (2 hops)",
654 "Remote Cache (1 hop)",
655 "Remote Cache (2 hops)",
656 "I/O",
657 "Uncached",
658};
659#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
660
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300661static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100662 size_t size, unsigned int width)
663{
664 char out[64];
665 size_t sz = sizeof(out) - 1; /* -1 for null termination */
666 size_t i, l = 0;
667 u64 m = PERF_MEM_LVL_NA;
668 u64 hit, miss;
669
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300670 if (he->mem_info)
671 m = he->mem_info->data_src.mem_lvl;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100672
673 out[0] = '\0';
674
675 hit = m & PERF_MEM_LVL_HIT;
676 miss = m & PERF_MEM_LVL_MISS;
677
678 /* already taken care of */
679 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
680
681 for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
682 if (!(m & 0x1))
683 continue;
684 if (l) {
685 strcat(out, " or ");
686 l += 4;
687 }
688 strncat(out, mem_lvl[i], sz - l);
689 l += strlen(mem_lvl[i]);
690 }
691 if (*out == '\0')
692 strcpy(out, "N/A");
693 if (hit)
694 strncat(out, " hit", sz - l);
695 if (miss)
696 strncat(out, " miss", sz - l);
697
698 return repsep_snprintf(bf, size, "%-*s", width, out);
699}
700
701static int64_t
702sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
703{
704 union perf_mem_data_src data_src_l;
705 union perf_mem_data_src data_src_r;
706
707 if (left->mem_info)
708 data_src_l = left->mem_info->data_src;
709 else
710 data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
711
712 if (right->mem_info)
713 data_src_r = right->mem_info->data_src;
714 else
715 data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
716
717 return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
718}
719
720static const char * const snoop_access[] = {
721 "N/A",
722 "None",
723 "Miss",
724 "Hit",
725 "HitM",
726};
727#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
728
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300729static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100730 size_t size, unsigned int width)
731{
732 char out[64];
733 size_t sz = sizeof(out) - 1; /* -1 for null termination */
734 size_t i, l = 0;
735 u64 m = PERF_MEM_SNOOP_NA;
736
737 out[0] = '\0';
738
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300739 if (he->mem_info)
740 m = he->mem_info->data_src.mem_snoop;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100741
742 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
743 if (!(m & 0x1))
744 continue;
745 if (l) {
746 strcat(out, " or ");
747 l += 4;
748 }
749 strncat(out, snoop_access[i], sz - l);
750 l += strlen(snoop_access[i]);
751 }
752
753 if (*out == '\0')
754 strcpy(out, "N/A");
755
756 return repsep_snprintf(bf, size, "%-*s", width, out);
757}
758
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100759struct sort_entry sort_mispredict = {
760 .se_header = "Branch Mispredicted",
761 .se_cmp = sort__mispredict_cmp,
762 .se_snprintf = hist_entry__mispredict_snprintf,
763 .se_width_idx = HISTC_MISPREDICT,
764};
765
Andi Kleen05484292013-01-24 16:10:29 +0100766static u64 he_weight(struct hist_entry *he)
767{
768 return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
769}
770
771static int64_t
772sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
773{
774 return he_weight(left) - he_weight(right);
775}
776
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300777static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100778 size_t size, unsigned int width)
779{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300780 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
Andi Kleen05484292013-01-24 16:10:29 +0100781}
782
783struct sort_entry sort_local_weight = {
784 .se_header = "Local Weight",
785 .se_cmp = sort__local_weight_cmp,
786 .se_snprintf = hist_entry__local_weight_snprintf,
787 .se_width_idx = HISTC_LOCAL_WEIGHT,
788};
789
790static int64_t
791sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
792{
793 return left->stat.weight - right->stat.weight;
794}
795
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300796static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100797 size_t size, unsigned int width)
798{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300799 return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
Andi Kleen05484292013-01-24 16:10:29 +0100800}
801
802struct sort_entry sort_global_weight = {
803 .se_header = "Weight",
804 .se_cmp = sort__global_weight_cmp,
805 .se_snprintf = hist_entry__global_weight_snprintf,
806 .se_width_idx = HISTC_GLOBAL_WEIGHT,
807};
808
Stephane Eranian98a3b322013-01-24 16:10:35 +0100809struct sort_entry sort_mem_daddr_sym = {
810 .se_header = "Data Symbol",
811 .se_cmp = sort__daddr_cmp,
812 .se_snprintf = hist_entry__daddr_snprintf,
813 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
814};
815
816struct sort_entry sort_mem_daddr_dso = {
817 .se_header = "Data Object",
818 .se_cmp = sort__dso_daddr_cmp,
819 .se_snprintf = hist_entry__dso_daddr_snprintf,
820 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
821};
822
823struct sort_entry sort_mem_locked = {
824 .se_header = "Locked",
825 .se_cmp = sort__locked_cmp,
826 .se_snprintf = hist_entry__locked_snprintf,
827 .se_width_idx = HISTC_MEM_LOCKED,
828};
829
830struct sort_entry sort_mem_tlb = {
831 .se_header = "TLB access",
832 .se_cmp = sort__tlb_cmp,
833 .se_snprintf = hist_entry__tlb_snprintf,
834 .se_width_idx = HISTC_MEM_TLB,
835};
836
837struct sort_entry sort_mem_lvl = {
838 .se_header = "Memory access",
839 .se_cmp = sort__lvl_cmp,
840 .se_snprintf = hist_entry__lvl_snprintf,
841 .se_width_idx = HISTC_MEM_LVL,
842};
843
844struct sort_entry sort_mem_snoop = {
845 .se_header = "Snoop",
846 .se_cmp = sort__snoop_cmp,
847 .se_snprintf = hist_entry__snoop_snprintf,
848 .se_width_idx = HISTC_MEM_SNOOP,
849};
850
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700851static int64_t
852sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
853{
854 return left->branch_info->flags.abort !=
855 right->branch_info->flags.abort;
856}
857
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300858static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700859 size_t size, unsigned int width)
860{
861 static const char *out = ".";
862
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300863 if (he->branch_info->flags.abort)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700864 out = "A";
865 return repsep_snprintf(bf, size, "%-*s", width, out);
866}
867
868struct sort_entry sort_abort = {
869 .se_header = "Transaction abort",
870 .se_cmp = sort__abort_cmp,
871 .se_snprintf = hist_entry__abort_snprintf,
872 .se_width_idx = HISTC_ABORT,
873};
874
875static int64_t
876sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
877{
878 return left->branch_info->flags.in_tx !=
879 right->branch_info->flags.in_tx;
880}
881
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300882static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700883 size_t size, unsigned int width)
884{
885 static const char *out = ".";
886
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300887 if (he->branch_info->flags.in_tx)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700888 out = "T";
889
890 return repsep_snprintf(bf, size, "%-*s", width, out);
891}
892
893struct sort_entry sort_in_tx = {
894 .se_header = "Branch in transaction",
895 .se_cmp = sort__in_tx_cmp,
896 .se_snprintf = hist_entry__in_tx_snprintf,
897 .se_width_idx = HISTC_IN_TX,
898};
899
Andi Kleen475eeab2013-09-20 07:40:43 -0700900static int64_t
901sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
902{
903 return left->transaction - right->transaction;
904}
905
906static inline char *add_str(char *p, const char *str)
907{
908 strcpy(p, str);
909 return p + strlen(str);
910}
911
912static struct txbit {
913 unsigned flag;
914 const char *name;
915 int skip_for_len;
916} txbits[] = {
917 { PERF_TXN_ELISION, "EL ", 0 },
918 { PERF_TXN_TRANSACTION, "TX ", 1 },
919 { PERF_TXN_SYNC, "SYNC ", 1 },
920 { PERF_TXN_ASYNC, "ASYNC ", 0 },
921 { PERF_TXN_RETRY, "RETRY ", 0 },
922 { PERF_TXN_CONFLICT, "CON ", 0 },
923 { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
924 { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
925 { 0, NULL, 0 }
926};
927
928int hist_entry__transaction_len(void)
929{
930 int i;
931 int len = 0;
932
933 for (i = 0; txbits[i].name; i++) {
934 if (!txbits[i].skip_for_len)
935 len += strlen(txbits[i].name);
936 }
937 len += 4; /* :XX<space> */
938 return len;
939}
940
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300941static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
Andi Kleen475eeab2013-09-20 07:40:43 -0700942 size_t size, unsigned int width)
943{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300944 u64 t = he->transaction;
Andi Kleen475eeab2013-09-20 07:40:43 -0700945 char buf[128];
946 char *p = buf;
947 int i;
948
949 buf[0] = 0;
950 for (i = 0; txbits[i].name; i++)
951 if (txbits[i].flag & t)
952 p = add_str(p, txbits[i].name);
953 if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
954 p = add_str(p, "NEITHER ");
955 if (t & PERF_TXN_ABORT_MASK) {
956 sprintf(p, ":%" PRIx64,
957 (t & PERF_TXN_ABORT_MASK) >>
958 PERF_TXN_ABORT_SHIFT);
959 p += strlen(p);
960 }
961
962 return repsep_snprintf(bf, size, "%-*s", width, buf);
963}
964
965struct sort_entry sort_transaction = {
966 .se_header = "Transaction ",
967 .se_cmp = sort__transaction_cmp,
968 .se_snprintf = hist_entry__transaction_snprintf,
969 .se_width_idx = HISTC_TRANSACTION,
970};
971
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200972struct sort_dimension {
973 const char *name;
974 struct sort_entry *entry;
975 int taken;
976};
977
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100978#define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
979
Namhyung Kimfc5871e2012-12-27 18:11:46 +0900980static struct sort_dimension common_sort_dimensions[] = {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100981 DIM(SORT_PID, "pid", sort_thread),
982 DIM(SORT_COMM, "comm", sort_comm),
983 DIM(SORT_DSO, "dso", sort_dso),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100984 DIM(SORT_SYM, "symbol", sort_sym),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100985 DIM(SORT_PARENT, "parent", sort_parent),
986 DIM(SORT_CPU, "cpu", sort_cpu),
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300987 DIM(SORT_SRCLINE, "srcline", sort_srcline),
Andi Kleenf9ea55d2013-07-18 15:58:53 -0700988 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
989 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
Andi Kleen475eeab2013-09-20 07:40:43 -0700990 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200991};
992
Namhyung Kimfc5871e2012-12-27 18:11:46 +0900993#undef DIM
994
995#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
996
997static struct sort_dimension bstack_sort_dimensions[] = {
998 DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
999 DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
1000 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
1001 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
1002 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001003 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1004 DIM(SORT_ABORT, "abort", sort_abort),
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001005};
1006
1007#undef DIM
1008
Namhyung Kimafab87b2013-04-03 21:26:11 +09001009#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
1010
1011static struct sort_dimension memory_sort_dimensions[] = {
Namhyung Kimafab87b2013-04-03 21:26:11 +09001012 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1013 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1014 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1015 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1016 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1017 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1018};
1019
1020#undef DIM
1021
Namhyung Kim2f532d092013-04-03 21:26:10 +09001022static void __sort_dimension__add(struct sort_dimension *sd, enum sort_type idx)
1023{
1024 if (sd->taken)
1025 return;
1026
1027 if (sd->entry->se_collapse)
1028 sort__need_collapse = 1;
1029
1030 if (list_empty(&hist_entry__sort_list))
1031 sort__first_dimension = idx;
1032
1033 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
1034 sd->taken = 1;
1035}
1036
John Kacurdd68ada2009-09-24 18:02:49 +02001037int sort_dimension__add(const char *tok)
1038{
1039 unsigned int i;
1040
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001041 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1042 struct sort_dimension *sd = &common_sort_dimensions[i];
John Kacurdd68ada2009-09-24 18:02:49 +02001043
John Kacurdd68ada2009-09-24 18:02:49 +02001044 if (strncasecmp(tok, sd->name, strlen(tok)))
1045 continue;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001046
John Kacurdd68ada2009-09-24 18:02:49 +02001047 if (sd->entry == &sort_parent) {
1048 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
1049 if (ret) {
1050 char err[BUFSIZ];
1051
1052 regerror(ret, &parent_regex, err, sizeof(err));
Arnaldo Carvalho de Melo2aefa4f2010-04-02 12:30:57 -03001053 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
1054 return -EINVAL;
John Kacurdd68ada2009-09-24 18:02:49 +02001055 }
1056 sort__has_parent = 1;
Namhyung Kim930477b2013-04-05 10:26:36 +09001057 } else if (sd->entry == &sort_sym) {
Namhyung Kim1af556402012-09-14 17:35:27 +09001058 sort__has_sym = 1;
John Kacurdd68ada2009-09-24 18:02:49 +02001059 }
1060
Namhyung Kim2f532d092013-04-03 21:26:10 +09001061 __sort_dimension__add(sd, i);
John Kacurdd68ada2009-09-24 18:02:49 +02001062 return 0;
1063 }
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001064
1065 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1066 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1067
1068 if (strncasecmp(tok, sd->name, strlen(tok)))
1069 continue;
1070
Namhyung Kim55369fc2013-04-01 20:35:20 +09001071 if (sort__mode != SORT_MODE__BRANCH)
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001072 return -EINVAL;
1073
1074 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
1075 sort__has_sym = 1;
1076
Namhyung Kim2f532d092013-04-03 21:26:10 +09001077 __sort_dimension__add(sd, i + __SORT_BRANCH_STACK);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001078 return 0;
1079 }
1080
Namhyung Kimafab87b2013-04-03 21:26:11 +09001081 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1082 struct sort_dimension *sd = &memory_sort_dimensions[i];
1083
1084 if (strncasecmp(tok, sd->name, strlen(tok)))
1085 continue;
1086
1087 if (sort__mode != SORT_MODE__MEMORY)
1088 return -EINVAL;
1089
1090 if (sd->entry == &sort_mem_daddr_sym)
1091 sort__has_sym = 1;
1092
1093 __sort_dimension__add(sd, i + __SORT_MEMORY_MODE);
1094 return 0;
1095 }
1096
John Kacurdd68ada2009-09-24 18:02:49 +02001097 return -ESRCH;
1098}
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001099
Namhyung Kim55309982013-02-06 14:57:16 +09001100int setup_sorting(void)
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001101{
1102 char *tmp, *tok, *str = strdup(sort_order);
Namhyung Kim55309982013-02-06 14:57:16 +09001103 int ret = 0;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001104
Namhyung Kim5936f542013-02-06 14:57:17 +09001105 if (str == NULL) {
1106 error("Not enough memory to setup sort keys");
1107 return -ENOMEM;
1108 }
1109
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001110 for (tok = strtok_r(str, ", ", &tmp);
1111 tok; tok = strtok_r(NULL, ", ", &tmp)) {
Namhyung Kim55309982013-02-06 14:57:16 +09001112 ret = sort_dimension__add(tok);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001113 if (ret == -EINVAL) {
1114 error("Invalid --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001115 break;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001116 } else if (ret == -ESRCH) {
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001117 error("Unknown --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001118 break;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001119 }
1120 }
1121
1122 free(str);
Namhyung Kim55309982013-02-06 14:57:16 +09001123 return ret;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001124}
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001125
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001126static void sort_entry__setup_elide(struct sort_entry *se,
Namhyung Kim08e71542013-04-03 21:26:19 +09001127 struct strlist *list,
1128 const char *list_name, FILE *fp)
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001129{
1130 if (list && strlist__nr_entries(list) == 1) {
1131 if (fp != NULL)
1132 fprintf(fp, "# %s: %s\n", list_name,
1133 strlist__entry(list, 0)->s);
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001134 se->elide = true;
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001135 }
1136}
Namhyung Kim08e71542013-04-03 21:26:19 +09001137
1138void sort__setup_elide(FILE *output)
1139{
1140 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1141 "dso", output);
1142 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list,
1143 "comm", output);
1144 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list,
1145 "symbol", output);
1146
1147 if (sort__mode == SORT_MODE__BRANCH) {
1148 sort_entry__setup_elide(&sort_dso_from,
1149 symbol_conf.dso_from_list,
1150 "dso_from", output);
1151 sort_entry__setup_elide(&sort_dso_to,
1152 symbol_conf.dso_to_list,
1153 "dso_to", output);
1154 sort_entry__setup_elide(&sort_sym_from,
1155 symbol_conf.sym_from_list,
1156 "sym_from", output);
1157 sort_entry__setup_elide(&sort_sym_to,
1158 symbol_conf.sym_to_list,
1159 "sym_to", output);
1160 } else if (sort__mode == SORT_MODE__MEMORY) {
1161 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1162 "symbol_daddr", output);
1163 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1164 "dso_daddr", output);
1165 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1166 "mem", output);
1167 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1168 "local_weight", output);
1169 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1170 "tlb", output);
1171 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1172 "snoop", output);
1173 }
1174
1175}