blob: 68a4fd2f505e65b0b9fbc58e0e1478bdcc1b7e2b [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 Kim2037be52013-12-18 14:21:09 +0900164static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
165{
166 return (int64_t)(right_ip - left_ip);
167}
168
Namhyung Kim51f27d12013-02-06 14:57:15 +0900169static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900170{
Namhyung Kim51f27d12013-02-06 14:57:15 +0900171 u64 ip_l, ip_r;
172
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900173 if (!sym_l || !sym_r)
174 return cmp_null(sym_l, sym_r);
175
176 if (sym_l == sym_r)
177 return 0;
178
179 ip_l = sym_l->start;
180 ip_r = sym_r->start;
181
182 return (int64_t)(ip_r - ip_l);
183}
184
185static int64_t
186sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
187{
Namhyung Kim09600e02013-10-15 11:01:56 +0900188 int64_t ret;
189
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900190 if (!left->ms.sym && !right->ms.sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900191 return _sort__addr_cmp(left->ip, right->ip);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900192
Namhyung Kim09600e02013-10-15 11:01:56 +0900193 /*
194 * comparing symbol address alone is not enough since it's a
195 * relative address within a dso.
196 */
197 ret = sort__dso_cmp(left, right);
198 if (ret != 0)
199 return ret;
200
Namhyung Kim51f27d12013-02-06 14:57:15 +0900201 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900202}
203
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100204static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
205 u64 ip, char level, char *bf, size_t size,
Namhyung Kim43355522012-12-27 18:11:39 +0900206 unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100207{
208 size_t ret = 0;
209
210 if (verbose) {
211 char o = map ? dso__symtab_origin(map->dso) : '!';
212 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
Namhyung Kimded19d52013-04-01 20:35:19 +0900213 BITS_PER_LONG / 4 + 2, ip, o);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100214 }
215
216 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
Stephane Eranian98a3b322013-01-24 16:10:35 +0100217 if (sym && map) {
218 if (map->type == MAP__VARIABLE) {
219 ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
220 ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
Namhyung Kim62667742013-01-24 16:10:42 +0100221 ip - map->unmap_ip(map, sym->start));
Stephane Eranian98a3b322013-01-24 16:10:35 +0100222 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
223 width - ret, "");
224 } else {
225 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
226 width - ret,
227 sym->name);
228 }
229 } else {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100230 size_t len = BITS_PER_LONG / 4;
231 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
232 len, ip);
233 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
234 width - ret, "");
235 }
236
237 return ret;
238}
239
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300240static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900241 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100242{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300243 return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
244 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100245}
John Kacurdd68ada2009-09-24 18:02:49 +0200246
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200247struct sort_entry sort_sym = {
248 .se_header = "Symbol",
249 .se_cmp = sort__sym_cmp,
250 .se_snprintf = hist_entry__sym_snprintf,
251 .se_width_idx = HISTC_SYMBOL,
252};
John Kacurdd68ada2009-09-24 18:02:49 +0200253
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300254/* --sort srcline */
255
256static int64_t
257sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
258{
Namhyung Kim4adcc432013-09-11 14:09:33 +0900259 if (!left->srcline) {
260 if (!left->ms.map)
261 left->srcline = SRCLINE_UNKNOWN;
262 else {
263 struct map *map = left->ms.map;
264 left->srcline = get_srcline(map->dso,
265 map__rip_2objdump(map, left->ip));
266 }
267 }
268 if (!right->srcline) {
269 if (!right->ms.map)
270 right->srcline = SRCLINE_UNKNOWN;
271 else {
272 struct map *map = right->ms.map;
273 right->srcline = get_srcline(map->dso,
274 map__rip_2objdump(map, right->ip));
275 }
276 }
277 return strcmp(left->srcline, right->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300278}
279
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300280static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300281 size_t size,
282 unsigned int width __maybe_unused)
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300283{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300284 return repsep_snprintf(bf, size, "%s", he->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300285}
286
287struct sort_entry sort_srcline = {
288 .se_header = "Source:Line",
289 .se_cmp = sort__srcline_cmp,
290 .se_snprintf = hist_entry__srcline_snprintf,
291 .se_width_idx = HISTC_SRCLINE,
292};
293
John Kacurdd68ada2009-09-24 18:02:49 +0200294/* --sort parent */
295
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200296static int64_t
John Kacurdd68ada2009-09-24 18:02:49 +0200297sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
298{
299 struct symbol *sym_l = left->parent;
300 struct symbol *sym_r = right->parent;
301
302 if (!sym_l || !sym_r)
303 return cmp_null(sym_l, sym_r);
304
305 return strcmp(sym_l->name, sym_r->name);
306}
307
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300308static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300309 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +0200310{
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300311 return repsep_snprintf(bf, size, "%-*s", width,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300312 he->parent ? he->parent->name : "[other]");
John Kacurdd68ada2009-09-24 18:02:49 +0200313}
314
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200315struct sort_entry sort_parent = {
316 .se_header = "Parent symbol",
317 .se_cmp = sort__parent_cmp,
318 .se_snprintf = hist_entry__parent_snprintf,
319 .se_width_idx = HISTC_PARENT,
320};
321
Arun Sharmaf60f3592010-06-04 11:27:10 -0300322/* --sort cpu */
323
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200324static int64_t
Arun Sharmaf60f3592010-06-04 11:27:10 -0300325sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
326{
327 return right->cpu - left->cpu;
328}
329
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300330static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
331 size_t size, unsigned int width)
Arun Sharmaf60f3592010-06-04 11:27:10 -0300332{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300333 return repsep_snprintf(bf, size, "%*d", width, he->cpu);
Arun Sharmaf60f3592010-06-04 11:27:10 -0300334}
335
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200336struct sort_entry sort_cpu = {
337 .se_header = "CPU",
338 .se_cmp = sort__cpu_cmp,
339 .se_snprintf = hist_entry__cpu_snprintf,
340 .se_width_idx = HISTC_CPU,
341};
342
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900343/* sort keys for branch stacks */
344
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100345static int64_t
346sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
347{
348 return _sort__dso_cmp(left->branch_info->from.map,
349 right->branch_info->from.map);
350}
351
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300352static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100353 size_t size, unsigned int width)
354{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300355 return _hist_entry__dso_snprintf(he->branch_info->from.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100356 bf, size, width);
357}
358
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100359static int64_t
360sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
361{
362 return _sort__dso_cmp(left->branch_info->to.map,
363 right->branch_info->to.map);
364}
365
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300366static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100367 size_t size, unsigned int width)
368{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300369 return _hist_entry__dso_snprintf(he->branch_info->to.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100370 bf, size, width);
371}
372
373static int64_t
374sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
375{
376 struct addr_map_symbol *from_l = &left->branch_info->from;
377 struct addr_map_symbol *from_r = &right->branch_info->from;
378
379 if (!from_l->sym && !from_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900380 return _sort__addr_cmp(from_l->addr, from_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100381
Namhyung Kim51f27d12013-02-06 14:57:15 +0900382 return _sort__sym_cmp(from_l->sym, from_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100383}
384
385static int64_t
386sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
387{
388 struct addr_map_symbol *to_l = &left->branch_info->to;
389 struct addr_map_symbol *to_r = &right->branch_info->to;
390
391 if (!to_l->sym && !to_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900392 return _sort__addr_cmp(to_l->addr, to_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100393
Namhyung Kim51f27d12013-02-06 14:57:15 +0900394 return _sort__sym_cmp(to_l->sym, to_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100395}
396
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300397static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900398 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100399{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300400 struct addr_map_symbol *from = &he->branch_info->from;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100401 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300402 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100403
404}
405
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300406static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900407 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100408{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300409 struct addr_map_symbol *to = &he->branch_info->to;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100410 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300411 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100412
413}
414
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900415struct sort_entry sort_dso_from = {
416 .se_header = "Source Shared Object",
417 .se_cmp = sort__dso_from_cmp,
418 .se_snprintf = hist_entry__dso_from_snprintf,
419 .se_width_idx = HISTC_DSO_FROM,
420};
421
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100422struct sort_entry sort_dso_to = {
423 .se_header = "Target Shared Object",
424 .se_cmp = sort__dso_to_cmp,
425 .se_snprintf = hist_entry__dso_to_snprintf,
426 .se_width_idx = HISTC_DSO_TO,
427};
428
429struct sort_entry sort_sym_from = {
430 .se_header = "Source Symbol",
431 .se_cmp = sort__sym_from_cmp,
432 .se_snprintf = hist_entry__sym_from_snprintf,
433 .se_width_idx = HISTC_SYMBOL_FROM,
434};
435
436struct sort_entry sort_sym_to = {
437 .se_header = "Target Symbol",
438 .se_cmp = sort__sym_to_cmp,
439 .se_snprintf = hist_entry__sym_to_snprintf,
440 .se_width_idx = HISTC_SYMBOL_TO,
441};
442
443static int64_t
444sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
445{
446 const unsigned char mp = left->branch_info->flags.mispred !=
447 right->branch_info->flags.mispred;
448 const unsigned char p = left->branch_info->flags.predicted !=
449 right->branch_info->flags.predicted;
450
451 return mp || p;
452}
453
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300454static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100455 size_t size, unsigned int width){
456 static const char *out = "N/A";
457
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300458 if (he->branch_info->flags.predicted)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100459 out = "N";
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300460 else if (he->branch_info->flags.mispred)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100461 out = "Y";
462
463 return repsep_snprintf(bf, size, "%-*s", width, out);
464}
465
Stephane Eranian98a3b322013-01-24 16:10:35 +0100466/* --sort daddr_sym */
467static int64_t
468sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
469{
470 uint64_t l = 0, r = 0;
471
472 if (left->mem_info)
473 l = left->mem_info->daddr.addr;
474 if (right->mem_info)
475 r = right->mem_info->daddr.addr;
476
477 return (int64_t)(r - l);
478}
479
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300480static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100481 size_t size, unsigned int width)
482{
483 uint64_t addr = 0;
484 struct map *map = NULL;
485 struct symbol *sym = NULL;
486
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300487 if (he->mem_info) {
488 addr = he->mem_info->daddr.addr;
489 map = he->mem_info->daddr.map;
490 sym = he->mem_info->daddr.sym;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100491 }
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300492 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100493 width);
494}
495
496static int64_t
497sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
498{
499 struct map *map_l = NULL;
500 struct map *map_r = NULL;
501
502 if (left->mem_info)
503 map_l = left->mem_info->daddr.map;
504 if (right->mem_info)
505 map_r = right->mem_info->daddr.map;
506
507 return _sort__dso_cmp(map_l, map_r);
508}
509
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300510static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100511 size_t size, unsigned int width)
512{
513 struct map *map = NULL;
514
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300515 if (he->mem_info)
516 map = he->mem_info->daddr.map;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100517
518 return _hist_entry__dso_snprintf(map, bf, size, width);
519}
520
521static int64_t
522sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
523{
524 union perf_mem_data_src data_src_l;
525 union perf_mem_data_src data_src_r;
526
527 if (left->mem_info)
528 data_src_l = left->mem_info->data_src;
529 else
530 data_src_l.mem_lock = PERF_MEM_LOCK_NA;
531
532 if (right->mem_info)
533 data_src_r = right->mem_info->data_src;
534 else
535 data_src_r.mem_lock = PERF_MEM_LOCK_NA;
536
537 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
538}
539
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300540static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100541 size_t size, unsigned int width)
542{
543 const char *out;
544 u64 mask = PERF_MEM_LOCK_NA;
545
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300546 if (he->mem_info)
547 mask = he->mem_info->data_src.mem_lock;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100548
549 if (mask & PERF_MEM_LOCK_NA)
550 out = "N/A";
551 else if (mask & PERF_MEM_LOCK_LOCKED)
552 out = "Yes";
553 else
554 out = "No";
555
556 return repsep_snprintf(bf, size, "%-*s", width, out);
557}
558
559static int64_t
560sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
561{
562 union perf_mem_data_src data_src_l;
563 union perf_mem_data_src data_src_r;
564
565 if (left->mem_info)
566 data_src_l = left->mem_info->data_src;
567 else
568 data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
569
570 if (right->mem_info)
571 data_src_r = right->mem_info->data_src;
572 else
573 data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
574
575 return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
576}
577
578static const char * const tlb_access[] = {
579 "N/A",
580 "HIT",
581 "MISS",
582 "L1",
583 "L2",
584 "Walker",
585 "Fault",
586};
587#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
588
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300589static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100590 size_t size, unsigned int width)
591{
592 char out[64];
593 size_t sz = sizeof(out) - 1; /* -1 for null termination */
594 size_t l = 0, i;
595 u64 m = PERF_MEM_TLB_NA;
596 u64 hit, miss;
597
598 out[0] = '\0';
599
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300600 if (he->mem_info)
601 m = he->mem_info->data_src.mem_dtlb;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100602
603 hit = m & PERF_MEM_TLB_HIT;
604 miss = m & PERF_MEM_TLB_MISS;
605
606 /* already taken care of */
607 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
608
609 for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
610 if (!(m & 0x1))
611 continue;
612 if (l) {
613 strcat(out, " or ");
614 l += 4;
615 }
616 strncat(out, tlb_access[i], sz - l);
617 l += strlen(tlb_access[i]);
618 }
619 if (*out == '\0')
620 strcpy(out, "N/A");
621 if (hit)
622 strncat(out, " hit", sz - l);
623 if (miss)
624 strncat(out, " miss", sz - l);
625
626 return repsep_snprintf(bf, size, "%-*s", width, out);
627}
628
629static int64_t
630sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
631{
632 union perf_mem_data_src data_src_l;
633 union perf_mem_data_src data_src_r;
634
635 if (left->mem_info)
636 data_src_l = left->mem_info->data_src;
637 else
638 data_src_l.mem_lvl = PERF_MEM_LVL_NA;
639
640 if (right->mem_info)
641 data_src_r = right->mem_info->data_src;
642 else
643 data_src_r.mem_lvl = PERF_MEM_LVL_NA;
644
645 return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
646}
647
648static const char * const mem_lvl[] = {
649 "N/A",
650 "HIT",
651 "MISS",
652 "L1",
653 "LFB",
654 "L2",
655 "L3",
656 "Local RAM",
657 "Remote RAM (1 hop)",
658 "Remote RAM (2 hops)",
659 "Remote Cache (1 hop)",
660 "Remote Cache (2 hops)",
661 "I/O",
662 "Uncached",
663};
664#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
665
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300666static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100667 size_t size, unsigned int width)
668{
669 char out[64];
670 size_t sz = sizeof(out) - 1; /* -1 for null termination */
671 size_t i, l = 0;
672 u64 m = PERF_MEM_LVL_NA;
673 u64 hit, miss;
674
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300675 if (he->mem_info)
676 m = he->mem_info->data_src.mem_lvl;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100677
678 out[0] = '\0';
679
680 hit = m & PERF_MEM_LVL_HIT;
681 miss = m & PERF_MEM_LVL_MISS;
682
683 /* already taken care of */
684 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
685
686 for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
687 if (!(m & 0x1))
688 continue;
689 if (l) {
690 strcat(out, " or ");
691 l += 4;
692 }
693 strncat(out, mem_lvl[i], sz - l);
694 l += strlen(mem_lvl[i]);
695 }
696 if (*out == '\0')
697 strcpy(out, "N/A");
698 if (hit)
699 strncat(out, " hit", sz - l);
700 if (miss)
701 strncat(out, " miss", sz - l);
702
703 return repsep_snprintf(bf, size, "%-*s", width, out);
704}
705
706static int64_t
707sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
708{
709 union perf_mem_data_src data_src_l;
710 union perf_mem_data_src data_src_r;
711
712 if (left->mem_info)
713 data_src_l = left->mem_info->data_src;
714 else
715 data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
716
717 if (right->mem_info)
718 data_src_r = right->mem_info->data_src;
719 else
720 data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
721
722 return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
723}
724
725static const char * const snoop_access[] = {
726 "N/A",
727 "None",
728 "Miss",
729 "Hit",
730 "HitM",
731};
732#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
733
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300734static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100735 size_t size, unsigned int width)
736{
737 char out[64];
738 size_t sz = sizeof(out) - 1; /* -1 for null termination */
739 size_t i, l = 0;
740 u64 m = PERF_MEM_SNOOP_NA;
741
742 out[0] = '\0';
743
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300744 if (he->mem_info)
745 m = he->mem_info->data_src.mem_snoop;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100746
747 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
748 if (!(m & 0x1))
749 continue;
750 if (l) {
751 strcat(out, " or ");
752 l += 4;
753 }
754 strncat(out, snoop_access[i], sz - l);
755 l += strlen(snoop_access[i]);
756 }
757
758 if (*out == '\0')
759 strcpy(out, "N/A");
760
761 return repsep_snprintf(bf, size, "%-*s", width, out);
762}
763
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100764struct sort_entry sort_mispredict = {
765 .se_header = "Branch Mispredicted",
766 .se_cmp = sort__mispredict_cmp,
767 .se_snprintf = hist_entry__mispredict_snprintf,
768 .se_width_idx = HISTC_MISPREDICT,
769};
770
Andi Kleen05484292013-01-24 16:10:29 +0100771static u64 he_weight(struct hist_entry *he)
772{
773 return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
774}
775
776static int64_t
777sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
778{
779 return he_weight(left) - he_weight(right);
780}
781
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300782static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100783 size_t size, unsigned int width)
784{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300785 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
Andi Kleen05484292013-01-24 16:10:29 +0100786}
787
788struct sort_entry sort_local_weight = {
789 .se_header = "Local Weight",
790 .se_cmp = sort__local_weight_cmp,
791 .se_snprintf = hist_entry__local_weight_snprintf,
792 .se_width_idx = HISTC_LOCAL_WEIGHT,
793};
794
795static int64_t
796sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
797{
798 return left->stat.weight - right->stat.weight;
799}
800
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300801static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100802 size_t size, unsigned int width)
803{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300804 return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
Andi Kleen05484292013-01-24 16:10:29 +0100805}
806
807struct sort_entry sort_global_weight = {
808 .se_header = "Weight",
809 .se_cmp = sort__global_weight_cmp,
810 .se_snprintf = hist_entry__global_weight_snprintf,
811 .se_width_idx = HISTC_GLOBAL_WEIGHT,
812};
813
Stephane Eranian98a3b322013-01-24 16:10:35 +0100814struct sort_entry sort_mem_daddr_sym = {
815 .se_header = "Data Symbol",
816 .se_cmp = sort__daddr_cmp,
817 .se_snprintf = hist_entry__daddr_snprintf,
818 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
819};
820
821struct sort_entry sort_mem_daddr_dso = {
822 .se_header = "Data Object",
823 .se_cmp = sort__dso_daddr_cmp,
824 .se_snprintf = hist_entry__dso_daddr_snprintf,
825 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
826};
827
828struct sort_entry sort_mem_locked = {
829 .se_header = "Locked",
830 .se_cmp = sort__locked_cmp,
831 .se_snprintf = hist_entry__locked_snprintf,
832 .se_width_idx = HISTC_MEM_LOCKED,
833};
834
835struct sort_entry sort_mem_tlb = {
836 .se_header = "TLB access",
837 .se_cmp = sort__tlb_cmp,
838 .se_snprintf = hist_entry__tlb_snprintf,
839 .se_width_idx = HISTC_MEM_TLB,
840};
841
842struct sort_entry sort_mem_lvl = {
843 .se_header = "Memory access",
844 .se_cmp = sort__lvl_cmp,
845 .se_snprintf = hist_entry__lvl_snprintf,
846 .se_width_idx = HISTC_MEM_LVL,
847};
848
849struct sort_entry sort_mem_snoop = {
850 .se_header = "Snoop",
851 .se_cmp = sort__snoop_cmp,
852 .se_snprintf = hist_entry__snoop_snprintf,
853 .se_width_idx = HISTC_MEM_SNOOP,
854};
855
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700856static int64_t
857sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
858{
859 return left->branch_info->flags.abort !=
860 right->branch_info->flags.abort;
861}
862
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300863static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700864 size_t size, unsigned int width)
865{
866 static const char *out = ".";
867
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300868 if (he->branch_info->flags.abort)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700869 out = "A";
870 return repsep_snprintf(bf, size, "%-*s", width, out);
871}
872
873struct sort_entry sort_abort = {
874 .se_header = "Transaction abort",
875 .se_cmp = sort__abort_cmp,
876 .se_snprintf = hist_entry__abort_snprintf,
877 .se_width_idx = HISTC_ABORT,
878};
879
880static int64_t
881sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
882{
883 return left->branch_info->flags.in_tx !=
884 right->branch_info->flags.in_tx;
885}
886
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300887static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700888 size_t size, unsigned int width)
889{
890 static const char *out = ".";
891
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300892 if (he->branch_info->flags.in_tx)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700893 out = "T";
894
895 return repsep_snprintf(bf, size, "%-*s", width, out);
896}
897
898struct sort_entry sort_in_tx = {
899 .se_header = "Branch in transaction",
900 .se_cmp = sort__in_tx_cmp,
901 .se_snprintf = hist_entry__in_tx_snprintf,
902 .se_width_idx = HISTC_IN_TX,
903};
904
Andi Kleen475eeab2013-09-20 07:40:43 -0700905static int64_t
906sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
907{
908 return left->transaction - right->transaction;
909}
910
911static inline char *add_str(char *p, const char *str)
912{
913 strcpy(p, str);
914 return p + strlen(str);
915}
916
917static struct txbit {
918 unsigned flag;
919 const char *name;
920 int skip_for_len;
921} txbits[] = {
922 { PERF_TXN_ELISION, "EL ", 0 },
923 { PERF_TXN_TRANSACTION, "TX ", 1 },
924 { PERF_TXN_SYNC, "SYNC ", 1 },
925 { PERF_TXN_ASYNC, "ASYNC ", 0 },
926 { PERF_TXN_RETRY, "RETRY ", 0 },
927 { PERF_TXN_CONFLICT, "CON ", 0 },
928 { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
929 { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
930 { 0, NULL, 0 }
931};
932
933int hist_entry__transaction_len(void)
934{
935 int i;
936 int len = 0;
937
938 for (i = 0; txbits[i].name; i++) {
939 if (!txbits[i].skip_for_len)
940 len += strlen(txbits[i].name);
941 }
942 len += 4; /* :XX<space> */
943 return len;
944}
945
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300946static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
Andi Kleen475eeab2013-09-20 07:40:43 -0700947 size_t size, unsigned int width)
948{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300949 u64 t = he->transaction;
Andi Kleen475eeab2013-09-20 07:40:43 -0700950 char buf[128];
951 char *p = buf;
952 int i;
953
954 buf[0] = 0;
955 for (i = 0; txbits[i].name; i++)
956 if (txbits[i].flag & t)
957 p = add_str(p, txbits[i].name);
958 if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
959 p = add_str(p, "NEITHER ");
960 if (t & PERF_TXN_ABORT_MASK) {
961 sprintf(p, ":%" PRIx64,
962 (t & PERF_TXN_ABORT_MASK) >>
963 PERF_TXN_ABORT_SHIFT);
964 p += strlen(p);
965 }
966
967 return repsep_snprintf(bf, size, "%-*s", width, buf);
968}
969
970struct sort_entry sort_transaction = {
971 .se_header = "Transaction ",
972 .se_cmp = sort__transaction_cmp,
973 .se_snprintf = hist_entry__transaction_snprintf,
974 .se_width_idx = HISTC_TRANSACTION,
975};
976
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200977struct sort_dimension {
978 const char *name;
979 struct sort_entry *entry;
980 int taken;
981};
982
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100983#define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
984
Namhyung Kimfc5871e2012-12-27 18:11:46 +0900985static struct sort_dimension common_sort_dimensions[] = {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100986 DIM(SORT_PID, "pid", sort_thread),
987 DIM(SORT_COMM, "comm", sort_comm),
988 DIM(SORT_DSO, "dso", sort_dso),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100989 DIM(SORT_SYM, "symbol", sort_sym),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100990 DIM(SORT_PARENT, "parent", sort_parent),
991 DIM(SORT_CPU, "cpu", sort_cpu),
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300992 DIM(SORT_SRCLINE, "srcline", sort_srcline),
Andi Kleenf9ea55d2013-07-18 15:58:53 -0700993 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
994 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
Andi Kleen475eeab2013-09-20 07:40:43 -0700995 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200996};
997
Namhyung Kimfc5871e2012-12-27 18:11:46 +0900998#undef DIM
999
1000#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
1001
1002static struct sort_dimension bstack_sort_dimensions[] = {
1003 DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
1004 DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
1005 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
1006 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
1007 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001008 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1009 DIM(SORT_ABORT, "abort", sort_abort),
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001010};
1011
1012#undef DIM
1013
Namhyung Kimafab87b2013-04-03 21:26:11 +09001014#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
1015
1016static struct sort_dimension memory_sort_dimensions[] = {
Namhyung Kimafab87b2013-04-03 21:26:11 +09001017 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1018 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1019 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1020 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1021 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1022 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1023};
1024
1025#undef DIM
1026
Namhyung Kim2f532d02013-04-03 21:26:10 +09001027static void __sort_dimension__add(struct sort_dimension *sd, enum sort_type idx)
1028{
1029 if (sd->taken)
1030 return;
1031
1032 if (sd->entry->se_collapse)
1033 sort__need_collapse = 1;
1034
1035 if (list_empty(&hist_entry__sort_list))
1036 sort__first_dimension = idx;
1037
1038 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
1039 sd->taken = 1;
1040}
1041
John Kacurdd68ada2009-09-24 18:02:49 +02001042int sort_dimension__add(const char *tok)
1043{
1044 unsigned int i;
1045
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001046 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1047 struct sort_dimension *sd = &common_sort_dimensions[i];
John Kacurdd68ada2009-09-24 18:02:49 +02001048
John Kacurdd68ada2009-09-24 18:02:49 +02001049 if (strncasecmp(tok, sd->name, strlen(tok)))
1050 continue;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001051
John Kacurdd68ada2009-09-24 18:02:49 +02001052 if (sd->entry == &sort_parent) {
1053 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
1054 if (ret) {
1055 char err[BUFSIZ];
1056
1057 regerror(ret, &parent_regex, err, sizeof(err));
Arnaldo Carvalho de Melo2aefa4f2010-04-02 12:30:57 -03001058 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
1059 return -EINVAL;
John Kacurdd68ada2009-09-24 18:02:49 +02001060 }
1061 sort__has_parent = 1;
Namhyung Kim930477b2013-04-05 10:26:36 +09001062 } else if (sd->entry == &sort_sym) {
Namhyung Kim1af556402012-09-14 17:35:27 +09001063 sort__has_sym = 1;
John Kacurdd68ada2009-09-24 18:02:49 +02001064 }
1065
Namhyung Kim2f532d02013-04-03 21:26:10 +09001066 __sort_dimension__add(sd, i);
John Kacurdd68ada2009-09-24 18:02:49 +02001067 return 0;
1068 }
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001069
1070 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1071 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1072
1073 if (strncasecmp(tok, sd->name, strlen(tok)))
1074 continue;
1075
Namhyung Kim55369fc2013-04-01 20:35:20 +09001076 if (sort__mode != SORT_MODE__BRANCH)
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001077 return -EINVAL;
1078
1079 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
1080 sort__has_sym = 1;
1081
Namhyung Kim2f532d02013-04-03 21:26:10 +09001082 __sort_dimension__add(sd, i + __SORT_BRANCH_STACK);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001083 return 0;
1084 }
1085
Namhyung Kimafab87b2013-04-03 21:26:11 +09001086 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1087 struct sort_dimension *sd = &memory_sort_dimensions[i];
1088
1089 if (strncasecmp(tok, sd->name, strlen(tok)))
1090 continue;
1091
1092 if (sort__mode != SORT_MODE__MEMORY)
1093 return -EINVAL;
1094
1095 if (sd->entry == &sort_mem_daddr_sym)
1096 sort__has_sym = 1;
1097
1098 __sort_dimension__add(sd, i + __SORT_MEMORY_MODE);
1099 return 0;
1100 }
1101
John Kacurdd68ada2009-09-24 18:02:49 +02001102 return -ESRCH;
1103}
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001104
Namhyung Kim55309982013-02-06 14:57:16 +09001105int setup_sorting(void)
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001106{
1107 char *tmp, *tok, *str = strdup(sort_order);
Namhyung Kim55309982013-02-06 14:57:16 +09001108 int ret = 0;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001109
Namhyung Kim5936f542013-02-06 14:57:17 +09001110 if (str == NULL) {
1111 error("Not enough memory to setup sort keys");
1112 return -ENOMEM;
1113 }
1114
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001115 for (tok = strtok_r(str, ", ", &tmp);
1116 tok; tok = strtok_r(NULL, ", ", &tmp)) {
Namhyung Kim55309982013-02-06 14:57:16 +09001117 ret = sort_dimension__add(tok);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001118 if (ret == -EINVAL) {
1119 error("Invalid --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001120 break;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001121 } else if (ret == -ESRCH) {
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001122 error("Unknown --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001123 break;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001124 }
1125 }
1126
1127 free(str);
Namhyung Kim55309982013-02-06 14:57:16 +09001128 return ret;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001129}
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001130
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001131static void sort_entry__setup_elide(struct sort_entry *se,
Namhyung Kim08e71542013-04-03 21:26:19 +09001132 struct strlist *list,
1133 const char *list_name, FILE *fp)
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001134{
1135 if (list && strlist__nr_entries(list) == 1) {
1136 if (fp != NULL)
1137 fprintf(fp, "# %s: %s\n", list_name,
1138 strlist__entry(list, 0)->s);
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001139 se->elide = true;
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001140 }
1141}
Namhyung Kim08e71542013-04-03 21:26:19 +09001142
1143void sort__setup_elide(FILE *output)
1144{
Namhyung Kim7524f632013-11-08 17:53:42 +09001145 struct sort_entry *se;
1146
Namhyung Kim08e71542013-04-03 21:26:19 +09001147 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1148 "dso", output);
1149 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list,
1150 "comm", output);
1151 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list,
1152 "symbol", output);
1153
1154 if (sort__mode == SORT_MODE__BRANCH) {
1155 sort_entry__setup_elide(&sort_dso_from,
1156 symbol_conf.dso_from_list,
1157 "dso_from", output);
1158 sort_entry__setup_elide(&sort_dso_to,
1159 symbol_conf.dso_to_list,
1160 "dso_to", output);
1161 sort_entry__setup_elide(&sort_sym_from,
1162 symbol_conf.sym_from_list,
1163 "sym_from", output);
1164 sort_entry__setup_elide(&sort_sym_to,
1165 symbol_conf.sym_to_list,
1166 "sym_to", output);
1167 } else if (sort__mode == SORT_MODE__MEMORY) {
1168 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1169 "symbol_daddr", output);
1170 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1171 "dso_daddr", output);
1172 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1173 "mem", output);
1174 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1175 "local_weight", output);
1176 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1177 "tlb", output);
1178 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1179 "snoop", output);
1180 }
1181
Namhyung Kim7524f632013-11-08 17:53:42 +09001182 /*
1183 * It makes no sense to elide all of sort entries.
1184 * Just revert them to show up again.
1185 */
1186 list_for_each_entry(se, &hist_entry__sort_list, list) {
1187 if (!se->elide)
1188 return;
1189 }
1190
1191 list_for_each_entry(se, &hist_entry__sort_list, list)
1192 se->elide = false;
Namhyung Kim08e71542013-04-03 21:26:19 +09001193}