blob: 9da8931d23948cb12d962867135d691b0e8b83cb [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"
Namhyung Kim8b536992014-03-03 11:46:55 +09005#include "evsel.h"
John Kacurdd68ada2009-09-24 18:02:49 +02006
7regex_t parent_regex;
Arnaldo Carvalho de Meloedb7c602010-05-17 16:22:41 -03008const char default_parent_pattern[] = "^sys_|^do_page_fault";
9const char *parent_pattern = default_parent_pattern;
10const char default_sort_order[] = "comm,dso,symbol";
Namhyung Kim512ae1b2014-03-18 11:31:39 +090011const char default_branch_sort_order[] = "comm,dso_from,symbol_from,dso_to,symbol_to";
12const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
13const char default_top_sort_order[] = "dso,symbol";
14const char default_diff_sort_order[] = "dso,symbol";
15const char *sort_order;
Namhyung Kima7d945b2014-03-04 10:46:34 +090016const char *field_order;
Greg Priceb21484f2012-12-06 21:48:05 -080017regex_t ignore_callees_regex;
18int have_ignore_callees = 0;
Frederic Weisbeckeraf0a6fa2009-10-22 23:23:22 +020019int sort__need_collapse = 0;
20int sort__has_parent = 0;
Namhyung Kim1af556402012-09-14 17:35:27 +090021int sort__has_sym = 0;
Namhyung Kim68f6d022013-12-18 14:21:10 +090022int sort__has_dso = 0;
Namhyung Kim55369fc2013-04-01 20:35:20 +090023enum sort_mode sort__mode = SORT_MODE__NORMAL;
Frederic Weisbeckera4fb5812009-10-22 23:23:23 +020024
John Kacurdd68ada2009-09-24 18:02:49 +020025
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030026static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
John Kacurdd68ada2009-09-24 18:02:49 +020027{
28 int n;
29 va_list ap;
30
31 va_start(ap, fmt);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030032 n = vsnprintf(bf, size, fmt, ap);
Jiri Olsa0ca0c132012-09-06 17:46:56 +020033 if (symbol_conf.field_sep && n > 0) {
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030034 char *sep = bf;
John Kacurdd68ada2009-09-24 18:02:49 +020035
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030036 while (1) {
Jiri Olsa0ca0c132012-09-06 17:46:56 +020037 sep = strchr(sep, *symbol_conf.field_sep);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030038 if (sep == NULL)
39 break;
40 *sep = '.';
John Kacurdd68ada2009-09-24 18:02:49 +020041 }
John Kacurdd68ada2009-09-24 18:02:49 +020042 }
43 va_end(ap);
Anton Blanchardb8327962012-03-07 11:42:49 +110044
45 if (n >= (int)size)
46 return size - 1;
John Kacurdd68ada2009-09-24 18:02:49 +020047 return n;
48}
49
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020050static int64_t cmp_null(const void *l, const void *r)
Frederic Weisbecker872a8782011-06-29 03:14:52 +020051{
52 if (!l && !r)
53 return 0;
54 else if (!l)
55 return -1;
56 else
57 return 1;
58}
59
60/* --sort pid */
61
62static int64_t
63sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
64{
Adrian Hunter38051232013-07-04 16:20:31 +030065 return right->thread->tid - left->thread->tid;
Frederic Weisbecker872a8782011-06-29 03:14:52 +020066}
67
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -030068static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030069 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +020070{
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020071 const char *comm = thread__comm_str(he->thread);
Namhyung Kimfb29a332012-12-27 18:11:40 +090072 return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020073 comm ?: "", he->thread->tid);
John Kacurdd68ada2009-09-24 18:02:49 +020074}
75
Frederic Weisbecker872a8782011-06-29 03:14:52 +020076struct sort_entry sort_thread = {
77 .se_header = "Command: Pid",
78 .se_cmp = sort__thread_cmp,
79 .se_snprintf = hist_entry__thread_snprintf,
80 .se_width_idx = HISTC_THREAD,
81};
82
83/* --sort comm */
84
85static int64_t
86sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
87{
Frederic Weisbeckerfedd63d2013-09-11 17:18:09 +020088 /* Compare the addr that should be unique among comm */
Namhyung Kim4dfced32013-09-13 16:28:57 +090089 return comm__str(right->comm) - comm__str(left->comm);
Frederic Weisbecker872a8782011-06-29 03:14:52 +020090}
91
92static int64_t
93sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
94{
Namhyung Kim4dfced32013-09-13 16:28:57 +090095 /* Compare the addr that should be unique among comm */
96 return comm__str(right->comm) - comm__str(left->comm);
Frederic Weisbecker872a8782011-06-29 03:14:52 +020097}
98
Namhyung Kim202e7a62014-03-04 11:01:41 +090099static int64_t
100sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
101{
102 return strcmp(comm__str(right->comm), comm__str(left->comm));
103}
104
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300105static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300106 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +0200107{
Namhyung Kim4dfced32013-09-13 16:28:57 +0900108 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm));
John Kacurdd68ada2009-09-24 18:02:49 +0200109}
110
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900111struct sort_entry sort_comm = {
112 .se_header = "Command",
113 .se_cmp = sort__comm_cmp,
114 .se_collapse = sort__comm_collapse,
Namhyung Kim202e7a62014-03-04 11:01:41 +0900115 .se_sort = sort__comm_sort,
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900116 .se_snprintf = hist_entry__comm_snprintf,
117 .se_width_idx = HISTC_COMM,
118};
119
120/* --sort dso */
121
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100122static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
John Kacurdd68ada2009-09-24 18:02:49 +0200123{
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100124 struct dso *dso_l = map_l ? map_l->dso : NULL;
125 struct dso *dso_r = map_r ? map_r->dso : NULL;
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300126 const char *dso_name_l, *dso_name_r;
John Kacurdd68ada2009-09-24 18:02:49 +0200127
128 if (!dso_l || !dso_r)
Namhyung Kim202e7a62014-03-04 11:01:41 +0900129 return cmp_null(dso_r, dso_l);
John Kacurdd68ada2009-09-24 18:02:49 +0200130
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300131 if (verbose) {
132 dso_name_l = dso_l->long_name;
133 dso_name_r = dso_r->long_name;
134 } else {
135 dso_name_l = dso_l->short_name;
136 dso_name_r = dso_r->short_name;
137 }
138
139 return strcmp(dso_name_l, dso_name_r);
John Kacurdd68ada2009-09-24 18:02:49 +0200140}
141
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100142static int64_t
143sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
John Kacurdd68ada2009-09-24 18:02:49 +0200144{
Namhyung Kim202e7a62014-03-04 11:01:41 +0900145 return _sort__dso_cmp(right->ms.map, left->ms.map);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100146}
147
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100148static int _hist_entry__dso_snprintf(struct map *map, char *bf,
149 size_t size, unsigned int width)
150{
151 if (map && map->dso) {
152 const char *dso_name = !verbose ? map->dso->short_name :
153 map->dso->long_name;
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300154 return repsep_snprintf(bf, size, "%-*s", width, dso_name);
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300155 }
John Kacurdd68ada2009-09-24 18:02:49 +0200156
Ian Munsie1437a302010-12-06 13:37:04 +1100157 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
John Kacurdd68ada2009-09-24 18:02:49 +0200158}
159
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300160static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100161 size_t size, unsigned int width)
162{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300163 return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100164}
165
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900166struct sort_entry sort_dso = {
167 .se_header = "Shared Object",
168 .se_cmp = sort__dso_cmp,
169 .se_snprintf = hist_entry__dso_snprintf,
170 .se_width_idx = HISTC_DSO,
171};
172
173/* --sort symbol */
174
Namhyung Kim2037be52013-12-18 14:21:09 +0900175static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
176{
177 return (int64_t)(right_ip - left_ip);
178}
179
Namhyung Kim51f27d12013-02-06 14:57:15 +0900180static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900181{
Namhyung Kim51f27d12013-02-06 14:57:15 +0900182 u64 ip_l, ip_r;
183
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900184 if (!sym_l || !sym_r)
185 return cmp_null(sym_l, sym_r);
186
187 if (sym_l == sym_r)
188 return 0;
189
190 ip_l = sym_l->start;
191 ip_r = sym_r->start;
192
193 return (int64_t)(ip_r - ip_l);
194}
195
196static int64_t
197sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
198{
Namhyung Kim09600e02013-10-15 11:01:56 +0900199 int64_t ret;
200
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900201 if (!left->ms.sym && !right->ms.sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900202 return _sort__addr_cmp(left->ip, right->ip);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900203
Namhyung Kim09600e02013-10-15 11:01:56 +0900204 /*
205 * comparing symbol address alone is not enough since it's a
206 * relative address within a dso.
207 */
Namhyung Kim68f6d022013-12-18 14:21:10 +0900208 if (!sort__has_dso) {
209 ret = sort__dso_cmp(left, right);
210 if (ret != 0)
211 return ret;
212 }
Namhyung Kim09600e02013-10-15 11:01:56 +0900213
Namhyung Kim51f27d12013-02-06 14:57:15 +0900214 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900215}
216
Namhyung Kim202e7a62014-03-04 11:01:41 +0900217static int64_t
218sort__sym_sort(struct hist_entry *left, struct hist_entry *right)
219{
220 if (!left->ms.sym || !right->ms.sym)
221 return cmp_null(left->ms.sym, right->ms.sym);
222
223 return strcmp(right->ms.sym->name, left->ms.sym->name);
224}
225
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100226static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
227 u64 ip, char level, char *bf, size_t size,
Namhyung Kim43355522012-12-27 18:11:39 +0900228 unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100229{
230 size_t ret = 0;
231
232 if (verbose) {
233 char o = map ? dso__symtab_origin(map->dso) : '!';
234 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
Namhyung Kimded19d52013-04-01 20:35:19 +0900235 BITS_PER_LONG / 4 + 2, ip, o);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100236 }
237
238 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
Stephane Eranian98a3b322013-01-24 16:10:35 +0100239 if (sym && map) {
240 if (map->type == MAP__VARIABLE) {
241 ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
242 ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
Namhyung Kim62667742013-01-24 16:10:42 +0100243 ip - map->unmap_ip(map, sym->start));
Stephane Eranian98a3b322013-01-24 16:10:35 +0100244 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
245 width - ret, "");
246 } else {
247 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
248 width - ret,
249 sym->name);
250 }
251 } else {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100252 size_t len = BITS_PER_LONG / 4;
253 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
254 len, ip);
255 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
256 width - ret, "");
257 }
258
259 return ret;
260}
261
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300262static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900263 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100264{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300265 return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
266 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100267}
John Kacurdd68ada2009-09-24 18:02:49 +0200268
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200269struct sort_entry sort_sym = {
270 .se_header = "Symbol",
271 .se_cmp = sort__sym_cmp,
Namhyung Kim202e7a62014-03-04 11:01:41 +0900272 .se_sort = sort__sym_sort,
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200273 .se_snprintf = hist_entry__sym_snprintf,
274 .se_width_idx = HISTC_SYMBOL,
275};
John Kacurdd68ada2009-09-24 18:02:49 +0200276
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300277/* --sort srcline */
278
279static int64_t
280sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
281{
Namhyung Kim4adcc432013-09-11 14:09:33 +0900282 if (!left->srcline) {
283 if (!left->ms.map)
284 left->srcline = SRCLINE_UNKNOWN;
285 else {
286 struct map *map = left->ms.map;
287 left->srcline = get_srcline(map->dso,
288 map__rip_2objdump(map, left->ip));
289 }
290 }
291 if (!right->srcline) {
292 if (!right->ms.map)
293 right->srcline = SRCLINE_UNKNOWN;
294 else {
295 struct map *map = right->ms.map;
296 right->srcline = get_srcline(map->dso,
297 map__rip_2objdump(map, right->ip));
298 }
299 }
Namhyung Kim202e7a62014-03-04 11:01:41 +0900300 return strcmp(right->srcline, left->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300301}
302
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300303static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300304 size_t size,
305 unsigned int width __maybe_unused)
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300306{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300307 return repsep_snprintf(bf, size, "%s", he->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300308}
309
310struct sort_entry sort_srcline = {
311 .se_header = "Source:Line",
312 .se_cmp = sort__srcline_cmp,
313 .se_snprintf = hist_entry__srcline_snprintf,
314 .se_width_idx = HISTC_SRCLINE,
315};
316
John Kacurdd68ada2009-09-24 18:02:49 +0200317/* --sort parent */
318
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200319static int64_t
John Kacurdd68ada2009-09-24 18:02:49 +0200320sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
321{
322 struct symbol *sym_l = left->parent;
323 struct symbol *sym_r = right->parent;
324
325 if (!sym_l || !sym_r)
326 return cmp_null(sym_l, sym_r);
327
Namhyung Kim202e7a62014-03-04 11:01:41 +0900328 return strcmp(sym_r->name, sym_l->name);
John Kacurdd68ada2009-09-24 18:02:49 +0200329}
330
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300331static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300332 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +0200333{
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300334 return repsep_snprintf(bf, size, "%-*s", width,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300335 he->parent ? he->parent->name : "[other]");
John Kacurdd68ada2009-09-24 18:02:49 +0200336}
337
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200338struct sort_entry sort_parent = {
339 .se_header = "Parent symbol",
340 .se_cmp = sort__parent_cmp,
341 .se_snprintf = hist_entry__parent_snprintf,
342 .se_width_idx = HISTC_PARENT,
343};
344
Arun Sharmaf60f3592010-06-04 11:27:10 -0300345/* --sort cpu */
346
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200347static int64_t
Arun Sharmaf60f3592010-06-04 11:27:10 -0300348sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
349{
350 return right->cpu - left->cpu;
351}
352
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300353static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
354 size_t size, unsigned int width)
Arun Sharmaf60f3592010-06-04 11:27:10 -0300355{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300356 return repsep_snprintf(bf, size, "%*d", width, he->cpu);
Arun Sharmaf60f3592010-06-04 11:27:10 -0300357}
358
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200359struct sort_entry sort_cpu = {
360 .se_header = "CPU",
361 .se_cmp = sort__cpu_cmp,
362 .se_snprintf = hist_entry__cpu_snprintf,
363 .se_width_idx = HISTC_CPU,
364};
365
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900366/* sort keys for branch stacks */
367
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100368static int64_t
369sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
370{
371 return _sort__dso_cmp(left->branch_info->from.map,
372 right->branch_info->from.map);
373}
374
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300375static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100376 size_t size, unsigned int width)
377{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300378 return _hist_entry__dso_snprintf(he->branch_info->from.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100379 bf, size, width);
380}
381
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100382static int64_t
383sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
384{
385 return _sort__dso_cmp(left->branch_info->to.map,
386 right->branch_info->to.map);
387}
388
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300389static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100390 size_t size, unsigned int width)
391{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300392 return _hist_entry__dso_snprintf(he->branch_info->to.map,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100393 bf, size, width);
394}
395
396static int64_t
397sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
398{
399 struct addr_map_symbol *from_l = &left->branch_info->from;
400 struct addr_map_symbol *from_r = &right->branch_info->from;
401
402 if (!from_l->sym && !from_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900403 return _sort__addr_cmp(from_l->addr, from_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100404
Namhyung Kim51f27d12013-02-06 14:57:15 +0900405 return _sort__sym_cmp(from_l->sym, from_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100406}
407
408static int64_t
409sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
410{
411 struct addr_map_symbol *to_l = &left->branch_info->to;
412 struct addr_map_symbol *to_r = &right->branch_info->to;
413
414 if (!to_l->sym && !to_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900415 return _sort__addr_cmp(to_l->addr, to_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100416
Namhyung Kim51f27d12013-02-06 14:57:15 +0900417 return _sort__sym_cmp(to_l->sym, to_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100418}
419
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300420static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900421 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100422{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300423 struct addr_map_symbol *from = &he->branch_info->from;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100424 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300425 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100426
427}
428
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300429static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900430 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100431{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300432 struct addr_map_symbol *to = &he->branch_info->to;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100433 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300434 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100435
436}
437
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900438struct sort_entry sort_dso_from = {
439 .se_header = "Source Shared Object",
440 .se_cmp = sort__dso_from_cmp,
441 .se_snprintf = hist_entry__dso_from_snprintf,
442 .se_width_idx = HISTC_DSO_FROM,
443};
444
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100445struct sort_entry sort_dso_to = {
446 .se_header = "Target Shared Object",
447 .se_cmp = sort__dso_to_cmp,
448 .se_snprintf = hist_entry__dso_to_snprintf,
449 .se_width_idx = HISTC_DSO_TO,
450};
451
452struct sort_entry sort_sym_from = {
453 .se_header = "Source Symbol",
454 .se_cmp = sort__sym_from_cmp,
455 .se_snprintf = hist_entry__sym_from_snprintf,
456 .se_width_idx = HISTC_SYMBOL_FROM,
457};
458
459struct sort_entry sort_sym_to = {
460 .se_header = "Target Symbol",
461 .se_cmp = sort__sym_to_cmp,
462 .se_snprintf = hist_entry__sym_to_snprintf,
463 .se_width_idx = HISTC_SYMBOL_TO,
464};
465
466static int64_t
467sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
468{
469 const unsigned char mp = left->branch_info->flags.mispred !=
470 right->branch_info->flags.mispred;
471 const unsigned char p = left->branch_info->flags.predicted !=
472 right->branch_info->flags.predicted;
473
474 return mp || p;
475}
476
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300477static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100478 size_t size, unsigned int width){
479 static const char *out = "N/A";
480
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300481 if (he->branch_info->flags.predicted)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100482 out = "N";
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300483 else if (he->branch_info->flags.mispred)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100484 out = "Y";
485
486 return repsep_snprintf(bf, size, "%-*s", width, out);
487}
488
Stephane Eranian98a3b322013-01-24 16:10:35 +0100489/* --sort daddr_sym */
490static int64_t
491sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
492{
493 uint64_t l = 0, r = 0;
494
495 if (left->mem_info)
496 l = left->mem_info->daddr.addr;
497 if (right->mem_info)
498 r = right->mem_info->daddr.addr;
499
500 return (int64_t)(r - l);
501}
502
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300503static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100504 size_t size, unsigned int width)
505{
506 uint64_t addr = 0;
507 struct map *map = NULL;
508 struct symbol *sym = NULL;
509
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300510 if (he->mem_info) {
511 addr = he->mem_info->daddr.addr;
512 map = he->mem_info->daddr.map;
513 sym = he->mem_info->daddr.sym;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100514 }
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300515 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100516 width);
517}
518
519static int64_t
520sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
521{
522 struct map *map_l = NULL;
523 struct map *map_r = NULL;
524
525 if (left->mem_info)
526 map_l = left->mem_info->daddr.map;
527 if (right->mem_info)
528 map_r = right->mem_info->daddr.map;
529
530 return _sort__dso_cmp(map_l, map_r);
531}
532
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300533static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100534 size_t size, unsigned int width)
535{
536 struct map *map = NULL;
537
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300538 if (he->mem_info)
539 map = he->mem_info->daddr.map;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100540
541 return _hist_entry__dso_snprintf(map, bf, size, width);
542}
543
544static int64_t
545sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
546{
547 union perf_mem_data_src data_src_l;
548 union perf_mem_data_src data_src_r;
549
550 if (left->mem_info)
551 data_src_l = left->mem_info->data_src;
552 else
553 data_src_l.mem_lock = PERF_MEM_LOCK_NA;
554
555 if (right->mem_info)
556 data_src_r = right->mem_info->data_src;
557 else
558 data_src_r.mem_lock = PERF_MEM_LOCK_NA;
559
560 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
561}
562
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300563static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100564 size_t size, unsigned int width)
565{
566 const char *out;
567 u64 mask = PERF_MEM_LOCK_NA;
568
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300569 if (he->mem_info)
570 mask = he->mem_info->data_src.mem_lock;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100571
572 if (mask & PERF_MEM_LOCK_NA)
573 out = "N/A";
574 else if (mask & PERF_MEM_LOCK_LOCKED)
575 out = "Yes";
576 else
577 out = "No";
578
579 return repsep_snprintf(bf, size, "%-*s", width, out);
580}
581
582static int64_t
583sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
584{
585 union perf_mem_data_src data_src_l;
586 union perf_mem_data_src data_src_r;
587
588 if (left->mem_info)
589 data_src_l = left->mem_info->data_src;
590 else
591 data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
592
593 if (right->mem_info)
594 data_src_r = right->mem_info->data_src;
595 else
596 data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
597
598 return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
599}
600
601static const char * const tlb_access[] = {
602 "N/A",
603 "HIT",
604 "MISS",
605 "L1",
606 "L2",
607 "Walker",
608 "Fault",
609};
610#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
611
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300612static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100613 size_t size, unsigned int width)
614{
615 char out[64];
616 size_t sz = sizeof(out) - 1; /* -1 for null termination */
617 size_t l = 0, i;
618 u64 m = PERF_MEM_TLB_NA;
619 u64 hit, miss;
620
621 out[0] = '\0';
622
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300623 if (he->mem_info)
624 m = he->mem_info->data_src.mem_dtlb;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100625
626 hit = m & PERF_MEM_TLB_HIT;
627 miss = m & PERF_MEM_TLB_MISS;
628
629 /* already taken care of */
630 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
631
632 for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
633 if (!(m & 0x1))
634 continue;
635 if (l) {
636 strcat(out, " or ");
637 l += 4;
638 }
639 strncat(out, tlb_access[i], sz - l);
640 l += strlen(tlb_access[i]);
641 }
642 if (*out == '\0')
643 strcpy(out, "N/A");
644 if (hit)
645 strncat(out, " hit", sz - l);
646 if (miss)
647 strncat(out, " miss", sz - l);
648
649 return repsep_snprintf(bf, size, "%-*s", width, out);
650}
651
652static int64_t
653sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
654{
655 union perf_mem_data_src data_src_l;
656 union perf_mem_data_src data_src_r;
657
658 if (left->mem_info)
659 data_src_l = left->mem_info->data_src;
660 else
661 data_src_l.mem_lvl = PERF_MEM_LVL_NA;
662
663 if (right->mem_info)
664 data_src_r = right->mem_info->data_src;
665 else
666 data_src_r.mem_lvl = PERF_MEM_LVL_NA;
667
668 return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
669}
670
671static const char * const mem_lvl[] = {
672 "N/A",
673 "HIT",
674 "MISS",
675 "L1",
676 "LFB",
677 "L2",
678 "L3",
679 "Local RAM",
680 "Remote RAM (1 hop)",
681 "Remote RAM (2 hops)",
682 "Remote Cache (1 hop)",
683 "Remote Cache (2 hops)",
684 "I/O",
685 "Uncached",
686};
687#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
688
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300689static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100690 size_t size, unsigned int width)
691{
692 char out[64];
693 size_t sz = sizeof(out) - 1; /* -1 for null termination */
694 size_t i, l = 0;
695 u64 m = PERF_MEM_LVL_NA;
696 u64 hit, miss;
697
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300698 if (he->mem_info)
699 m = he->mem_info->data_src.mem_lvl;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100700
701 out[0] = '\0';
702
703 hit = m & PERF_MEM_LVL_HIT;
704 miss = m & PERF_MEM_LVL_MISS;
705
706 /* already taken care of */
707 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
708
709 for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
710 if (!(m & 0x1))
711 continue;
712 if (l) {
713 strcat(out, " or ");
714 l += 4;
715 }
716 strncat(out, mem_lvl[i], sz - l);
717 l += strlen(mem_lvl[i]);
718 }
719 if (*out == '\0')
720 strcpy(out, "N/A");
721 if (hit)
722 strncat(out, " hit", sz - l);
723 if (miss)
724 strncat(out, " miss", sz - l);
725
726 return repsep_snprintf(bf, size, "%-*s", width, out);
727}
728
729static int64_t
730sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
731{
732 union perf_mem_data_src data_src_l;
733 union perf_mem_data_src data_src_r;
734
735 if (left->mem_info)
736 data_src_l = left->mem_info->data_src;
737 else
738 data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
739
740 if (right->mem_info)
741 data_src_r = right->mem_info->data_src;
742 else
743 data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
744
745 return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
746}
747
748static const char * const snoop_access[] = {
749 "N/A",
750 "None",
751 "Miss",
752 "Hit",
753 "HitM",
754};
755#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
756
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300757static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100758 size_t size, unsigned int width)
759{
760 char out[64];
761 size_t sz = sizeof(out) - 1; /* -1 for null termination */
762 size_t i, l = 0;
763 u64 m = PERF_MEM_SNOOP_NA;
764
765 out[0] = '\0';
766
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300767 if (he->mem_info)
768 m = he->mem_info->data_src.mem_snoop;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100769
770 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
771 if (!(m & 0x1))
772 continue;
773 if (l) {
774 strcat(out, " or ");
775 l += 4;
776 }
777 strncat(out, snoop_access[i], sz - l);
778 l += strlen(snoop_access[i]);
779 }
780
781 if (*out == '\0')
782 strcpy(out, "N/A");
783
784 return repsep_snprintf(bf, size, "%-*s", width, out);
785}
786
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100787struct sort_entry sort_mispredict = {
788 .se_header = "Branch Mispredicted",
789 .se_cmp = sort__mispredict_cmp,
790 .se_snprintf = hist_entry__mispredict_snprintf,
791 .se_width_idx = HISTC_MISPREDICT,
792};
793
Andi Kleen05484292013-01-24 16:10:29 +0100794static u64 he_weight(struct hist_entry *he)
795{
796 return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
797}
798
799static int64_t
800sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
801{
802 return he_weight(left) - he_weight(right);
803}
804
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300805static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100806 size_t size, unsigned int width)
807{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300808 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
Andi Kleen05484292013-01-24 16:10:29 +0100809}
810
811struct sort_entry sort_local_weight = {
812 .se_header = "Local Weight",
813 .se_cmp = sort__local_weight_cmp,
814 .se_snprintf = hist_entry__local_weight_snprintf,
815 .se_width_idx = HISTC_LOCAL_WEIGHT,
816};
817
818static int64_t
819sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
820{
821 return left->stat.weight - right->stat.weight;
822}
823
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300824static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +0100825 size_t size, unsigned int width)
826{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300827 return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
Andi Kleen05484292013-01-24 16:10:29 +0100828}
829
830struct sort_entry sort_global_weight = {
831 .se_header = "Weight",
832 .se_cmp = sort__global_weight_cmp,
833 .se_snprintf = hist_entry__global_weight_snprintf,
834 .se_width_idx = HISTC_GLOBAL_WEIGHT,
835};
836
Stephane Eranian98a3b322013-01-24 16:10:35 +0100837struct sort_entry sort_mem_daddr_sym = {
838 .se_header = "Data Symbol",
839 .se_cmp = sort__daddr_cmp,
840 .se_snprintf = hist_entry__daddr_snprintf,
841 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
842};
843
844struct sort_entry sort_mem_daddr_dso = {
845 .se_header = "Data Object",
846 .se_cmp = sort__dso_daddr_cmp,
847 .se_snprintf = hist_entry__dso_daddr_snprintf,
848 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
849};
850
851struct sort_entry sort_mem_locked = {
852 .se_header = "Locked",
853 .se_cmp = sort__locked_cmp,
854 .se_snprintf = hist_entry__locked_snprintf,
855 .se_width_idx = HISTC_MEM_LOCKED,
856};
857
858struct sort_entry sort_mem_tlb = {
859 .se_header = "TLB access",
860 .se_cmp = sort__tlb_cmp,
861 .se_snprintf = hist_entry__tlb_snprintf,
862 .se_width_idx = HISTC_MEM_TLB,
863};
864
865struct sort_entry sort_mem_lvl = {
866 .se_header = "Memory access",
867 .se_cmp = sort__lvl_cmp,
868 .se_snprintf = hist_entry__lvl_snprintf,
869 .se_width_idx = HISTC_MEM_LVL,
870};
871
872struct sort_entry sort_mem_snoop = {
873 .se_header = "Snoop",
874 .se_cmp = sort__snoop_cmp,
875 .se_snprintf = hist_entry__snoop_snprintf,
876 .se_width_idx = HISTC_MEM_SNOOP,
877};
878
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700879static int64_t
880sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
881{
882 return left->branch_info->flags.abort !=
883 right->branch_info->flags.abort;
884}
885
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300886static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700887 size_t size, unsigned int width)
888{
889 static const char *out = ".";
890
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300891 if (he->branch_info->flags.abort)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700892 out = "A";
893 return repsep_snprintf(bf, size, "%-*s", width, out);
894}
895
896struct sort_entry sort_abort = {
897 .se_header = "Transaction abort",
898 .se_cmp = sort__abort_cmp,
899 .se_snprintf = hist_entry__abort_snprintf,
900 .se_width_idx = HISTC_ABORT,
901};
902
903static int64_t
904sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
905{
906 return left->branch_info->flags.in_tx !=
907 right->branch_info->flags.in_tx;
908}
909
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300910static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700911 size_t size, unsigned int width)
912{
913 static const char *out = ".";
914
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300915 if (he->branch_info->flags.in_tx)
Andi Kleenf5d05bc2013-09-20 07:40:41 -0700916 out = "T";
917
918 return repsep_snprintf(bf, size, "%-*s", width, out);
919}
920
921struct sort_entry sort_in_tx = {
922 .se_header = "Branch in transaction",
923 .se_cmp = sort__in_tx_cmp,
924 .se_snprintf = hist_entry__in_tx_snprintf,
925 .se_width_idx = HISTC_IN_TX,
926};
927
Andi Kleen475eeab2013-09-20 07:40:43 -0700928static int64_t
929sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
930{
931 return left->transaction - right->transaction;
932}
933
934static inline char *add_str(char *p, const char *str)
935{
936 strcpy(p, str);
937 return p + strlen(str);
938}
939
940static struct txbit {
941 unsigned flag;
942 const char *name;
943 int skip_for_len;
944} txbits[] = {
945 { PERF_TXN_ELISION, "EL ", 0 },
946 { PERF_TXN_TRANSACTION, "TX ", 1 },
947 { PERF_TXN_SYNC, "SYNC ", 1 },
948 { PERF_TXN_ASYNC, "ASYNC ", 0 },
949 { PERF_TXN_RETRY, "RETRY ", 0 },
950 { PERF_TXN_CONFLICT, "CON ", 0 },
951 { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
952 { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
953 { 0, NULL, 0 }
954};
955
956int hist_entry__transaction_len(void)
957{
958 int i;
959 int len = 0;
960
961 for (i = 0; txbits[i].name; i++) {
962 if (!txbits[i].skip_for_len)
963 len += strlen(txbits[i].name);
964 }
965 len += 4; /* :XX<space> */
966 return len;
967}
968
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300969static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
Andi Kleen475eeab2013-09-20 07:40:43 -0700970 size_t size, unsigned int width)
971{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300972 u64 t = he->transaction;
Andi Kleen475eeab2013-09-20 07:40:43 -0700973 char buf[128];
974 char *p = buf;
975 int i;
976
977 buf[0] = 0;
978 for (i = 0; txbits[i].name; i++)
979 if (txbits[i].flag & t)
980 p = add_str(p, txbits[i].name);
981 if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
982 p = add_str(p, "NEITHER ");
983 if (t & PERF_TXN_ABORT_MASK) {
984 sprintf(p, ":%" PRIx64,
985 (t & PERF_TXN_ABORT_MASK) >>
986 PERF_TXN_ABORT_SHIFT);
987 p += strlen(p);
988 }
989
990 return repsep_snprintf(bf, size, "%-*s", width, buf);
991}
992
993struct sort_entry sort_transaction = {
994 .se_header = "Transaction ",
995 .se_cmp = sort__transaction_cmp,
996 .se_snprintf = hist_entry__transaction_snprintf,
997 .se_width_idx = HISTC_TRANSACTION,
998};
999
Frederic Weisbecker872a8782011-06-29 03:14:52 +02001000struct sort_dimension {
1001 const char *name;
1002 struct sort_entry *entry;
1003 int taken;
1004};
1005
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001006#define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
1007
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001008static struct sort_dimension common_sort_dimensions[] = {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001009 DIM(SORT_PID, "pid", sort_thread),
1010 DIM(SORT_COMM, "comm", sort_comm),
1011 DIM(SORT_DSO, "dso", sort_dso),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001012 DIM(SORT_SYM, "symbol", sort_sym),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001013 DIM(SORT_PARENT, "parent", sort_parent),
1014 DIM(SORT_CPU, "cpu", sort_cpu),
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -03001015 DIM(SORT_SRCLINE, "srcline", sort_srcline),
Andi Kleenf9ea55d2013-07-18 15:58:53 -07001016 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
1017 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
Andi Kleen475eeab2013-09-20 07:40:43 -07001018 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
Frederic Weisbecker872a8782011-06-29 03:14:52 +02001019};
1020
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001021#undef DIM
1022
1023#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
1024
1025static struct sort_dimension bstack_sort_dimensions[] = {
1026 DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
1027 DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
1028 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
1029 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
1030 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001031 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1032 DIM(SORT_ABORT, "abort", sort_abort),
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001033};
1034
1035#undef DIM
1036
Namhyung Kimafab87b2013-04-03 21:26:11 +09001037#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
1038
1039static struct sort_dimension memory_sort_dimensions[] = {
Namhyung Kimafab87b2013-04-03 21:26:11 +09001040 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
1041 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1042 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1043 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1044 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1045 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
1046};
1047
1048#undef DIM
1049
Namhyung Kima2ce0672014-03-04 09:06:42 +09001050struct hpp_dimension {
1051 const char *name;
1052 struct perf_hpp_fmt *fmt;
1053 int taken;
1054};
1055
1056#define DIM(d, n) { .name = n, .fmt = &perf_hpp__format[d], }
1057
1058static struct hpp_dimension hpp_sort_dimensions[] = {
1059 DIM(PERF_HPP__OVERHEAD, "overhead"),
1060 DIM(PERF_HPP__OVERHEAD_SYS, "overhead_sys"),
1061 DIM(PERF_HPP__OVERHEAD_US, "overhead_us"),
1062 DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"),
1063 DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"),
Namhyung Kim594dcbf2013-10-30 16:06:59 +09001064 DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
Namhyung Kima2ce0672014-03-04 09:06:42 +09001065 DIM(PERF_HPP__SAMPLES, "sample"),
1066 DIM(PERF_HPP__PERIOD, "period"),
1067};
1068
1069#undef DIM
1070
Namhyung Kim8b536992014-03-03 11:46:55 +09001071struct hpp_sort_entry {
1072 struct perf_hpp_fmt hpp;
1073 struct sort_entry *se;
1074};
1075
Namhyung Kima7d945b2014-03-04 10:46:34 +09001076bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1077{
1078 struct hpp_sort_entry *hse_a;
1079 struct hpp_sort_entry *hse_b;
1080
1081 if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b))
1082 return false;
1083
1084 hse_a = container_of(a, struct hpp_sort_entry, hpp);
1085 hse_b = container_of(b, struct hpp_sort_entry, hpp);
1086
1087 return hse_a->se == hse_b->se;
1088}
1089
Namhyung Kim678a5002014-03-20 11:18:54 +09001090void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1091{
1092 struct hpp_sort_entry *hse;
1093
1094 if (!perf_hpp__is_sort_entry(fmt))
1095 return;
1096
1097 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1098 hists__new_col_len(hists, hse->se->se_width_idx,
1099 strlen(hse->se->se_header));
1100}
1101
Namhyung Kim8b536992014-03-03 11:46:55 +09001102static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1103 struct perf_evsel *evsel)
1104{
1105 struct hpp_sort_entry *hse;
1106 size_t len;
1107
1108 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1109 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1110
1111 return scnprintf(hpp->buf, hpp->size, "%*s", len, hse->se->se_header);
1112}
1113
1114static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1115 struct perf_hpp *hpp __maybe_unused,
1116 struct perf_evsel *evsel)
1117{
1118 struct hpp_sort_entry *hse;
1119
1120 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1121
1122 return hists__col_len(&evsel->hists, hse->se->se_width_idx);
1123}
1124
1125static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1126 struct hist_entry *he)
1127{
1128 struct hpp_sort_entry *hse;
1129 size_t len;
1130
1131 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1132 len = hists__col_len(he->hists, hse->se->se_width_idx);
1133
1134 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1135}
1136
Namhyung Kima7d945b2014-03-04 10:46:34 +09001137static struct hpp_sort_entry *
1138__sort_dimension__alloc_hpp(struct sort_dimension *sd)
Namhyung Kim8b536992014-03-03 11:46:55 +09001139{
1140 struct hpp_sort_entry *hse;
1141
1142 hse = malloc(sizeof(*hse));
1143 if (hse == NULL) {
1144 pr_err("Memory allocation failed\n");
Namhyung Kima7d945b2014-03-04 10:46:34 +09001145 return NULL;
Namhyung Kim8b536992014-03-03 11:46:55 +09001146 }
1147
1148 hse->se = sd->entry;
1149 hse->hpp.header = __sort__hpp_header;
1150 hse->hpp.width = __sort__hpp_width;
1151 hse->hpp.entry = __sort__hpp_entry;
1152 hse->hpp.color = NULL;
1153
1154 hse->hpp.cmp = sd->entry->se_cmp;
1155 hse->hpp.collapse = sd->entry->se_collapse ? : sd->entry->se_cmp;
Namhyung Kim202e7a62014-03-04 11:01:41 +09001156 hse->hpp.sort = sd->entry->se_sort ? : hse->hpp.collapse;
Namhyung Kim8b536992014-03-03 11:46:55 +09001157
1158 INIT_LIST_HEAD(&hse->hpp.list);
1159 INIT_LIST_HEAD(&hse->hpp.sort_list);
1160
Namhyung Kima7d945b2014-03-04 10:46:34 +09001161 return hse;
1162}
1163
1164bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format)
1165{
1166 return format->header == __sort__hpp_header;
1167}
1168
1169static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd)
1170{
1171 struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1172
1173 if (hse == NULL)
1174 return -1;
1175
Namhyung Kim8b536992014-03-03 11:46:55 +09001176 perf_hpp__register_sort_field(&hse->hpp);
1177 return 0;
1178}
1179
Namhyung Kima7d945b2014-03-04 10:46:34 +09001180static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
1181{
1182 struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1183
1184 if (hse == NULL)
1185 return -1;
1186
1187 perf_hpp__column_register(&hse->hpp);
1188 return 0;
1189}
1190
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001191static int __sort_dimension__add(struct sort_dimension *sd)
Namhyung Kim2f532d092013-04-03 21:26:10 +09001192{
1193 if (sd->taken)
Namhyung Kim8b536992014-03-03 11:46:55 +09001194 return 0;
1195
Namhyung Kima7d945b2014-03-04 10:46:34 +09001196 if (__sort_dimension__add_hpp_sort(sd) < 0)
Namhyung Kim8b536992014-03-03 11:46:55 +09001197 return -1;
Namhyung Kim2f532d092013-04-03 21:26:10 +09001198
1199 if (sd->entry->se_collapse)
1200 sort__need_collapse = 1;
1201
Namhyung Kim2f532d092013-04-03 21:26:10 +09001202 sd->taken = 1;
Namhyung Kim8b536992014-03-03 11:46:55 +09001203
1204 return 0;
Namhyung Kim2f532d092013-04-03 21:26:10 +09001205}
1206
Namhyung Kima2ce0672014-03-04 09:06:42 +09001207static int __hpp_dimension__add(struct hpp_dimension *hd)
1208{
1209 if (!hd->taken) {
1210 hd->taken = 1;
1211
1212 perf_hpp__register_sort_field(hd->fmt);
1213 }
1214 return 0;
1215}
1216
Namhyung Kima7d945b2014-03-04 10:46:34 +09001217static int __sort_dimension__add_output(struct sort_dimension *sd)
1218{
1219 if (sd->taken)
1220 return 0;
1221
1222 if (__sort_dimension__add_hpp_output(sd) < 0)
1223 return -1;
1224
1225 sd->taken = 1;
1226 return 0;
1227}
1228
1229static int __hpp_dimension__add_output(struct hpp_dimension *hd)
1230{
1231 if (!hd->taken) {
1232 hd->taken = 1;
1233
1234 perf_hpp__column_register(hd->fmt);
1235 }
1236 return 0;
1237}
1238
John Kacurdd68ada2009-09-24 18:02:49 +02001239int sort_dimension__add(const char *tok)
1240{
1241 unsigned int i;
1242
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001243 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1244 struct sort_dimension *sd = &common_sort_dimensions[i];
John Kacurdd68ada2009-09-24 18:02:49 +02001245
John Kacurdd68ada2009-09-24 18:02:49 +02001246 if (strncasecmp(tok, sd->name, strlen(tok)))
1247 continue;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001248
John Kacurdd68ada2009-09-24 18:02:49 +02001249 if (sd->entry == &sort_parent) {
1250 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
1251 if (ret) {
1252 char err[BUFSIZ];
1253
1254 regerror(ret, &parent_regex, err, sizeof(err));
Arnaldo Carvalho de Melo2aefa4f2010-04-02 12:30:57 -03001255 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
1256 return -EINVAL;
John Kacurdd68ada2009-09-24 18:02:49 +02001257 }
1258 sort__has_parent = 1;
Namhyung Kim930477b2013-04-05 10:26:36 +09001259 } else if (sd->entry == &sort_sym) {
Namhyung Kim1af556402012-09-14 17:35:27 +09001260 sort__has_sym = 1;
Namhyung Kim68f6d022013-12-18 14:21:10 +09001261 } else if (sd->entry == &sort_dso) {
1262 sort__has_dso = 1;
John Kacurdd68ada2009-09-24 18:02:49 +02001263 }
1264
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001265 return __sort_dimension__add(sd);
John Kacurdd68ada2009-09-24 18:02:49 +02001266 }
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001267
Namhyung Kima2ce0672014-03-04 09:06:42 +09001268 for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
1269 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
1270
1271 if (strncasecmp(tok, hd->name, strlen(tok)))
1272 continue;
1273
1274 return __hpp_dimension__add(hd);
1275 }
1276
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001277 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1278 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1279
1280 if (strncasecmp(tok, sd->name, strlen(tok)))
1281 continue;
1282
Namhyung Kim55369fc2013-04-01 20:35:20 +09001283 if (sort__mode != SORT_MODE__BRANCH)
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001284 return -EINVAL;
1285
1286 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
1287 sort__has_sym = 1;
1288
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001289 __sort_dimension__add(sd);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001290 return 0;
1291 }
1292
Namhyung Kimafab87b2013-04-03 21:26:11 +09001293 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1294 struct sort_dimension *sd = &memory_sort_dimensions[i];
1295
1296 if (strncasecmp(tok, sd->name, strlen(tok)))
1297 continue;
1298
1299 if (sort__mode != SORT_MODE__MEMORY)
1300 return -EINVAL;
1301
1302 if (sd->entry == &sort_mem_daddr_sym)
1303 sort__has_sym = 1;
1304
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001305 __sort_dimension__add(sd);
Namhyung Kimafab87b2013-04-03 21:26:11 +09001306 return 0;
1307 }
1308
John Kacurdd68ada2009-09-24 18:02:49 +02001309 return -ESRCH;
1310}
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001311
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001312static const char *get_default_sort_order(void)
1313{
1314 const char *default_sort_orders[] = {
1315 default_sort_order,
1316 default_branch_sort_order,
1317 default_mem_sort_order,
1318 default_top_sort_order,
1319 default_diff_sort_order,
1320 };
1321
1322 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
1323
1324 return default_sort_orders[sort__mode];
1325}
1326
Namhyung Kima7d945b2014-03-04 10:46:34 +09001327static int __setup_sorting(void)
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001328{
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001329 char *tmp, *tok, *str;
1330 const char *sort_keys = sort_order;
Namhyung Kim55309982013-02-06 14:57:16 +09001331 int ret = 0;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001332
Namhyung Kima7d945b2014-03-04 10:46:34 +09001333 if (sort_keys == NULL) {
1334 if (field_order) {
1335 /*
1336 * If user specified field order but no sort order,
1337 * we'll honor it and not add default sort orders.
1338 */
1339 return 0;
1340 }
1341
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001342 sort_keys = get_default_sort_order();
Namhyung Kima7d945b2014-03-04 10:46:34 +09001343 }
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001344
1345 str = strdup(sort_keys);
Namhyung Kim5936f542013-02-06 14:57:17 +09001346 if (str == NULL) {
1347 error("Not enough memory to setup sort keys");
1348 return -ENOMEM;
1349 }
1350
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001351 for (tok = strtok_r(str, ", ", &tmp);
1352 tok; tok = strtok_r(NULL, ", ", &tmp)) {
Namhyung Kim55309982013-02-06 14:57:16 +09001353 ret = sort_dimension__add(tok);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001354 if (ret == -EINVAL) {
1355 error("Invalid --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001356 break;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001357 } else if (ret == -ESRCH) {
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001358 error("Unknown --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001359 break;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001360 }
1361 }
1362
1363 free(str);
Namhyung Kim55309982013-02-06 14:57:16 +09001364 return ret;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001365}
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001366
Namhyung Kime67d49a2014-03-18 13:00:59 +09001367bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
1368{
1369 if (perf_hpp__is_sort_entry(format)) {
1370 struct hpp_sort_entry *hse;
1371
1372 hse = container_of(format, struct hpp_sort_entry, hpp);
1373 return hse->se->elide;
1374 }
1375 return false;
1376}
1377
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001378static void sort_entry__setup_elide(struct sort_entry *se,
Namhyung Kim08e71542013-04-03 21:26:19 +09001379 struct strlist *list,
1380 const char *list_name, FILE *fp)
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001381{
1382 if (list && strlist__nr_entries(list) == 1) {
1383 if (fp != NULL)
1384 fprintf(fp, "# %s: %s\n", list_name,
1385 strlist__entry(list, 0)->s);
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001386 se->elide = true;
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001387 }
1388}
Namhyung Kim08e71542013-04-03 21:26:19 +09001389
1390void sort__setup_elide(FILE *output)
1391{
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001392 struct perf_hpp_fmt *fmt;
1393 struct hpp_sort_entry *hse;
Namhyung Kim7524f632013-11-08 17:53:42 +09001394
Namhyung Kim08e71542013-04-03 21:26:19 +09001395 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1396 "dso", output);
1397 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list,
1398 "comm", output);
1399 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list,
1400 "symbol", output);
1401
1402 if (sort__mode == SORT_MODE__BRANCH) {
1403 sort_entry__setup_elide(&sort_dso_from,
1404 symbol_conf.dso_from_list,
1405 "dso_from", output);
1406 sort_entry__setup_elide(&sort_dso_to,
1407 symbol_conf.dso_to_list,
1408 "dso_to", output);
1409 sort_entry__setup_elide(&sort_sym_from,
1410 symbol_conf.sym_from_list,
1411 "sym_from", output);
1412 sort_entry__setup_elide(&sort_sym_to,
1413 symbol_conf.sym_to_list,
1414 "sym_to", output);
1415 } else if (sort__mode == SORT_MODE__MEMORY) {
1416 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1417 "symbol_daddr", output);
1418 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1419 "dso_daddr", output);
1420 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1421 "mem", output);
1422 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1423 "local_weight", output);
1424 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1425 "tlb", output);
1426 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1427 "snoop", output);
1428 }
1429
Namhyung Kim7524f632013-11-08 17:53:42 +09001430 /*
1431 * It makes no sense to elide all of sort entries.
1432 * Just revert them to show up again.
1433 */
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001434 perf_hpp__for_each_format(fmt) {
1435 if (!perf_hpp__is_sort_entry(fmt))
1436 continue;
1437
1438 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1439 if (!hse->se->elide)
Namhyung Kim7524f632013-11-08 17:53:42 +09001440 return;
1441 }
1442
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001443 perf_hpp__for_each_format(fmt) {
1444 if (!perf_hpp__is_sort_entry(fmt))
1445 continue;
1446
1447 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1448 hse->se->elide = false;
1449 }
Namhyung Kim08e71542013-04-03 21:26:19 +09001450}
Namhyung Kima7d945b2014-03-04 10:46:34 +09001451
1452static int output_field_add(char *tok)
1453{
1454 unsigned int i;
1455
1456 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1457 struct sort_dimension *sd = &common_sort_dimensions[i];
1458
1459 if (strncasecmp(tok, sd->name, strlen(tok)))
1460 continue;
1461
1462 return __sort_dimension__add_output(sd);
1463 }
1464
1465 for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
1466 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
1467
1468 if (strncasecmp(tok, hd->name, strlen(tok)))
1469 continue;
1470
1471 return __hpp_dimension__add_output(hd);
1472 }
1473
1474 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1475 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1476
1477 if (strncasecmp(tok, sd->name, strlen(tok)))
1478 continue;
1479
1480 return __sort_dimension__add_output(sd);
1481 }
1482
1483 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1484 struct sort_dimension *sd = &memory_sort_dimensions[i];
1485
1486 if (strncasecmp(tok, sd->name, strlen(tok)))
1487 continue;
1488
1489 return __sort_dimension__add_output(sd);
1490 }
1491
1492 return -ESRCH;
1493}
1494
1495static void reset_dimensions(void)
1496{
1497 unsigned int i;
1498
1499 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++)
1500 common_sort_dimensions[i].taken = 0;
1501
1502 for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++)
1503 hpp_sort_dimensions[i].taken = 0;
1504
1505 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++)
1506 bstack_sort_dimensions[i].taken = 0;
1507
1508 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++)
1509 memory_sort_dimensions[i].taken = 0;
1510}
1511
1512static int __setup_output_field(void)
1513{
1514 char *tmp, *tok, *str;
1515 int ret = 0;
1516
1517 if (field_order == NULL)
1518 return 0;
1519
1520 reset_dimensions();
1521
1522 str = strdup(field_order);
1523 if (str == NULL) {
1524 error("Not enough memory to setup output fields");
1525 return -ENOMEM;
1526 }
1527
1528 for (tok = strtok_r(str, ", ", &tmp);
1529 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1530 ret = output_field_add(tok);
1531 if (ret == -EINVAL) {
1532 error("Invalid --fields key: `%s'", tok);
1533 break;
1534 } else if (ret == -ESRCH) {
1535 error("Unknown --fields key: `%s'", tok);
1536 break;
1537 }
1538 }
1539
1540 free(str);
1541 return ret;
1542}
1543
1544int setup_sorting(void)
1545{
1546 int err;
1547
1548 err = __setup_sorting();
1549 if (err < 0)
1550 return err;
1551
1552 if (parent_pattern != default_parent_pattern) {
1553 err = sort_dimension__add("parent");
1554 if (err < 0)
1555 return err;
1556 }
1557
1558 reset_dimensions();
1559
1560 /*
1561 * perf diff doesn't use default hpp output fields.
1562 */
1563 if (sort__mode != SORT_MODE__DIFF)
1564 perf_hpp__init();
1565
1566 err = __setup_output_field();
1567 if (err < 0)
1568 return err;
1569
1570 /* copy sort keys to output fields */
1571 perf_hpp__setup_output_field();
1572 /* and then copy output fields to sort keys */
1573 perf_hpp__append_sort_keys();
1574
1575 return 0;
1576}
Namhyung Kim1c89fe92014-05-07 18:42:24 +09001577
1578void reset_output_field(void)
1579{
1580 sort__need_collapse = 0;
1581 sort__has_parent = 0;
1582 sort__has_sym = 0;
1583 sort__has_dso = 0;
1584
1585 reset_dimensions();
1586 perf_hpp__reset_output_field();
1587}