blob: 635cd8f8b22ed14463fe4f7fd9357f9e663da41f [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 Kim68f6d022013-12-18 14:21:10 +090016int sort__has_dso = 0;
Namhyung Kim55369fc2013-04-01 20:35:20 +090017enum sort_mode sort__mode = SORT_MODE__NORMAL;
Frederic Weisbeckera4fb5812009-10-22 23:23:23 +020018
19enum sort_type sort__first_dimension;
John Kacurdd68ada2009-09-24 18:02:49 +020020
John Kacurdd68ada2009-09-24 18:02:49 +020021LIST_HEAD(hist_entry__sort_list);
22
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030023static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
John Kacurdd68ada2009-09-24 18:02:49 +020024{
25 int n;
26 va_list ap;
27
28 va_start(ap, fmt);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030029 n = vsnprintf(bf, size, fmt, ap);
Jiri Olsa0ca0c132012-09-06 17:46:56 +020030 if (symbol_conf.field_sep && n > 0) {
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030031 char *sep = bf;
John Kacurdd68ada2009-09-24 18:02:49 +020032
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030033 while (1) {
Jiri Olsa0ca0c132012-09-06 17:46:56 +020034 sep = strchr(sep, *symbol_conf.field_sep);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030035 if (sep == NULL)
36 break;
37 *sep = '.';
John Kacurdd68ada2009-09-24 18:02:49 +020038 }
John Kacurdd68ada2009-09-24 18:02:49 +020039 }
40 va_end(ap);
Anton Blanchardb8327962012-03-07 11:42:49 +110041
42 if (n >= (int)size)
43 return size - 1;
John Kacurdd68ada2009-09-24 18:02:49 +020044 return n;
45}
46
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020047static int64_t cmp_null(const void *l, const void *r)
Frederic Weisbecker872a8782011-06-29 03:14:52 +020048{
49 if (!l && !r)
50 return 0;
51 else if (!l)
52 return -1;
53 else
54 return 1;
55}
56
57/* --sort pid */
58
59static int64_t
60sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
61{
Adrian Hunter38051232013-07-04 16:20:31 +030062 return right->thread->tid - left->thread->tid;
Frederic Weisbecker872a8782011-06-29 03:14:52 +020063}
64
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -030065static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030066 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +020067{
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020068 const char *comm = thread__comm_str(he->thread);
Namhyung Kimfb29a332012-12-27 18:11:40 +090069 return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020070 comm ?: "", he->thread->tid);
John Kacurdd68ada2009-09-24 18:02:49 +020071}
72
Frederic Weisbecker872a8782011-06-29 03:14:52 +020073struct sort_entry sort_thread = {
74 .se_header = "Command: Pid",
75 .se_cmp = sort__thread_cmp,
76 .se_snprintf = hist_entry__thread_snprintf,
77 .se_width_idx = HISTC_THREAD,
78};
79
80/* --sort comm */
81
82static int64_t
83sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
84{
Frederic Weisbeckerfedd63d2013-09-11 17:18:09 +020085 /* Compare the addr that should be unique among comm */
Namhyung Kim4dfced32013-09-13 16:28:57 +090086 return comm__str(right->comm) - comm__str(left->comm);
Frederic Weisbecker872a8782011-06-29 03:14:52 +020087}
88
89static int64_t
90sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
91{
Namhyung Kim4dfced32013-09-13 16:28:57 +090092 /* Compare the addr that should be unique among comm */
93 return comm__str(right->comm) - comm__str(left->comm);
Frederic Weisbecker872a8782011-06-29 03:14:52 +020094}
95
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -030096static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030097 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +020098{
Namhyung Kim4dfced32013-09-13 16:28:57 +090099 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm));
John Kacurdd68ada2009-09-24 18:02:49 +0200100}
101
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900102struct sort_entry sort_comm = {
103 .se_header = "Command",
104 .se_cmp = sort__comm_cmp,
105 .se_collapse = sort__comm_collapse,
106 .se_snprintf = hist_entry__comm_snprintf,
107 .se_width_idx = HISTC_COMM,
108};
109
110/* --sort dso */
111
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100112static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
John Kacurdd68ada2009-09-24 18:02:49 +0200113{
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100114 struct dso *dso_l = map_l ? map_l->dso : NULL;
115 struct dso *dso_r = map_r ? map_r->dso : NULL;
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300116 const char *dso_name_l, *dso_name_r;
John Kacurdd68ada2009-09-24 18:02:49 +0200117
118 if (!dso_l || !dso_r)
119 return cmp_null(dso_l, dso_r);
120
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300121 if (verbose) {
122 dso_name_l = dso_l->long_name;
123 dso_name_r = dso_r->long_name;
124 } else {
125 dso_name_l = dso_l->short_name;
126 dso_name_r = dso_r->short_name;
127 }
128
129 return strcmp(dso_name_l, dso_name_r);
John Kacurdd68ada2009-09-24 18:02:49 +0200130}
131
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100132static int64_t
133sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
John Kacurdd68ada2009-09-24 18:02:49 +0200134{
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100135 return _sort__dso_cmp(left->ms.map, right->ms.map);
136}
137
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100138static int _hist_entry__dso_snprintf(struct map *map, char *bf,
139 size_t size, unsigned int width)
140{
141 if (map && map->dso) {
142 const char *dso_name = !verbose ? map->dso->short_name :
143 map->dso->long_name;
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300144 return repsep_snprintf(bf, size, "%-*s", width, dso_name);
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300145 }
John Kacurdd68ada2009-09-24 18:02:49 +0200146
Ian Munsie1437a302010-12-06 13:37:04 +1100147 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
John Kacurdd68ada2009-09-24 18:02:49 +0200148}
149
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300150static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100151 size_t size, unsigned int width)
152{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300153 return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100154}
155
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900156struct sort_entry sort_dso = {
157 .se_header = "Shared Object",
158 .se_cmp = sort__dso_cmp,
159 .se_snprintf = hist_entry__dso_snprintf,
160 .se_width_idx = HISTC_DSO,
161};
162
163/* --sort symbol */
164
Namhyung Kim2037be52013-12-18 14:21:09 +0900165static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
166{
167 return (int64_t)(right_ip - left_ip);
168}
169
Namhyung Kim51f27d12013-02-06 14:57:15 +0900170static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900171{
Namhyung Kim51f27d12013-02-06 14:57:15 +0900172 u64 ip_l, ip_r;
173
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900174 if (!sym_l || !sym_r)
175 return cmp_null(sym_l, sym_r);
176
177 if (sym_l == sym_r)
178 return 0;
179
180 ip_l = sym_l->start;
181 ip_r = sym_r->start;
182
183 return (int64_t)(ip_r - ip_l);
184}
185
186static int64_t
187sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
188{
Namhyung Kim09600e02013-10-15 11:01:56 +0900189 int64_t ret;
190
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900191 if (!left->ms.sym && !right->ms.sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900192 return _sort__addr_cmp(left->ip, right->ip);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900193
Namhyung Kim09600e02013-10-15 11:01:56 +0900194 /*
195 * comparing symbol address alone is not enough since it's a
196 * relative address within a dso.
197 */
Namhyung Kim68f6d022013-12-18 14:21:10 +0900198 if (!sort__has_dso) {
199 ret = sort__dso_cmp(left, right);
200 if (ret != 0)
201 return ret;
202 }
Namhyung Kim09600e02013-10-15 11:01:56 +0900203
Namhyung Kim51f27d12013-02-06 14:57:15 +0900204 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900205}
206
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100207static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
208 u64 ip, char level, char *bf, size_t size,
Namhyung Kim43355522012-12-27 18:11:39 +0900209 unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100210{
211 size_t ret = 0;
212
213 if (verbose) {
214 char o = map ? dso__symtab_origin(map->dso) : '!';
215 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
Namhyung Kimded19d52013-04-01 20:35:19 +0900216 BITS_PER_LONG / 4 + 2, ip, o);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100217 }
218
219 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
Stephane Eranian98a3b322013-01-24 16:10:35 +0100220 if (sym && map) {
221 if (map->type == MAP__VARIABLE) {
222 ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
223 ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
Namhyung Kim62667742013-01-24 16:10:42 +0100224 ip - map->unmap_ip(map, sym->start));
Stephane Eranian98a3b322013-01-24 16:10:35 +0100225 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
226 width - ret, "");
227 } else {
228 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
229 width - ret,
230 sym->name);
231 }
232 } else {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100233 size_t len = BITS_PER_LONG / 4;
234 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
235 len, ip);
236 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
237 width - ret, "");
238 }
239
240 return ret;
241}
242
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300243static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900244 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100245{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300246 return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
247 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100248}
John Kacurdd68ada2009-09-24 18:02:49 +0200249
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200250struct sort_entry sort_sym = {
251 .se_header = "Symbol",
252 .se_cmp = sort__sym_cmp,
253 .se_snprintf = hist_entry__sym_snprintf,
254 .se_width_idx = HISTC_SYMBOL,
255};
John Kacurdd68ada2009-09-24 18:02:49 +0200256
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300257/* --sort srcline */
258
259static int64_t
260sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
261{
Namhyung Kim4adcc432013-09-11 14:09:33 +0900262 if (!left->srcline) {
263 if (!left->ms.map)
264 left->srcline = SRCLINE_UNKNOWN;
265 else {
266 struct map *map = left->ms.map;
267 left->srcline = get_srcline(map->dso,
268 map__rip_2objdump(map, left->ip));
269 }
270 }
271 if (!right->srcline) {
272 if (!right->ms.map)
273 right->srcline = SRCLINE_UNKNOWN;
274 else {
275 struct map *map = right->ms.map;
276 right->srcline = get_srcline(map->dso,
277 map__rip_2objdump(map, right->ip));
278 }
279 }
280 return strcmp(left->srcline, right->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300281}
282
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300283static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300284 size_t size,
285 unsigned int width __maybe_unused)
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300286{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300287 return repsep_snprintf(bf, size, "%s", he->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300288}
289
290struct sort_entry sort_srcline = {
291 .se_header = "Source:Line",
292 .se_cmp = sort__srcline_cmp,
293 .se_snprintf = hist_entry__srcline_snprintf,
294 .se_width_idx = HISTC_SRCLINE,
295};
296
John Kacurdd68ada2009-09-24 18:02:49 +0200297/* --sort parent */
298
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200299static int64_t
John Kacurdd68ada2009-09-24 18:02:49 +0200300sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
301{
302 struct symbol *sym_l = left->parent;
303 struct symbol *sym_r = right->parent;
304
305 if (!sym_l || !sym_r)
306 return cmp_null(sym_l, sym_r);
307
308 return strcmp(sym_l->name, sym_r->name);
309}
310
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300311static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300312 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +0200313{
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300314 return repsep_snprintf(bf, size, "%-*s", width,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300315 he->parent ? he->parent->name : "[other]");
John Kacurdd68ada2009-09-24 18:02:49 +0200316}
317
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200318struct sort_entry sort_parent = {
319 .se_header = "Parent symbol",
320 .se_cmp = sort__parent_cmp,
321 .se_snprintf = hist_entry__parent_snprintf,
322 .se_width_idx = HISTC_PARENT,
323};
324
Arun Sharmaf60f3592010-06-04 11:27:10 -0300325/* --sort cpu */
326
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200327static int64_t
Arun Sharmaf60f3592010-06-04 11:27:10 -0300328sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
329{
330 return right->cpu - left->cpu;
331}
332
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300333static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
334 size_t size, unsigned int width)
Arun Sharmaf60f3592010-06-04 11:27:10 -0300335{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300336 return repsep_snprintf(bf, size, "%*d", width, he->cpu);
Arun Sharmaf60f3592010-06-04 11:27:10 -0300337}
338
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200339struct sort_entry sort_cpu = {
340 .se_header = "CPU",
341 .se_cmp = sort__cpu_cmp,
342 .se_snprintf = hist_entry__cpu_snprintf,
343 .se_width_idx = HISTC_CPU,
344};
345
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900346/* sort keys for branch stacks */
347
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100348static int64_t
349sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
350{
351 return _sort__dso_cmp(left->branch_info->from.map,
352 right->branch_info->from.map);
353}
354
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300355static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100356 size_t size, unsigned int width)
357{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300358 return _hist_entry__dso_snprintf(he->branch_info->from.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100359 bf, size, width);
360}
361
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100362static int64_t
363sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
364{
365 return _sort__dso_cmp(left->branch_info->to.map,
366 right->branch_info->to.map);
367}
368
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300369static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100370 size_t size, unsigned int width)
371{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300372 return _hist_entry__dso_snprintf(he->branch_info->to.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100373 bf, size, width);
374}
375
376static int64_t
377sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
378{
379 struct addr_map_symbol *from_l = &left->branch_info->from;
380 struct addr_map_symbol *from_r = &right->branch_info->from;
381
382 if (!from_l->sym && !from_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900383 return _sort__addr_cmp(from_l->addr, from_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100384
Namhyung Kim51f27d12013-02-06 14:57:15 +0900385 return _sort__sym_cmp(from_l->sym, from_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100386}
387
388static int64_t
389sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
390{
391 struct addr_map_symbol *to_l = &left->branch_info->to;
392 struct addr_map_symbol *to_r = &right->branch_info->to;
393
394 if (!to_l->sym && !to_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900395 return _sort__addr_cmp(to_l->addr, to_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100396
Namhyung Kim51f27d12013-02-06 14:57:15 +0900397 return _sort__sym_cmp(to_l->sym, to_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100398}
399
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300400static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900401 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100402{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300403 struct addr_map_symbol *from = &he->branch_info->from;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100404 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300405 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100406
407}
408
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300409static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900410 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100411{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300412 struct addr_map_symbol *to = &he->branch_info->to;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100413 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300414 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100415
416}
417
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900418struct sort_entry sort_dso_from = {
419 .se_header = "Source Shared Object",
420 .se_cmp = sort__dso_from_cmp,
421 .se_snprintf = hist_entry__dso_from_snprintf,
422 .se_width_idx = HISTC_DSO_FROM,
423};
424
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100425struct sort_entry sort_dso_to = {
426 .se_header = "Target Shared Object",
427 .se_cmp = sort__dso_to_cmp,
428 .se_snprintf = hist_entry__dso_to_snprintf,
429 .se_width_idx = HISTC_DSO_TO,
430};
431
432struct sort_entry sort_sym_from = {
433 .se_header = "Source Symbol",
434 .se_cmp = sort__sym_from_cmp,
435 .se_snprintf = hist_entry__sym_from_snprintf,
436 .se_width_idx = HISTC_SYMBOL_FROM,
437};
438
439struct sort_entry sort_sym_to = {
440 .se_header = "Target Symbol",
441 .se_cmp = sort__sym_to_cmp,
442 .se_snprintf = hist_entry__sym_to_snprintf,
443 .se_width_idx = HISTC_SYMBOL_TO,
444};
445
446static int64_t
447sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
448{
449 const unsigned char mp = left->branch_info->flags.mispred !=
450 right->branch_info->flags.mispred;
451 const unsigned char p = left->branch_info->flags.predicted !=
452 right->branch_info->flags.predicted;
453
454 return mp || p;
455}
456
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300457static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100458 size_t size, unsigned int width){
459 static const char *out = "N/A";
460
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300461 if (he->branch_info->flags.predicted)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100462 out = "N";
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300463 else if (he->branch_info->flags.mispred)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100464 out = "Y";
465
466 return repsep_snprintf(bf, size, "%-*s", width, out);
467}
468
Stephane Eranian98a3b322013-01-24 16:10:35 +0100469/* --sort daddr_sym */
470static int64_t
471sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
472{
473 uint64_t l = 0, r = 0;
474
475 if (left->mem_info)
476 l = left->mem_info->daddr.addr;
477 if (right->mem_info)
478 r = right->mem_info->daddr.addr;
479
480 return (int64_t)(r - l);
481}
482
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300483static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100484 size_t size, unsigned int width)
485{
486 uint64_t addr = 0;
487 struct map *map = NULL;
488 struct symbol *sym = NULL;
489
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300490 if (he->mem_info) {
491 addr = he->mem_info->daddr.addr;
492 map = he->mem_info->daddr.map;
493 sym = he->mem_info->daddr.sym;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100494 }
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300495 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100496 width);
497}
498
499static int64_t
500sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
501{
502 struct map *map_l = NULL;
503 struct map *map_r = NULL;
504
505 if (left->mem_info)
506 map_l = left->mem_info->daddr.map;
507 if (right->mem_info)
508 map_r = right->mem_info->daddr.map;
509
510 return _sort__dso_cmp(map_l, map_r);
511}
512
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300513static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100514 size_t size, unsigned int width)
515{
516 struct map *map = NULL;
517
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300518 if (he->mem_info)
519 map = he->mem_info->daddr.map;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100520
521 return _hist_entry__dso_snprintf(map, bf, size, width);
522}
523
524static int64_t
525sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
526{
527 union perf_mem_data_src data_src_l;
528 union perf_mem_data_src data_src_r;
529
530 if (left->mem_info)
531 data_src_l = left->mem_info->data_src;
532 else
533 data_src_l.mem_lock = PERF_MEM_LOCK_NA;
534
535 if (right->mem_info)
536 data_src_r = right->mem_info->data_src;
537 else
538 data_src_r.mem_lock = PERF_MEM_LOCK_NA;
539
540 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
541}
542
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300543static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100544 size_t size, unsigned int width)
545{
546 const char *out;
547 u64 mask = PERF_MEM_LOCK_NA;
548
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300549 if (he->mem_info)
550 mask = he->mem_info->data_src.mem_lock;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100551
552 if (mask & PERF_MEM_LOCK_NA)
553 out = "N/A";
554 else if (mask & PERF_MEM_LOCK_LOCKED)
555 out = "Yes";
556 else
557 out = "No";
558
559 return repsep_snprintf(bf, size, "%-*s", width, out);
560}
561
562static int64_t
563sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
564{
565 union perf_mem_data_src data_src_l;
566 union perf_mem_data_src data_src_r;
567
568 if (left->mem_info)
569 data_src_l = left->mem_info->data_src;
570 else
571 data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
572
573 if (right->mem_info)
574 data_src_r = right->mem_info->data_src;
575 else
576 data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
577
578 return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
579}
580
581static const char * const tlb_access[] = {
582 "N/A",
583 "HIT",
584 "MISS",
585 "L1",
586 "L2",
587 "Walker",
588 "Fault",
589};
590#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
591
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300592static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100593 size_t size, unsigned int width)
594{
595 char out[64];
596 size_t sz = sizeof(out) - 1; /* -1 for null termination */
597 size_t l = 0, i;
598 u64 m = PERF_MEM_TLB_NA;
599 u64 hit, miss;
600
601 out[0] = '\0';
602
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300603 if (he->mem_info)
604 m = he->mem_info->data_src.mem_dtlb;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100605
606 hit = m & PERF_MEM_TLB_HIT;
607 miss = m & PERF_MEM_TLB_MISS;
608
609 /* already taken care of */
610 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
611
612 for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
613 if (!(m & 0x1))
614 continue;
615 if (l) {
616 strcat(out, " or ");
617 l += 4;
618 }
619 strncat(out, tlb_access[i], sz - l);
620 l += strlen(tlb_access[i]);
621 }
622 if (*out == '\0')
623 strcpy(out, "N/A");
624 if (hit)
625 strncat(out, " hit", sz - l);
626 if (miss)
627 strncat(out, " miss", sz - l);
628
629 return repsep_snprintf(bf, size, "%-*s", width, out);
630}
631
632static int64_t
633sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
634{
635 union perf_mem_data_src data_src_l;
636 union perf_mem_data_src data_src_r;
637
638 if (left->mem_info)
639 data_src_l = left->mem_info->data_src;
640 else
641 data_src_l.mem_lvl = PERF_MEM_LVL_NA;
642
643 if (right->mem_info)
644 data_src_r = right->mem_info->data_src;
645 else
646 data_src_r.mem_lvl = PERF_MEM_LVL_NA;
647
648 return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
649}
650
651static const char * const mem_lvl[] = {
652 "N/A",
653 "HIT",
654 "MISS",
655 "L1",
656 "LFB",
657 "L2",
658 "L3",
659 "Local RAM",
660 "Remote RAM (1 hop)",
661 "Remote RAM (2 hops)",
662 "Remote Cache (1 hop)",
663 "Remote Cache (2 hops)",
664 "I/O",
665 "Uncached",
666};
667#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
668
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300669static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100670 size_t size, unsigned int width)
671{
672 char out[64];
673 size_t sz = sizeof(out) - 1; /* -1 for null termination */
674 size_t i, l = 0;
675 u64 m = PERF_MEM_LVL_NA;
676 u64 hit, miss;
677
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300678 if (he->mem_info)
679 m = he->mem_info->data_src.mem_lvl;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100680
681 out[0] = '\0';
682
683 hit = m & PERF_MEM_LVL_HIT;
684 miss = m & PERF_MEM_LVL_MISS;
685
686 /* already taken care of */
687 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
688
689 for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
690 if (!(m & 0x1))
691 continue;
692 if (l) {
693 strcat(out, " or ");
694 l += 4;
695 }
696 strncat(out, mem_lvl[i], sz - l);
697 l += strlen(mem_lvl[i]);
698 }
699 if (*out == '\0')
700 strcpy(out, "N/A");
701 if (hit)
702 strncat(out, " hit", sz - l);
703 if (miss)
704 strncat(out, " miss", sz - l);
705
706 return repsep_snprintf(bf, size, "%-*s", width, out);
707}
708
709static int64_t
710sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
711{
712 union perf_mem_data_src data_src_l;
713 union perf_mem_data_src data_src_r;
714
715 if (left->mem_info)
716 data_src_l = left->mem_info->data_src;
717 else
718 data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
719
720 if (right->mem_info)
721 data_src_r = right->mem_info->data_src;
722 else
723 data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
724
725 return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
726}
727
728static const char * const snoop_access[] = {
729 "N/A",
730 "None",
731 "Miss",
732 "Hit",
733 "HitM",
734};
735#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
736
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300737static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100738 size_t size, unsigned int width)
739{
740 char out[64];
741 size_t sz = sizeof(out) - 1; /* -1 for null termination */
742 size_t i, l = 0;
743 u64 m = PERF_MEM_SNOOP_NA;
744
745 out[0] = '\0';
746
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300747 if (he->mem_info)
748 m = he->mem_info->data_src.mem_snoop;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100749
750 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
751 if (!(m & 0x1))
752 continue;
753 if (l) {
754 strcat(out, " or ");
755 l += 4;
756 }
757 strncat(out, snoop_access[i], sz - l);
758 l += strlen(snoop_access[i]);
759 }
760
761 if (*out == '\0')
762 strcpy(out, "N/A");
763
764 return repsep_snprintf(bf, size, "%-*s", width, out);
765}
766
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100767struct sort_entry sort_mispredict = {
768 .se_header = "Branch Mispredicted",
769 .se_cmp = sort__mispredict_cmp,
770 .se_snprintf = hist_entry__mispredict_snprintf,
771 .se_width_idx = HISTC_MISPREDICT,
772};
773
Andi Kleen05484292013-01-24 16:10:29 +0100774static u64 he_weight(struct hist_entry *he)
775{
776 return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
777}
778
779static int64_t
780sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
781{
782 return he_weight(left) - he_weight(right);
783}
784
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300785static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100786 size_t size, unsigned int width)
787{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300788 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
Andi Kleen05484292013-01-24 16:10:29 +0100789}
790
791struct sort_entry sort_local_weight = {
792 .se_header = "Local Weight",
793 .se_cmp = sort__local_weight_cmp,
794 .se_snprintf = hist_entry__local_weight_snprintf,
795 .se_width_idx = HISTC_LOCAL_WEIGHT,
796};
797
798static int64_t
799sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
800{
801 return left->stat.weight - right->stat.weight;
802}
803
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300804static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100805 size_t size, unsigned int width)
806{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300807 return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
Andi Kleen05484292013-01-24 16:10:29 +0100808}
809
810struct sort_entry sort_global_weight = {
811 .se_header = "Weight",
812 .se_cmp = sort__global_weight_cmp,
813 .se_snprintf = hist_entry__global_weight_snprintf,
814 .se_width_idx = HISTC_GLOBAL_WEIGHT,
815};
816
Stephane Eranian98a3b322013-01-24 16:10:35 +0100817struct sort_entry sort_mem_daddr_sym = {
818 .se_header = "Data Symbol",
819 .se_cmp = sort__daddr_cmp,
820 .se_snprintf = hist_entry__daddr_snprintf,
821 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
822};
823
824struct sort_entry sort_mem_daddr_dso = {
825 .se_header = "Data Object",
826 .se_cmp = sort__dso_daddr_cmp,
827 .se_snprintf = hist_entry__dso_daddr_snprintf,
828 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
829};
830
831struct sort_entry sort_mem_locked = {
832 .se_header = "Locked",
833 .se_cmp = sort__locked_cmp,
834 .se_snprintf = hist_entry__locked_snprintf,
835 .se_width_idx = HISTC_MEM_LOCKED,
836};
837
838struct sort_entry sort_mem_tlb = {
839 .se_header = "TLB access",
840 .se_cmp = sort__tlb_cmp,
841 .se_snprintf = hist_entry__tlb_snprintf,
842 .se_width_idx = HISTC_MEM_TLB,
843};
844
845struct sort_entry sort_mem_lvl = {
846 .se_header = "Memory access",
847 .se_cmp = sort__lvl_cmp,
848 .se_snprintf = hist_entry__lvl_snprintf,
849 .se_width_idx = HISTC_MEM_LVL,
850};
851
852struct sort_entry sort_mem_snoop = {
853 .se_header = "Snoop",
854 .se_cmp = sort__snoop_cmp,
855 .se_snprintf = hist_entry__snoop_snprintf,
856 .se_width_idx = HISTC_MEM_SNOOP,
857};
858
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700859static int64_t
860sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
861{
862 return left->branch_info->flags.abort !=
863 right->branch_info->flags.abort;
864}
865
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300866static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700867 size_t size, unsigned int width)
868{
869 static const char *out = ".";
870
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300871 if (he->branch_info->flags.abort)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700872 out = "A";
873 return repsep_snprintf(bf, size, "%-*s", width, out);
874}
875
876struct sort_entry sort_abort = {
877 .se_header = "Transaction abort",
878 .se_cmp = sort__abort_cmp,
879 .se_snprintf = hist_entry__abort_snprintf,
880 .se_width_idx = HISTC_ABORT,
881};
882
883static int64_t
884sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
885{
886 return left->branch_info->flags.in_tx !=
887 right->branch_info->flags.in_tx;
888}
889
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300890static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700891 size_t size, unsigned int width)
892{
893 static const char *out = ".";
894
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300895 if (he->branch_info->flags.in_tx)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700896 out = "T";
897
898 return repsep_snprintf(bf, size, "%-*s", width, out);
899}
900
901struct sort_entry sort_in_tx = {
902 .se_header = "Branch in transaction",
903 .se_cmp = sort__in_tx_cmp,
904 .se_snprintf = hist_entry__in_tx_snprintf,
905 .se_width_idx = HISTC_IN_TX,
906};
907
Andi Kleen475eeab2013-09-20 07:40:43 -0700908static int64_t
909sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
910{
911 return left->transaction - right->transaction;
912}
913
914static inline char *add_str(char *p, const char *str)
915{
916 strcpy(p, str);
917 return p + strlen(str);
918}
919
920static struct txbit {
921 unsigned flag;
922 const char *name;
923 int skip_for_len;
924} txbits[] = {
925 { PERF_TXN_ELISION, "EL ", 0 },
926 { PERF_TXN_TRANSACTION, "TX ", 1 },
927 { PERF_TXN_SYNC, "SYNC ", 1 },
928 { PERF_TXN_ASYNC, "ASYNC ", 0 },
929 { PERF_TXN_RETRY, "RETRY ", 0 },
930 { PERF_TXN_CONFLICT, "CON ", 0 },
931 { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
932 { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
933 { 0, NULL, 0 }
934};
935
936int hist_entry__transaction_len(void)
937{
938 int i;
939 int len = 0;
940
941 for (i = 0; txbits[i].name; i++) {
942 if (!txbits[i].skip_for_len)
943 len += strlen(txbits[i].name);
944 }
945 len += 4; /* :XX<space> */
946 return len;
947}
948
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300949static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
Andi Kleen475eeab2013-09-20 07:40:43 -0700950 size_t size, unsigned int width)
951{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300952 u64 t = he->transaction;
Andi Kleen475eeab2013-09-20 07:40:43 -0700953 char buf[128];
954 char *p = buf;
955 int i;
956
957 buf[0] = 0;
958 for (i = 0; txbits[i].name; i++)
959 if (txbits[i].flag & t)
960 p = add_str(p, txbits[i].name);
961 if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
962 p = add_str(p, "NEITHER ");
963 if (t & PERF_TXN_ABORT_MASK) {
964 sprintf(p, ":%" PRIx64,
965 (t & PERF_TXN_ABORT_MASK) >>
966 PERF_TXN_ABORT_SHIFT);
967 p += strlen(p);
968 }
969
970 return repsep_snprintf(bf, size, "%-*s", width, buf);
971}
972
973struct sort_entry sort_transaction = {
974 .se_header = "Transaction ",
975 .se_cmp = sort__transaction_cmp,
976 .se_snprintf = hist_entry__transaction_snprintf,
977 .se_width_idx = HISTC_TRANSACTION,
978};
979
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200980struct sort_dimension {
981 const char *name;
982 struct sort_entry *entry;
983 int taken;
984};
985
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100986#define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
987
Namhyung Kimfc5871e2012-12-27 18:11:46 +0900988static struct sort_dimension common_sort_dimensions[] = {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100989 DIM(SORT_PID, "pid", sort_thread),
990 DIM(SORT_COMM, "comm", sort_comm),
991 DIM(SORT_DSO, "dso", sort_dso),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100992 DIM(SORT_SYM, "symbol", sort_sym),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100993 DIM(SORT_PARENT, "parent", sort_parent),
994 DIM(SORT_CPU, "cpu", sort_cpu),
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300995 DIM(SORT_SRCLINE, "srcline", sort_srcline),
Andi Kleenf9ea55d2013-07-18 15:58:53 -0700996 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
997 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
Andi Kleen475eeab2013-09-20 07:40:43 -0700998 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200999};
1000
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001001#undef DIM
1002
1003#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
1004
1005static struct sort_dimension bstack_sort_dimensions[] = {
1006 DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
1007 DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
1008 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
1009 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
1010 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001011 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1012 DIM(SORT_ABORT, "abort", sort_abort),
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001013};
1014
1015#undef DIM
1016
Namhyung Kimafab87b2013-04-03 21:26:11 +09001017#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
1018
1019static struct sort_dimension memory_sort_dimensions[] = {
Namhyung Kimafab87b2013-04-03 21:26:11 +09001020 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1021 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1022 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1023 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1024 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1025 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1026};
1027
1028#undef DIM
1029
Namhyung Kim2f532d02013-04-03 21:26:10 +09001030static void __sort_dimension__add(struct sort_dimension *sd, enum sort_type idx)
1031{
1032 if (sd->taken)
1033 return;
1034
1035 if (sd->entry->se_collapse)
1036 sort__need_collapse = 1;
1037
1038 if (list_empty(&hist_entry__sort_list))
1039 sort__first_dimension = idx;
1040
1041 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
1042 sd->taken = 1;
1043}
1044
John Kacurdd68ada2009-09-24 18:02:49 +02001045int sort_dimension__add(const char *tok)
1046{
1047 unsigned int i;
1048
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001049 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1050 struct sort_dimension *sd = &common_sort_dimensions[i];
John Kacurdd68ada2009-09-24 18:02:49 +02001051
John Kacurdd68ada2009-09-24 18:02:49 +02001052 if (strncasecmp(tok, sd->name, strlen(tok)))
1053 continue;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001054
John Kacurdd68ada2009-09-24 18:02:49 +02001055 if (sd->entry == &sort_parent) {
1056 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
1057 if (ret) {
1058 char err[BUFSIZ];
1059
1060 regerror(ret, &parent_regex, err, sizeof(err));
Arnaldo Carvalho de Melo2aefa4f2010-04-02 12:30:57 -03001061 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
1062 return -EINVAL;
John Kacurdd68ada2009-09-24 18:02:49 +02001063 }
1064 sort__has_parent = 1;
Namhyung Kim930477b2013-04-05 10:26:36 +09001065 } else if (sd->entry == &sort_sym) {
Namhyung Kim1af556402012-09-14 17:35:27 +09001066 sort__has_sym = 1;
Namhyung Kim68f6d022013-12-18 14:21:10 +09001067 } else if (sd->entry == &sort_dso) {
1068 sort__has_dso = 1;
John Kacurdd68ada2009-09-24 18:02:49 +02001069 }
1070
Namhyung Kim2f532d02013-04-03 21:26:10 +09001071 __sort_dimension__add(sd, i);
John Kacurdd68ada2009-09-24 18:02:49 +02001072 return 0;
1073 }
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001074
1075 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1076 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1077
1078 if (strncasecmp(tok, sd->name, strlen(tok)))
1079 continue;
1080
Namhyung Kim55369fc2013-04-01 20:35:20 +09001081 if (sort__mode != SORT_MODE__BRANCH)
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001082 return -EINVAL;
1083
1084 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
1085 sort__has_sym = 1;
1086
Namhyung Kim2f532d02013-04-03 21:26:10 +09001087 __sort_dimension__add(sd, i + __SORT_BRANCH_STACK);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001088 return 0;
1089 }
1090
Namhyung Kimafab87b2013-04-03 21:26:11 +09001091 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1092 struct sort_dimension *sd = &memory_sort_dimensions[i];
1093
1094 if (strncasecmp(tok, sd->name, strlen(tok)))
1095 continue;
1096
1097 if (sort__mode != SORT_MODE__MEMORY)
1098 return -EINVAL;
1099
1100 if (sd->entry == &sort_mem_daddr_sym)
1101 sort__has_sym = 1;
1102
1103 __sort_dimension__add(sd, i + __SORT_MEMORY_MODE);
1104 return 0;
1105 }
1106
John Kacurdd68ada2009-09-24 18:02:49 +02001107 return -ESRCH;
1108}
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001109
Namhyung Kim55309982013-02-06 14:57:16 +09001110int setup_sorting(void)
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001111{
1112 char *tmp, *tok, *str = strdup(sort_order);
Namhyung Kim55309982013-02-06 14:57:16 +09001113 int ret = 0;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001114
Namhyung Kim5936f542013-02-06 14:57:17 +09001115 if (str == NULL) {
1116 error("Not enough memory to setup sort keys");
1117 return -ENOMEM;
1118 }
1119
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001120 for (tok = strtok_r(str, ", ", &tmp);
1121 tok; tok = strtok_r(NULL, ", ", &tmp)) {
Namhyung Kim55309982013-02-06 14:57:16 +09001122 ret = sort_dimension__add(tok);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001123 if (ret == -EINVAL) {
1124 error("Invalid --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001125 break;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001126 } else if (ret == -ESRCH) {
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001127 error("Unknown --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001128 break;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001129 }
1130 }
1131
1132 free(str);
Namhyung Kim55309982013-02-06 14:57:16 +09001133 return ret;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001134}
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001135
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001136static void sort_entry__setup_elide(struct sort_entry *se,
Namhyung Kim08e71542013-04-03 21:26:19 +09001137 struct strlist *list,
1138 const char *list_name, FILE *fp)
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001139{
1140 if (list && strlist__nr_entries(list) == 1) {
1141 if (fp != NULL)
1142 fprintf(fp, "# %s: %s\n", list_name,
1143 strlist__entry(list, 0)->s);
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001144 se->elide = true;
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001145 }
1146}
Namhyung Kim08e71542013-04-03 21:26:19 +09001147
1148void sort__setup_elide(FILE *output)
1149{
Namhyung Kim7524f632013-11-08 17:53:42 +09001150 struct sort_entry *se;
1151
Namhyung Kim08e71542013-04-03 21:26:19 +09001152 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1153 "dso", output);
1154 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list,
1155 "comm", output);
1156 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list,
1157 "symbol", output);
1158
1159 if (sort__mode == SORT_MODE__BRANCH) {
1160 sort_entry__setup_elide(&sort_dso_from,
1161 symbol_conf.dso_from_list,
1162 "dso_from", output);
1163 sort_entry__setup_elide(&sort_dso_to,
1164 symbol_conf.dso_to_list,
1165 "dso_to", output);
1166 sort_entry__setup_elide(&sort_sym_from,
1167 symbol_conf.sym_from_list,
1168 "sym_from", output);
1169 sort_entry__setup_elide(&sort_sym_to,
1170 symbol_conf.sym_to_list,
1171 "sym_to", output);
1172 } else if (sort__mode == SORT_MODE__MEMORY) {
1173 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1174 "symbol_daddr", output);
1175 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1176 "dso_daddr", output);
1177 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1178 "mem", output);
1179 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1180 "local_weight", output);
1181 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1182 "tlb", output);
1183 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1184 "snoop", output);
1185 }
1186
Namhyung Kim7524f632013-11-08 17:53:42 +09001187 /*
1188 * It makes no sense to elide all of sort entries.
1189 * Just revert them to show up again.
1190 */
1191 list_for_each_entry(se, &hist_entry__sort_list, list) {
1192 if (!se->elide)
1193 return;
1194 }
1195
1196 list_for_each_entry(se, &hist_entry__sort_list, list)
1197 se->elide = false;
Namhyung Kim08e71542013-04-03 21:26:19 +09001198}