blob: 2d8ccd4d9e1b7bd5231d35c2afaaec9078c86573 [file] [log] [blame]
Don Zickus9b32ba72014-06-01 15:38:29 +02001#include <sys/mman.h>
John Kacurdd68ada2009-09-24 18:02:49 +02002#include "sort.h"
Arnaldo Carvalho de Melo8a6c5b22010-07-20 14:42:52 -03003#include "hist.h"
Namhyung Kim4dfced32013-09-13 16:28:57 +09004#include "comm.h"
Namhyung Kim08e71542013-04-03 21:26:19 +09005#include "symbol.h"
Namhyung Kim8b536992014-03-03 11:46:55 +09006#include "evsel.h"
John Kacurdd68ada2009-09-24 18:02:49 +02007
8regex_t parent_regex;
Arnaldo Carvalho de Meloedb7c602010-05-17 16:22:41 -03009const char default_parent_pattern[] = "^sys_|^do_page_fault";
10const char *parent_pattern = default_parent_pattern;
11const char default_sort_order[] = "comm,dso,symbol";
Andi Kleen40997d62015-07-18 08:24:53 -070012const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
Namhyung Kim512ae1b2014-03-18 11:31:39 +090013const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
14const char default_top_sort_order[] = "dso,symbol";
15const char default_diff_sort_order[] = "dso,symbol";
16const char *sort_order;
Namhyung Kima7d945b2014-03-04 10:46:34 +090017const char *field_order;
Greg Priceb21484f2012-12-06 21:48:05 -080018regex_t ignore_callees_regex;
19int have_ignore_callees = 0;
Frederic Weisbeckeraf0a6fa2009-10-22 23:23:22 +020020int sort__need_collapse = 0;
21int sort__has_parent = 0;
Namhyung Kim1af556402012-09-14 17:35:27 +090022int sort__has_sym = 0;
Namhyung Kim68f6d022013-12-18 14:21:10 +090023int sort__has_dso = 0;
Kan Liang2e7ea3a2015-09-04 10:45:43 -040024int sort__has_socket = 0;
Namhyung Kim55369fc2013-04-01 20:35:20 +090025enum sort_mode sort__mode = SORT_MODE__NORMAL;
Frederic Weisbeckera4fb5812009-10-22 23:23:23 +020026
John Kacurdd68ada2009-09-24 18:02:49 +020027
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030028static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
John Kacurdd68ada2009-09-24 18:02:49 +020029{
30 int n;
31 va_list ap;
32
33 va_start(ap, fmt);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030034 n = vsnprintf(bf, size, fmt, ap);
Jiri Olsa0ca0c132012-09-06 17:46:56 +020035 if (symbol_conf.field_sep && n > 0) {
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030036 char *sep = bf;
John Kacurdd68ada2009-09-24 18:02:49 +020037
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030038 while (1) {
Jiri Olsa0ca0c132012-09-06 17:46:56 +020039 sep = strchr(sep, *symbol_conf.field_sep);
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030040 if (sep == NULL)
41 break;
42 *sep = '.';
John Kacurdd68ada2009-09-24 18:02:49 +020043 }
John Kacurdd68ada2009-09-24 18:02:49 +020044 }
45 va_end(ap);
Anton Blanchardb8327962012-03-07 11:42:49 +110046
47 if (n >= (int)size)
48 return size - 1;
John Kacurdd68ada2009-09-24 18:02:49 +020049 return n;
50}
51
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020052static int64_t cmp_null(const void *l, const void *r)
Frederic Weisbecker872a8782011-06-29 03:14:52 +020053{
54 if (!l && !r)
55 return 0;
56 else if (!l)
57 return -1;
58 else
59 return 1;
60}
61
62/* --sort pid */
63
64static int64_t
65sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
66{
Adrian Hunter38051232013-07-04 16:20:31 +030067 return right->thread->tid - left->thread->tid;
Frederic Weisbecker872a8782011-06-29 03:14:52 +020068}
69
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -030070static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -030071 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +020072{
Frederic Weisbeckerb9c51432013-09-11 14:46:56 +020073 const char *comm = thread__comm_str(he->thread);
Namhyung Kim5b591662014-07-31 14:47:38 +090074
75 width = max(7U, width) - 6;
76 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
77 width, width, comm ?: "");
John Kacurdd68ada2009-09-24 18:02:49 +020078}
79
Frederic Weisbecker872a8782011-06-29 03:14:52 +020080struct sort_entry sort_thread = {
Namhyung Kim8246de82014-07-31 14:47:35 +090081 .se_header = " Pid:Command",
Frederic Weisbecker872a8782011-06-29 03:14:52 +020082 .se_cmp = sort__thread_cmp,
83 .se_snprintf = hist_entry__thread_snprintf,
84 .se_width_idx = HISTC_THREAD,
85};
86
87/* --sort comm */
88
89static int64_t
90sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
91{
Frederic Weisbeckerfedd63d2013-09-11 17:18:09 +020092 /* Compare the addr that should be unique among comm */
Jiri Olsa2f15bd82015-05-15 17:54:28 +020093 return strcmp(comm__str(right->comm), comm__str(left->comm));
Frederic Weisbecker872a8782011-06-29 03:14:52 +020094}
95
96static int64_t
97sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
98{
Namhyung Kim4dfced32013-09-13 16:28:57 +090099 /* Compare the addr that should be unique among comm */
Jiri Olsa2f15bd82015-05-15 17:54:28 +0200100 return strcmp(comm__str(right->comm), comm__str(left->comm));
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200101}
102
Namhyung Kim202e7a62014-03-04 11:01:41 +0900103static int64_t
104sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
105{
106 return strcmp(comm__str(right->comm), comm__str(left->comm));
107}
108
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300109static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300110 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +0200111{
Namhyung Kim5b591662014-07-31 14:47:38 +0900112 return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
John Kacurdd68ada2009-09-24 18:02:49 +0200113}
114
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900115struct sort_entry sort_comm = {
116 .se_header = "Command",
117 .se_cmp = sort__comm_cmp,
118 .se_collapse = sort__comm_collapse,
Namhyung Kim202e7a62014-03-04 11:01:41 +0900119 .se_sort = sort__comm_sort,
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900120 .se_snprintf = hist_entry__comm_snprintf,
121 .se_width_idx = HISTC_COMM,
122};
123
124/* --sort dso */
125
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100126static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
John Kacurdd68ada2009-09-24 18:02:49 +0200127{
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100128 struct dso *dso_l = map_l ? map_l->dso : NULL;
129 struct dso *dso_r = map_r ? map_r->dso : NULL;
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300130 const char *dso_name_l, *dso_name_r;
John Kacurdd68ada2009-09-24 18:02:49 +0200131
132 if (!dso_l || !dso_r)
Namhyung Kim202e7a62014-03-04 11:01:41 +0900133 return cmp_null(dso_r, dso_l);
John Kacurdd68ada2009-09-24 18:02:49 +0200134
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300135 if (verbose) {
136 dso_name_l = dso_l->long_name;
137 dso_name_r = dso_r->long_name;
138 } else {
139 dso_name_l = dso_l->short_name;
140 dso_name_r = dso_r->short_name;
141 }
142
143 return strcmp(dso_name_l, dso_name_r);
John Kacurdd68ada2009-09-24 18:02:49 +0200144}
145
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100146static int64_t
147sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
John Kacurdd68ada2009-09-24 18:02:49 +0200148{
Namhyung Kim202e7a62014-03-04 11:01:41 +0900149 return _sort__dso_cmp(right->ms.map, left->ms.map);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100150}
151
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100152static int _hist_entry__dso_snprintf(struct map *map, char *bf,
153 size_t size, unsigned int width)
154{
155 if (map && map->dso) {
156 const char *dso_name = !verbose ? map->dso->short_name :
157 map->dso->long_name;
Namhyung Kim5b591662014-07-31 14:47:38 +0900158 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
Arnaldo Carvalho de Melo439d4732009-10-02 03:29:58 -0300159 }
John Kacurdd68ada2009-09-24 18:02:49 +0200160
Namhyung Kim5b591662014-07-31 14:47:38 +0900161 return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
John Kacurdd68ada2009-09-24 18:02:49 +0200162}
163
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300164static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100165 size_t size, unsigned int width)
166{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300167 return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100168}
169
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900170struct sort_entry sort_dso = {
171 .se_header = "Shared Object",
172 .se_cmp = sort__dso_cmp,
173 .se_snprintf = hist_entry__dso_snprintf,
174 .se_width_idx = HISTC_DSO,
175};
176
177/* --sort symbol */
178
Namhyung Kim2037be52013-12-18 14:21:09 +0900179static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
180{
181 return (int64_t)(right_ip - left_ip);
182}
183
Namhyung Kim51f27d12013-02-06 14:57:15 +0900184static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900185{
186 if (!sym_l || !sym_r)
187 return cmp_null(sym_l, sym_r);
188
189 if (sym_l == sym_r)
190 return 0;
191
Yannick Brosseauc05676c2015-06-17 16:41:10 -0700192 if (sym_l->start != sym_r->start)
193 return (int64_t)(sym_r->start - sym_l->start);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900194
Yannick Brosseauc05676c2015-06-17 16:41:10 -0700195 return (int64_t)(sym_r->end - sym_l->end);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900196}
197
198static int64_t
199sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
200{
Namhyung Kim09600e02013-10-15 11:01:56 +0900201 int64_t ret;
202
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900203 if (!left->ms.sym && !right->ms.sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900204 return _sort__addr_cmp(left->ip, right->ip);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900205
Namhyung Kim09600e02013-10-15 11:01:56 +0900206 /*
207 * comparing symbol address alone is not enough since it's a
208 * relative address within a dso.
209 */
Namhyung Kim68f6d022013-12-18 14:21:10 +0900210 if (!sort__has_dso) {
211 ret = sort__dso_cmp(left, right);
212 if (ret != 0)
213 return ret;
214 }
Namhyung Kim09600e02013-10-15 11:01:56 +0900215
Namhyung Kim51f27d12013-02-06 14:57:15 +0900216 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900217}
218
Namhyung Kim202e7a62014-03-04 11:01:41 +0900219static int64_t
220sort__sym_sort(struct hist_entry *left, struct hist_entry *right)
221{
222 if (!left->ms.sym || !right->ms.sym)
223 return cmp_null(left->ms.sym, right->ms.sym);
224
225 return strcmp(right->ms.sym->name, left->ms.sym->name);
226}
227
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100228static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
229 u64 ip, char level, char *bf, size_t size,
Namhyung Kim43355522012-12-27 18:11:39 +0900230 unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100231{
232 size_t ret = 0;
233
234 if (verbose) {
235 char o = map ? dso__symtab_origin(map->dso) : '!';
236 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
Namhyung Kimded19d52013-04-01 20:35:19 +0900237 BITS_PER_LONG / 4 + 2, ip, o);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100238 }
239
240 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
Stephane Eranian98a3b322013-01-24 16:10:35 +0100241 if (sym && map) {
242 if (map->type == MAP__VARIABLE) {
243 ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
244 ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
Namhyung Kim62667742013-01-24 16:10:42 +0100245 ip - map->unmap_ip(map, sym->start));
Stephane Eranian98a3b322013-01-24 16:10:35 +0100246 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
247 width - ret, "");
248 } else {
249 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
250 width - ret,
251 sym->name);
252 }
253 } else {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100254 size_t len = BITS_PER_LONG / 4;
255 ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
256 len, ip);
257 ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
258 width - ret, "");
259 }
260
Namhyung Kim5b591662014-07-31 14:47:38 +0900261 if (ret > width)
262 bf[width] = '\0';
263
264 return width;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100265}
266
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300267static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900268 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100269{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300270 return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
271 he->level, bf, size, width);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100272}
John Kacurdd68ada2009-09-24 18:02:49 +0200273
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200274struct sort_entry sort_sym = {
275 .se_header = "Symbol",
276 .se_cmp = sort__sym_cmp,
Namhyung Kim202e7a62014-03-04 11:01:41 +0900277 .se_sort = sort__sym_sort,
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200278 .se_snprintf = hist_entry__sym_snprintf,
279 .se_width_idx = HISTC_SYMBOL,
280};
John Kacurdd68ada2009-09-24 18:02:49 +0200281
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300282/* --sort srcline */
283
284static int64_t
285sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
286{
Namhyung Kim4adcc432013-09-11 14:09:33 +0900287 if (!left->srcline) {
288 if (!left->ms.map)
289 left->srcline = SRCLINE_UNKNOWN;
290 else {
291 struct map *map = left->ms.map;
292 left->srcline = get_srcline(map->dso,
Andi Kleen85c116a2014-11-12 18:05:27 -0800293 map__rip_2objdump(map, left->ip),
294 left->ms.sym, true);
Namhyung Kim4adcc432013-09-11 14:09:33 +0900295 }
296 }
297 if (!right->srcline) {
298 if (!right->ms.map)
299 right->srcline = SRCLINE_UNKNOWN;
300 else {
301 struct map *map = right->ms.map;
302 right->srcline = get_srcline(map->dso,
Andi Kleen85c116a2014-11-12 18:05:27 -0800303 map__rip_2objdump(map, right->ip),
304 right->ms.sym, true);
Namhyung Kim4adcc432013-09-11 14:09:33 +0900305 }
306 }
Namhyung Kim202e7a62014-03-04 11:01:41 +0900307 return strcmp(right->srcline, left->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300308}
309
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300310static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim5b591662014-07-31 14:47:38 +0900311 size_t size, unsigned int width)
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300312{
Arnaldo Carvalho de Melob2d53672014-11-18 18:02:51 -0300313 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -0300314}
315
316struct sort_entry sort_srcline = {
317 .se_header = "Source:Line",
318 .se_cmp = sort__srcline_cmp,
319 .se_snprintf = hist_entry__srcline_snprintf,
320 .se_width_idx = HISTC_SRCLINE,
321};
322
Andi Kleen31191a82015-08-07 15:54:24 -0700323/* --sort srcfile */
324
325static char no_srcfile[1];
326
327static char *get_srcfile(struct hist_entry *e)
328{
329 char *sf, *p;
330 struct map *map = e->ms.map;
331
Andi Kleen2f84b422015-09-01 11:47:19 -0700332 sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
333 e->ms.sym, false, true);
Andi Kleen76b10652015-08-11 06:36:55 -0700334 if (!strcmp(sf, SRCLINE_UNKNOWN))
335 return no_srcfile;
Andi Kleen31191a82015-08-07 15:54:24 -0700336 p = strchr(sf, ':');
337 if (p && *sf) {
338 *p = 0;
339 return sf;
340 }
341 free(sf);
342 return no_srcfile;
343}
344
345static int64_t
346sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
347{
348 if (!left->srcfile) {
349 if (!left->ms.map)
350 left->srcfile = no_srcfile;
351 else
352 left->srcfile = get_srcfile(left);
353 }
354 if (!right->srcfile) {
355 if (!right->ms.map)
356 right->srcfile = no_srcfile;
357 else
358 right->srcfile = get_srcfile(right);
359 }
360 return strcmp(right->srcfile, left->srcfile);
361}
362
363static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
364 size_t size, unsigned int width)
365{
366 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcfile);
367}
368
369struct sort_entry sort_srcfile = {
370 .se_header = "Source File",
371 .se_cmp = sort__srcfile_cmp,
372 .se_snprintf = hist_entry__srcfile_snprintf,
373 .se_width_idx = HISTC_SRCFILE,
374};
375
John Kacurdd68ada2009-09-24 18:02:49 +0200376/* --sort parent */
377
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200378static int64_t
John Kacurdd68ada2009-09-24 18:02:49 +0200379sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
380{
381 struct symbol *sym_l = left->parent;
382 struct symbol *sym_r = right->parent;
383
384 if (!sym_l || !sym_r)
385 return cmp_null(sym_l, sym_r);
386
Namhyung Kim202e7a62014-03-04 11:01:41 +0900387 return strcmp(sym_r->name, sym_l->name);
John Kacurdd68ada2009-09-24 18:02:49 +0200388}
389
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300390static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
Arnaldo Carvalho de Meloa4e3b952010-03-31 11:33:40 -0300391 size_t size, unsigned int width)
John Kacurdd68ada2009-09-24 18:02:49 +0200392{
Namhyung Kim5b591662014-07-31 14:47:38 +0900393 return repsep_snprintf(bf, size, "%-*.*s", width, width,
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300394 he->parent ? he->parent->name : "[other]");
John Kacurdd68ada2009-09-24 18:02:49 +0200395}
396
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200397struct sort_entry sort_parent = {
398 .se_header = "Parent symbol",
399 .se_cmp = sort__parent_cmp,
400 .se_snprintf = hist_entry__parent_snprintf,
401 .se_width_idx = HISTC_PARENT,
402};
403
Arun Sharmaf60f3592010-06-04 11:27:10 -0300404/* --sort cpu */
405
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200406static int64_t
Arun Sharmaf60f3592010-06-04 11:27:10 -0300407sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
408{
409 return right->cpu - left->cpu;
410}
411
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300412static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
413 size_t size, unsigned int width)
Arun Sharmaf60f3592010-06-04 11:27:10 -0300414{
Namhyung Kim5b591662014-07-31 14:47:38 +0900415 return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
Arun Sharmaf60f3592010-06-04 11:27:10 -0300416}
417
Frederic Weisbecker872a8782011-06-29 03:14:52 +0200418struct sort_entry sort_cpu = {
419 .se_header = "CPU",
420 .se_cmp = sort__cpu_cmp,
421 .se_snprintf = hist_entry__cpu_snprintf,
422 .se_width_idx = HISTC_CPU,
423};
424
Kan Liang2e7ea3a2015-09-04 10:45:43 -0400425/* --sort socket */
426
427static int64_t
428sort__socket_cmp(struct hist_entry *left, struct hist_entry *right)
429{
430 return right->socket - left->socket;
431}
432
433static int hist_entry__socket_snprintf(struct hist_entry *he, char *bf,
434 size_t size, unsigned int width)
435{
436 return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket);
437}
438
439struct sort_entry sort_socket = {
440 .se_header = "Socket",
441 .se_cmp = sort__socket_cmp,
442 .se_snprintf = hist_entry__socket_snprintf,
443 .se_width_idx = HISTC_SOCKET,
444};
445
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900446/* sort keys for branch stacks */
447
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100448static int64_t
449sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
450{
Jiri Olsa288a4b92014-10-16 16:07:07 +0200451 if (!left->branch_info || !right->branch_info)
452 return cmp_null(left->branch_info, right->branch_info);
453
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100454 return _sort__dso_cmp(left->branch_info->from.map,
455 right->branch_info->from.map);
456}
457
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300458static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100459 size_t size, unsigned int width)
460{
Jiri Olsa288a4b92014-10-16 16:07:07 +0200461 if (he->branch_info)
462 return _hist_entry__dso_snprintf(he->branch_info->from.map,
463 bf, size, width);
464 else
465 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100466}
467
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100468static int64_t
469sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
470{
Jiri Olsa8b62fa52014-10-16 16:07:06 +0200471 if (!left->branch_info || !right->branch_info)
472 return cmp_null(left->branch_info, right->branch_info);
473
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100474 return _sort__dso_cmp(left->branch_info->to.map,
475 right->branch_info->to.map);
476}
477
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300478static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100479 size_t size, unsigned int width)
480{
Jiri Olsa8b62fa52014-10-16 16:07:06 +0200481 if (he->branch_info)
482 return _hist_entry__dso_snprintf(he->branch_info->to.map,
483 bf, size, width);
484 else
485 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100486}
487
488static int64_t
489sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
490{
491 struct addr_map_symbol *from_l = &left->branch_info->from;
492 struct addr_map_symbol *from_r = &right->branch_info->from;
493
Jiri Olsa1b9e97a2014-10-16 16:07:05 +0200494 if (!left->branch_info || !right->branch_info)
495 return cmp_null(left->branch_info, right->branch_info);
496
497 from_l = &left->branch_info->from;
498 from_r = &right->branch_info->from;
499
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100500 if (!from_l->sym && !from_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900501 return _sort__addr_cmp(from_l->addr, from_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100502
Namhyung Kim51f27d12013-02-06 14:57:15 +0900503 return _sort__sym_cmp(from_l->sym, from_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100504}
505
506static int64_t
507sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
508{
Jiri Olsa38cdbd32014-10-16 16:07:04 +0200509 struct addr_map_symbol *to_l, *to_r;
510
511 if (!left->branch_info || !right->branch_info)
512 return cmp_null(left->branch_info, right->branch_info);
513
514 to_l = &left->branch_info->to;
515 to_r = &right->branch_info->to;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100516
517 if (!to_l->sym && !to_r->sym)
Namhyung Kim2037be52013-12-18 14:21:09 +0900518 return _sort__addr_cmp(to_l->addr, to_r->addr);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100519
Namhyung Kim51f27d12013-02-06 14:57:15 +0900520 return _sort__sym_cmp(to_l->sym, to_r->sym);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100521}
522
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300523static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900524 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100525{
Jiri Olsa1b9e97a2014-10-16 16:07:05 +0200526 if (he->branch_info) {
527 struct addr_map_symbol *from = &he->branch_info->from;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100528
Jiri Olsa1b9e97a2014-10-16 16:07:05 +0200529 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
530 he->level, bf, size, width);
531 }
532
533 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100534}
535
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300536static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
Namhyung Kim43355522012-12-27 18:11:39 +0900537 size_t size, unsigned int width)
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100538{
Jiri Olsa38cdbd32014-10-16 16:07:04 +0200539 if (he->branch_info) {
540 struct addr_map_symbol *to = &he->branch_info->to;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100541
Jiri Olsa38cdbd32014-10-16 16:07:04 +0200542 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
543 he->level, bf, size, width);
544 }
545
546 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100547}
548
Namhyung Kim14d1ac72012-12-27 18:11:38 +0900549struct sort_entry sort_dso_from = {
550 .se_header = "Source Shared Object",
551 .se_cmp = sort__dso_from_cmp,
552 .se_snprintf = hist_entry__dso_from_snprintf,
553 .se_width_idx = HISTC_DSO_FROM,
554};
555
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100556struct sort_entry sort_dso_to = {
557 .se_header = "Target Shared Object",
558 .se_cmp = sort__dso_to_cmp,
559 .se_snprintf = hist_entry__dso_to_snprintf,
560 .se_width_idx = HISTC_DSO_TO,
561};
562
563struct sort_entry sort_sym_from = {
564 .se_header = "Source Symbol",
565 .se_cmp = sort__sym_from_cmp,
566 .se_snprintf = hist_entry__sym_from_snprintf,
567 .se_width_idx = HISTC_SYMBOL_FROM,
568};
569
570struct sort_entry sort_sym_to = {
571 .se_header = "Target Symbol",
572 .se_cmp = sort__sym_to_cmp,
573 .se_snprintf = hist_entry__sym_to_snprintf,
574 .se_width_idx = HISTC_SYMBOL_TO,
575};
576
577static int64_t
578sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
579{
Jiri Olsa428560e2014-10-16 16:07:03 +0200580 unsigned char mp, p;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100581
Jiri Olsa428560e2014-10-16 16:07:03 +0200582 if (!left->branch_info || !right->branch_info)
583 return cmp_null(left->branch_info, right->branch_info);
584
585 mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred;
586 p = left->branch_info->flags.predicted != right->branch_info->flags.predicted;
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100587 return mp || p;
588}
589
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300590static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100591 size_t size, unsigned int width){
592 static const char *out = "N/A";
593
Jiri Olsa428560e2014-10-16 16:07:03 +0200594 if (he->branch_info) {
595 if (he->branch_info->flags.predicted)
596 out = "N";
597 else if (he->branch_info->flags.mispred)
598 out = "Y";
599 }
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100600
Namhyung Kim5b591662014-07-31 14:47:38 +0900601 return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +0100602}
603
Andi Kleen0e332f02015-07-18 08:24:46 -0700604static int64_t
605sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
606{
607 return left->branch_info->flags.cycles -
608 right->branch_info->flags.cycles;
609}
610
611static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf,
612 size_t size, unsigned int width)
613{
614 if (he->branch_info->flags.cycles == 0)
615 return repsep_snprintf(bf, size, "%-*s", width, "-");
616 return repsep_snprintf(bf, size, "%-*hd", width,
617 he->branch_info->flags.cycles);
618}
619
620struct sort_entry sort_cycles = {
621 .se_header = "Basic Block Cycles",
622 .se_cmp = sort__cycles_cmp,
623 .se_snprintf = hist_entry__cycles_snprintf,
624 .se_width_idx = HISTC_CYCLES,
625};
626
Stephane Eranian98a3b322013-01-24 16:10:35 +0100627/* --sort daddr_sym */
628static int64_t
629sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
630{
631 uint64_t l = 0, r = 0;
632
633 if (left->mem_info)
634 l = left->mem_info->daddr.addr;
635 if (right->mem_info)
636 r = right->mem_info->daddr.addr;
637
638 return (int64_t)(r - l);
639}
640
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300641static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100642 size_t size, unsigned int width)
643{
644 uint64_t addr = 0;
645 struct map *map = NULL;
646 struct symbol *sym = NULL;
647
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300648 if (he->mem_info) {
649 addr = he->mem_info->daddr.addr;
650 map = he->mem_info->daddr.map;
651 sym = he->mem_info->daddr.sym;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100652 }
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300653 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100654 width);
655}
656
657static int64_t
Don Zickus28e6db22015-10-05 20:06:07 +0200658sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right)
659{
660 uint64_t l = 0, r = 0;
661
662 if (left->mem_info)
663 l = left->mem_info->iaddr.addr;
664 if (right->mem_info)
665 r = right->mem_info->iaddr.addr;
666
667 return (int64_t)(r - l);
668}
669
670static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf,
671 size_t size, unsigned int width)
672{
673 uint64_t addr = 0;
674 struct map *map = NULL;
675 struct symbol *sym = NULL;
676
677 if (he->mem_info) {
678 addr = he->mem_info->iaddr.addr;
679 map = he->mem_info->iaddr.map;
680 sym = he->mem_info->iaddr.sym;
681 }
682 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
683 width);
684}
685
686static int64_t
Stephane Eranian98a3b322013-01-24 16:10:35 +0100687sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
688{
689 struct map *map_l = NULL;
690 struct map *map_r = NULL;
691
692 if (left->mem_info)
693 map_l = left->mem_info->daddr.map;
694 if (right->mem_info)
695 map_r = right->mem_info->daddr.map;
696
697 return _sort__dso_cmp(map_l, map_r);
698}
699
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300700static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100701 size_t size, unsigned int width)
702{
703 struct map *map = NULL;
704
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300705 if (he->mem_info)
706 map = he->mem_info->daddr.map;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100707
708 return _hist_entry__dso_snprintf(map, bf, size, width);
709}
710
711static int64_t
712sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
713{
714 union perf_mem_data_src data_src_l;
715 union perf_mem_data_src data_src_r;
716
717 if (left->mem_info)
718 data_src_l = left->mem_info->data_src;
719 else
720 data_src_l.mem_lock = PERF_MEM_LOCK_NA;
721
722 if (right->mem_info)
723 data_src_r = right->mem_info->data_src;
724 else
725 data_src_r.mem_lock = PERF_MEM_LOCK_NA;
726
727 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
728}
729
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300730static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100731 size_t size, unsigned int width)
732{
733 const char *out;
734 u64 mask = PERF_MEM_LOCK_NA;
735
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300736 if (he->mem_info)
737 mask = he->mem_info->data_src.mem_lock;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100738
739 if (mask & PERF_MEM_LOCK_NA)
740 out = "N/A";
741 else if (mask & PERF_MEM_LOCK_LOCKED)
742 out = "Yes";
743 else
744 out = "No";
745
746 return repsep_snprintf(bf, size, "%-*s", width, out);
747}
748
749static int64_t
750sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
751{
752 union perf_mem_data_src data_src_l;
753 union perf_mem_data_src data_src_r;
754
755 if (left->mem_info)
756 data_src_l = left->mem_info->data_src;
757 else
758 data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
759
760 if (right->mem_info)
761 data_src_r = right->mem_info->data_src;
762 else
763 data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
764
765 return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
766}
767
768static const char * const tlb_access[] = {
769 "N/A",
770 "HIT",
771 "MISS",
772 "L1",
773 "L2",
774 "Walker",
775 "Fault",
776};
777#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
778
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300779static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100780 size_t size, unsigned int width)
781{
782 char out[64];
783 size_t sz = sizeof(out) - 1; /* -1 for null termination */
784 size_t l = 0, i;
785 u64 m = PERF_MEM_TLB_NA;
786 u64 hit, miss;
787
788 out[0] = '\0';
789
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300790 if (he->mem_info)
791 m = he->mem_info->data_src.mem_dtlb;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100792
793 hit = m & PERF_MEM_TLB_HIT;
794 miss = m & PERF_MEM_TLB_MISS;
795
796 /* already taken care of */
797 m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
798
799 for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
800 if (!(m & 0x1))
801 continue;
802 if (l) {
803 strcat(out, " or ");
804 l += 4;
805 }
806 strncat(out, tlb_access[i], sz - l);
807 l += strlen(tlb_access[i]);
808 }
809 if (*out == '\0')
810 strcpy(out, "N/A");
811 if (hit)
812 strncat(out, " hit", sz - l);
813 if (miss)
814 strncat(out, " miss", sz - l);
815
816 return repsep_snprintf(bf, size, "%-*s", width, out);
817}
818
819static int64_t
820sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
821{
822 union perf_mem_data_src data_src_l;
823 union perf_mem_data_src data_src_r;
824
825 if (left->mem_info)
826 data_src_l = left->mem_info->data_src;
827 else
828 data_src_l.mem_lvl = PERF_MEM_LVL_NA;
829
830 if (right->mem_info)
831 data_src_r = right->mem_info->data_src;
832 else
833 data_src_r.mem_lvl = PERF_MEM_LVL_NA;
834
835 return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
836}
837
838static const char * const mem_lvl[] = {
839 "N/A",
840 "HIT",
841 "MISS",
842 "L1",
843 "LFB",
844 "L2",
845 "L3",
846 "Local RAM",
847 "Remote RAM (1 hop)",
848 "Remote RAM (2 hops)",
849 "Remote Cache (1 hop)",
850 "Remote Cache (2 hops)",
851 "I/O",
852 "Uncached",
853};
854#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
855
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300856static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100857 size_t size, unsigned int width)
858{
859 char out[64];
860 size_t sz = sizeof(out) - 1; /* -1 for null termination */
861 size_t i, l = 0;
862 u64 m = PERF_MEM_LVL_NA;
863 u64 hit, miss;
864
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300865 if (he->mem_info)
866 m = he->mem_info->data_src.mem_lvl;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100867
868 out[0] = '\0';
869
870 hit = m & PERF_MEM_LVL_HIT;
871 miss = m & PERF_MEM_LVL_MISS;
872
873 /* already taken care of */
874 m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
875
876 for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
877 if (!(m & 0x1))
878 continue;
879 if (l) {
880 strcat(out, " or ");
881 l += 4;
882 }
883 strncat(out, mem_lvl[i], sz - l);
884 l += strlen(mem_lvl[i]);
885 }
886 if (*out == '\0')
887 strcpy(out, "N/A");
888 if (hit)
889 strncat(out, " hit", sz - l);
890 if (miss)
891 strncat(out, " miss", sz - l);
892
893 return repsep_snprintf(bf, size, "%-*s", width, out);
894}
895
896static int64_t
897sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
898{
899 union perf_mem_data_src data_src_l;
900 union perf_mem_data_src data_src_r;
901
902 if (left->mem_info)
903 data_src_l = left->mem_info->data_src;
904 else
905 data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
906
907 if (right->mem_info)
908 data_src_r = right->mem_info->data_src;
909 else
910 data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
911
912 return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
913}
914
915static const char * const snoop_access[] = {
916 "N/A",
917 "None",
918 "Miss",
919 "Hit",
920 "HitM",
921};
922#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
923
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300924static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
Stephane Eranian98a3b322013-01-24 16:10:35 +0100925 size_t size, unsigned int width)
926{
927 char out[64];
928 size_t sz = sizeof(out) - 1; /* -1 for null termination */
929 size_t i, l = 0;
930 u64 m = PERF_MEM_SNOOP_NA;
931
932 out[0] = '\0';
933
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -0300934 if (he->mem_info)
935 m = he->mem_info->data_src.mem_snoop;
Stephane Eranian98a3b322013-01-24 16:10:35 +0100936
937 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
938 if (!(m & 0x1))
939 continue;
940 if (l) {
941 strcat(out, " or ");
942 l += 4;
943 }
944 strncat(out, snoop_access[i], sz - l);
945 l += strlen(snoop_access[i]);
946 }
947
948 if (*out == '\0')
949 strcpy(out, "N/A");
950
951 return repsep_snprintf(bf, size, "%-*s", width, out);
952}
953
Don Zickus9b32ba72014-06-01 15:38:29 +0200954static inline u64 cl_address(u64 address)
955{
956 /* return the cacheline of the address */
957 return (address & ~(cacheline_size - 1));
958}
959
960static int64_t
961sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
962{
963 u64 l, r;
964 struct map *l_map, *r_map;
965
966 if (!left->mem_info) return -1;
967 if (!right->mem_info) return 1;
968
969 /* group event types together */
970 if (left->cpumode > right->cpumode) return -1;
971 if (left->cpumode < right->cpumode) return 1;
972
973 l_map = left->mem_info->daddr.map;
974 r_map = right->mem_info->daddr.map;
975
976 /* if both are NULL, jump to sort on al_addr instead */
977 if (!l_map && !r_map)
978 goto addr;
979
980 if (!l_map) return -1;
981 if (!r_map) return 1;
982
983 if (l_map->maj > r_map->maj) return -1;
984 if (l_map->maj < r_map->maj) return 1;
985
986 if (l_map->min > r_map->min) return -1;
987 if (l_map->min < r_map->min) return 1;
988
989 if (l_map->ino > r_map->ino) return -1;
990 if (l_map->ino < r_map->ino) return 1;
991
992 if (l_map->ino_generation > r_map->ino_generation) return -1;
993 if (l_map->ino_generation < r_map->ino_generation) return 1;
994
995 /*
996 * Addresses with no major/minor numbers are assumed to be
997 * anonymous in userspace. Sort those on pid then address.
998 *
999 * The kernel and non-zero major/minor mapped areas are
1000 * assumed to be unity mapped. Sort those on address.
1001 */
1002
1003 if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
1004 (!(l_map->flags & MAP_SHARED)) &&
1005 !l_map->maj && !l_map->min && !l_map->ino &&
1006 !l_map->ino_generation) {
1007 /* userspace anonymous */
1008
1009 if (left->thread->pid_ > right->thread->pid_) return -1;
1010 if (left->thread->pid_ < right->thread->pid_) return 1;
1011 }
1012
1013addr:
1014 /* al_addr does all the right addr - start + offset calculations */
1015 l = cl_address(left->mem_info->daddr.al_addr);
1016 r = cl_address(right->mem_info->daddr.al_addr);
1017
1018 if (l > r) return -1;
1019 if (l < r) return 1;
1020
1021 return 0;
1022}
1023
1024static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
1025 size_t size, unsigned int width)
1026{
1027
1028 uint64_t addr = 0;
1029 struct map *map = NULL;
1030 struct symbol *sym = NULL;
1031 char level = he->level;
1032
1033 if (he->mem_info) {
1034 addr = cl_address(he->mem_info->daddr.al_addr);
1035 map = he->mem_info->daddr.map;
1036 sym = he->mem_info->daddr.sym;
1037
1038 /* print [s] for shared data mmaps */
1039 if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
1040 map && (map->type == MAP__VARIABLE) &&
1041 (map->flags & MAP_SHARED) &&
1042 (map->maj || map->min || map->ino ||
1043 map->ino_generation))
1044 level = 's';
1045 else if (!map)
1046 level = 'X';
1047 }
1048 return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
1049 width);
1050}
1051
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001052struct sort_entry sort_mispredict = {
1053 .se_header = "Branch Mispredicted",
1054 .se_cmp = sort__mispredict_cmp,
1055 .se_snprintf = hist_entry__mispredict_snprintf,
1056 .se_width_idx = HISTC_MISPREDICT,
1057};
1058
Andi Kleen05484292013-01-24 16:10:29 +01001059static u64 he_weight(struct hist_entry *he)
1060{
1061 return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
1062}
1063
1064static int64_t
1065sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
1066{
1067 return he_weight(left) - he_weight(right);
1068}
1069
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001070static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +01001071 size_t size, unsigned int width)
1072{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001073 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
Andi Kleen05484292013-01-24 16:10:29 +01001074}
1075
1076struct sort_entry sort_local_weight = {
1077 .se_header = "Local Weight",
1078 .se_cmp = sort__local_weight_cmp,
1079 .se_snprintf = hist_entry__local_weight_snprintf,
1080 .se_width_idx = HISTC_LOCAL_WEIGHT,
1081};
1082
1083static int64_t
1084sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
1085{
1086 return left->stat.weight - right->stat.weight;
1087}
1088
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001089static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
Andi Kleen05484292013-01-24 16:10:29 +01001090 size_t size, unsigned int width)
1091{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001092 return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
Andi Kleen05484292013-01-24 16:10:29 +01001093}
1094
1095struct sort_entry sort_global_weight = {
1096 .se_header = "Weight",
1097 .se_cmp = sort__global_weight_cmp,
1098 .se_snprintf = hist_entry__global_weight_snprintf,
1099 .se_width_idx = HISTC_GLOBAL_WEIGHT,
1100};
1101
Stephane Eranian98a3b322013-01-24 16:10:35 +01001102struct sort_entry sort_mem_daddr_sym = {
1103 .se_header = "Data Symbol",
1104 .se_cmp = sort__daddr_cmp,
1105 .se_snprintf = hist_entry__daddr_snprintf,
1106 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
1107};
1108
Don Zickus28e6db22015-10-05 20:06:07 +02001109struct sort_entry sort_mem_iaddr_sym = {
1110 .se_header = "Code Symbol",
1111 .se_cmp = sort__iaddr_cmp,
1112 .se_snprintf = hist_entry__iaddr_snprintf,
1113 .se_width_idx = HISTC_MEM_IADDR_SYMBOL,
1114};
1115
Stephane Eranian98a3b322013-01-24 16:10:35 +01001116struct sort_entry sort_mem_daddr_dso = {
1117 .se_header = "Data Object",
1118 .se_cmp = sort__dso_daddr_cmp,
1119 .se_snprintf = hist_entry__dso_daddr_snprintf,
1120 .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
1121};
1122
1123struct sort_entry sort_mem_locked = {
1124 .se_header = "Locked",
1125 .se_cmp = sort__locked_cmp,
1126 .se_snprintf = hist_entry__locked_snprintf,
1127 .se_width_idx = HISTC_MEM_LOCKED,
1128};
1129
1130struct sort_entry sort_mem_tlb = {
1131 .se_header = "TLB access",
1132 .se_cmp = sort__tlb_cmp,
1133 .se_snprintf = hist_entry__tlb_snprintf,
1134 .se_width_idx = HISTC_MEM_TLB,
1135};
1136
1137struct sort_entry sort_mem_lvl = {
1138 .se_header = "Memory access",
1139 .se_cmp = sort__lvl_cmp,
1140 .se_snprintf = hist_entry__lvl_snprintf,
1141 .se_width_idx = HISTC_MEM_LVL,
1142};
1143
1144struct sort_entry sort_mem_snoop = {
1145 .se_header = "Snoop",
1146 .se_cmp = sort__snoop_cmp,
1147 .se_snprintf = hist_entry__snoop_snprintf,
1148 .se_width_idx = HISTC_MEM_SNOOP,
1149};
1150
Don Zickus9b32ba72014-06-01 15:38:29 +02001151struct sort_entry sort_mem_dcacheline = {
1152 .se_header = "Data Cacheline",
1153 .se_cmp = sort__dcacheline_cmp,
1154 .se_snprintf = hist_entry__dcacheline_snprintf,
1155 .se_width_idx = HISTC_MEM_DCACHELINE,
1156};
1157
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001158static int64_t
1159sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
1160{
Jiri Olsa49f47442014-10-16 16:07:01 +02001161 if (!left->branch_info || !right->branch_info)
1162 return cmp_null(left->branch_info, right->branch_info);
1163
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001164 return left->branch_info->flags.abort !=
1165 right->branch_info->flags.abort;
1166}
1167
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001168static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001169 size_t size, unsigned int width)
1170{
Jiri Olsa49f47442014-10-16 16:07:01 +02001171 static const char *out = "N/A";
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001172
Jiri Olsa49f47442014-10-16 16:07:01 +02001173 if (he->branch_info) {
1174 if (he->branch_info->flags.abort)
1175 out = "A";
1176 else
1177 out = ".";
1178 }
1179
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001180 return repsep_snprintf(bf, size, "%-*s", width, out);
1181}
1182
1183struct sort_entry sort_abort = {
1184 .se_header = "Transaction abort",
1185 .se_cmp = sort__abort_cmp,
1186 .se_snprintf = hist_entry__abort_snprintf,
1187 .se_width_idx = HISTC_ABORT,
1188};
1189
1190static int64_t
1191sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
1192{
Jiri Olsa0199d242014-10-16 16:07:02 +02001193 if (!left->branch_info || !right->branch_info)
1194 return cmp_null(left->branch_info, right->branch_info);
1195
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001196 return left->branch_info->flags.in_tx !=
1197 right->branch_info->flags.in_tx;
1198}
1199
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001200static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001201 size_t size, unsigned int width)
1202{
Jiri Olsa0199d242014-10-16 16:07:02 +02001203 static const char *out = "N/A";
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001204
Jiri Olsa0199d242014-10-16 16:07:02 +02001205 if (he->branch_info) {
1206 if (he->branch_info->flags.in_tx)
1207 out = "T";
1208 else
1209 out = ".";
1210 }
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001211
1212 return repsep_snprintf(bf, size, "%-*s", width, out);
1213}
1214
1215struct sort_entry sort_in_tx = {
1216 .se_header = "Branch in transaction",
1217 .se_cmp = sort__in_tx_cmp,
1218 .se_snprintf = hist_entry__in_tx_snprintf,
1219 .se_width_idx = HISTC_IN_TX,
1220};
1221
Andi Kleen475eeab2013-09-20 07:40:43 -07001222static int64_t
1223sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
1224{
1225 return left->transaction - right->transaction;
1226}
1227
1228static inline char *add_str(char *p, const char *str)
1229{
1230 strcpy(p, str);
1231 return p + strlen(str);
1232}
1233
1234static struct txbit {
1235 unsigned flag;
1236 const char *name;
1237 int skip_for_len;
1238} txbits[] = {
1239 { PERF_TXN_ELISION, "EL ", 0 },
1240 { PERF_TXN_TRANSACTION, "TX ", 1 },
1241 { PERF_TXN_SYNC, "SYNC ", 1 },
1242 { PERF_TXN_ASYNC, "ASYNC ", 0 },
1243 { PERF_TXN_RETRY, "RETRY ", 0 },
1244 { PERF_TXN_CONFLICT, "CON ", 0 },
1245 { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
1246 { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
1247 { 0, NULL, 0 }
1248};
1249
1250int hist_entry__transaction_len(void)
1251{
1252 int i;
1253 int len = 0;
1254
1255 for (i = 0; txbits[i].name; i++) {
1256 if (!txbits[i].skip_for_len)
1257 len += strlen(txbits[i].name);
1258 }
1259 len += 4; /* :XX<space> */
1260 return len;
1261}
1262
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001263static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
Andi Kleen475eeab2013-09-20 07:40:43 -07001264 size_t size, unsigned int width)
1265{
Arnaldo Carvalho de Meloc824c432013-10-22 19:01:31 -03001266 u64 t = he->transaction;
Andi Kleen475eeab2013-09-20 07:40:43 -07001267 char buf[128];
1268 char *p = buf;
1269 int i;
1270
1271 buf[0] = 0;
1272 for (i = 0; txbits[i].name; i++)
1273 if (txbits[i].flag & t)
1274 p = add_str(p, txbits[i].name);
1275 if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
1276 p = add_str(p, "NEITHER ");
1277 if (t & PERF_TXN_ABORT_MASK) {
1278 sprintf(p, ":%" PRIx64,
1279 (t & PERF_TXN_ABORT_MASK) >>
1280 PERF_TXN_ABORT_SHIFT);
1281 p += strlen(p);
1282 }
1283
1284 return repsep_snprintf(bf, size, "%-*s", width, buf);
1285}
1286
1287struct sort_entry sort_transaction = {
1288 .se_header = "Transaction ",
1289 .se_cmp = sort__transaction_cmp,
1290 .se_snprintf = hist_entry__transaction_snprintf,
1291 .se_width_idx = HISTC_TRANSACTION,
1292};
1293
Frederic Weisbecker872a8782011-06-29 03:14:52 +02001294struct sort_dimension {
1295 const char *name;
1296 struct sort_entry *entry;
1297 int taken;
1298};
1299
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001300#define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
1301
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001302static struct sort_dimension common_sort_dimensions[] = {
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001303 DIM(SORT_PID, "pid", sort_thread),
1304 DIM(SORT_COMM, "comm", sort_comm),
1305 DIM(SORT_DSO, "dso", sort_dso),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001306 DIM(SORT_SYM, "symbol", sort_sym),
Roberto Agostino Vitillob5387522012-02-09 23:21:01 +01001307 DIM(SORT_PARENT, "parent", sort_parent),
1308 DIM(SORT_CPU, "cpu", sort_cpu),
Kan Liang2e7ea3a2015-09-04 10:45:43 -04001309 DIM(SORT_SOCKET, "socket", sort_socket),
Arnaldo Carvalho de Melo409a8be2012-05-30 10:33:24 -03001310 DIM(SORT_SRCLINE, "srcline", sort_srcline),
Andi Kleen31191a82015-08-07 15:54:24 -07001311 DIM(SORT_SRCFILE, "srcfile", sort_srcfile),
Andi Kleenf9ea55d2013-07-18 15:58:53 -07001312 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
1313 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
Andi Kleen475eeab2013-09-20 07:40:43 -07001314 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
Frederic Weisbecker872a8782011-06-29 03:14:52 +02001315};
1316
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001317#undef DIM
1318
1319#define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
1320
1321static struct sort_dimension bstack_sort_dimensions[] = {
1322 DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
1323 DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
1324 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
1325 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
1326 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
Andi Kleenf5d05bc2013-09-20 07:40:41 -07001327 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1328 DIM(SORT_ABORT, "abort", sort_abort),
Andi Kleen0e332f02015-07-18 08:24:46 -07001329 DIM(SORT_CYCLES, "cycles", sort_cycles),
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001330};
1331
1332#undef DIM
1333
Namhyung Kimafab87b2013-04-03 21:26:11 +09001334#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
1335
1336static struct sort_dimension memory_sort_dimensions[] = {
Namhyung Kimafab87b2013-04-03 21:26:11 +09001337 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
Don Zickus28e6db22015-10-05 20:06:07 +02001338 DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym),
Namhyung Kimafab87b2013-04-03 21:26:11 +09001339 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
1340 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
1341 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
1342 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
1343 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
Don Zickus9b32ba72014-06-01 15:38:29 +02001344 DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
Namhyung Kimafab87b2013-04-03 21:26:11 +09001345};
1346
1347#undef DIM
1348
Namhyung Kima2ce0672014-03-04 09:06:42 +09001349struct hpp_dimension {
1350 const char *name;
1351 struct perf_hpp_fmt *fmt;
1352 int taken;
1353};
1354
1355#define DIM(d, n) { .name = n, .fmt = &perf_hpp__format[d], }
1356
1357static struct hpp_dimension hpp_sort_dimensions[] = {
1358 DIM(PERF_HPP__OVERHEAD, "overhead"),
1359 DIM(PERF_HPP__OVERHEAD_SYS, "overhead_sys"),
1360 DIM(PERF_HPP__OVERHEAD_US, "overhead_us"),
1361 DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"),
1362 DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"),
Namhyung Kim594dcbf2013-10-30 16:06:59 +09001363 DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
Namhyung Kima2ce0672014-03-04 09:06:42 +09001364 DIM(PERF_HPP__SAMPLES, "sample"),
1365 DIM(PERF_HPP__PERIOD, "period"),
1366};
1367
1368#undef DIM
1369
Namhyung Kim8b536992014-03-03 11:46:55 +09001370struct hpp_sort_entry {
1371 struct perf_hpp_fmt hpp;
1372 struct sort_entry *se;
1373};
1374
Namhyung Kima7d945b2014-03-04 10:46:34 +09001375bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1376{
1377 struct hpp_sort_entry *hse_a;
1378 struct hpp_sort_entry *hse_b;
1379
1380 if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b))
1381 return false;
1382
1383 hse_a = container_of(a, struct hpp_sort_entry, hpp);
1384 hse_b = container_of(b, struct hpp_sort_entry, hpp);
1385
1386 return hse_a->se == hse_b->se;
1387}
1388
Namhyung Kime0d66c72014-07-31 14:47:37 +09001389void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
Namhyung Kim678a5002014-03-20 11:18:54 +09001390{
1391 struct hpp_sort_entry *hse;
1392
1393 if (!perf_hpp__is_sort_entry(fmt))
1394 return;
1395
1396 hse = container_of(fmt, struct hpp_sort_entry, hpp);
Namhyung Kim1ecd4452014-07-31 14:47:40 +09001397 hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
Namhyung Kim678a5002014-03-20 11:18:54 +09001398}
1399
Namhyung Kim8b536992014-03-03 11:46:55 +09001400static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1401 struct perf_evsel *evsel)
1402{
1403 struct hpp_sort_entry *hse;
Namhyung Kim5b591662014-07-31 14:47:38 +09001404 size_t len = fmt->user_len;
Namhyung Kim8b536992014-03-03 11:46:55 +09001405
1406 hse = container_of(fmt, struct hpp_sort_entry, hpp);
Namhyung Kim8b536992014-03-03 11:46:55 +09001407
Namhyung Kim5b591662014-07-31 14:47:38 +09001408 if (!len)
Arnaldo Carvalho de Melo4ea062ed2014-10-09 13:13:41 -03001409 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
Namhyung Kim5b591662014-07-31 14:47:38 +09001410
Namhyung Kim1ecd4452014-07-31 14:47:40 +09001411 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
Namhyung Kim8b536992014-03-03 11:46:55 +09001412}
1413
1414static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1415 struct perf_hpp *hpp __maybe_unused,
1416 struct perf_evsel *evsel)
1417{
1418 struct hpp_sort_entry *hse;
Namhyung Kim5b591662014-07-31 14:47:38 +09001419 size_t len = fmt->user_len;
Namhyung Kim8b536992014-03-03 11:46:55 +09001420
1421 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1422
Namhyung Kim5b591662014-07-31 14:47:38 +09001423 if (!len)
Arnaldo Carvalho de Melo4ea062ed2014-10-09 13:13:41 -03001424 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
Namhyung Kim5b591662014-07-31 14:47:38 +09001425
1426 return len;
Namhyung Kim8b536992014-03-03 11:46:55 +09001427}
1428
1429static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1430 struct hist_entry *he)
1431{
1432 struct hpp_sort_entry *hse;
Namhyung Kim5b591662014-07-31 14:47:38 +09001433 size_t len = fmt->user_len;
Namhyung Kim8b536992014-03-03 11:46:55 +09001434
1435 hse = container_of(fmt, struct hpp_sort_entry, hpp);
Namhyung Kim5b591662014-07-31 14:47:38 +09001436
1437 if (!len)
1438 len = hists__col_len(he->hists, hse->se->se_width_idx);
Namhyung Kim8b536992014-03-03 11:46:55 +09001439
1440 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1441}
1442
Namhyung Kim87bbdf72015-01-08 09:45:46 +09001443static int64_t __sort__hpp_cmp(struct perf_hpp_fmt *fmt,
1444 struct hist_entry *a, struct hist_entry *b)
1445{
1446 struct hpp_sort_entry *hse;
1447
1448 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1449 return hse->se->se_cmp(a, b);
1450}
1451
1452static int64_t __sort__hpp_collapse(struct perf_hpp_fmt *fmt,
1453 struct hist_entry *a, struct hist_entry *b)
1454{
1455 struct hpp_sort_entry *hse;
1456 int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
1457
1458 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1459 collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp;
1460 return collapse_fn(a, b);
1461}
1462
1463static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt,
1464 struct hist_entry *a, struct hist_entry *b)
1465{
1466 struct hpp_sort_entry *hse;
1467 int64_t (*sort_fn)(struct hist_entry *, struct hist_entry *);
1468
1469 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1470 sort_fn = hse->se->se_sort ?: hse->se->se_cmp;
1471 return sort_fn(a, b);
1472}
1473
Namhyung Kima7d945b2014-03-04 10:46:34 +09001474static struct hpp_sort_entry *
1475__sort_dimension__alloc_hpp(struct sort_dimension *sd)
Namhyung Kim8b536992014-03-03 11:46:55 +09001476{
1477 struct hpp_sort_entry *hse;
1478
1479 hse = malloc(sizeof(*hse));
1480 if (hse == NULL) {
1481 pr_err("Memory allocation failed\n");
Namhyung Kima7d945b2014-03-04 10:46:34 +09001482 return NULL;
Namhyung Kim8b536992014-03-03 11:46:55 +09001483 }
1484
1485 hse->se = sd->entry;
Namhyung Kim1ecd4452014-07-31 14:47:40 +09001486 hse->hpp.name = sd->entry->se_header;
Namhyung Kim8b536992014-03-03 11:46:55 +09001487 hse->hpp.header = __sort__hpp_header;
1488 hse->hpp.width = __sort__hpp_width;
1489 hse->hpp.entry = __sort__hpp_entry;
1490 hse->hpp.color = NULL;
1491
Namhyung Kim87bbdf72015-01-08 09:45:46 +09001492 hse->hpp.cmp = __sort__hpp_cmp;
1493 hse->hpp.collapse = __sort__hpp_collapse;
1494 hse->hpp.sort = __sort__hpp_sort;
Namhyung Kim8b536992014-03-03 11:46:55 +09001495
1496 INIT_LIST_HEAD(&hse->hpp.list);
1497 INIT_LIST_HEAD(&hse->hpp.sort_list);
Jiri Olsaf2998422014-05-23 17:15:47 +02001498 hse->hpp.elide = false;
Namhyung Kime0d66c72014-07-31 14:47:37 +09001499 hse->hpp.len = 0;
Namhyung Kim5b591662014-07-31 14:47:38 +09001500 hse->hpp.user_len = 0;
Namhyung Kim8b536992014-03-03 11:46:55 +09001501
Namhyung Kima7d945b2014-03-04 10:46:34 +09001502 return hse;
1503}
1504
1505bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format)
1506{
1507 return format->header == __sort__hpp_header;
1508}
1509
1510static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd)
1511{
1512 struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1513
1514 if (hse == NULL)
1515 return -1;
1516
Namhyung Kim8b536992014-03-03 11:46:55 +09001517 perf_hpp__register_sort_field(&hse->hpp);
1518 return 0;
1519}
1520
Namhyung Kima7d945b2014-03-04 10:46:34 +09001521static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
1522{
1523 struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
1524
1525 if (hse == NULL)
1526 return -1;
1527
1528 perf_hpp__column_register(&hse->hpp);
1529 return 0;
1530}
1531
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001532static int __sort_dimension__add(struct sort_dimension *sd)
Namhyung Kim2f532d02013-04-03 21:26:10 +09001533{
1534 if (sd->taken)
Namhyung Kim8b536992014-03-03 11:46:55 +09001535 return 0;
1536
Namhyung Kima7d945b2014-03-04 10:46:34 +09001537 if (__sort_dimension__add_hpp_sort(sd) < 0)
Namhyung Kim8b536992014-03-03 11:46:55 +09001538 return -1;
Namhyung Kim2f532d02013-04-03 21:26:10 +09001539
1540 if (sd->entry->se_collapse)
1541 sort__need_collapse = 1;
1542
Namhyung Kim2f532d02013-04-03 21:26:10 +09001543 sd->taken = 1;
Namhyung Kim8b536992014-03-03 11:46:55 +09001544
1545 return 0;
Namhyung Kim2f532d02013-04-03 21:26:10 +09001546}
1547
Namhyung Kima2ce0672014-03-04 09:06:42 +09001548static int __hpp_dimension__add(struct hpp_dimension *hd)
1549{
1550 if (!hd->taken) {
1551 hd->taken = 1;
1552
1553 perf_hpp__register_sort_field(hd->fmt);
1554 }
1555 return 0;
1556}
1557
Namhyung Kima7d945b2014-03-04 10:46:34 +09001558static int __sort_dimension__add_output(struct sort_dimension *sd)
1559{
1560 if (sd->taken)
1561 return 0;
1562
1563 if (__sort_dimension__add_hpp_output(sd) < 0)
1564 return -1;
1565
1566 sd->taken = 1;
1567 return 0;
1568}
1569
1570static int __hpp_dimension__add_output(struct hpp_dimension *hd)
1571{
1572 if (!hd->taken) {
1573 hd->taken = 1;
1574
1575 perf_hpp__column_register(hd->fmt);
1576 }
1577 return 0;
1578}
1579
Jiri Olsabeeaaeb2015-10-06 14:25:11 +02001580int hpp_dimension__add_output(unsigned col)
1581{
1582 BUG_ON(col >= PERF_HPP__MAX_INDEX);
1583 return __hpp_dimension__add_output(&hpp_sort_dimensions[col]);
1584}
1585
John Kacurdd68ada2009-09-24 18:02:49 +02001586int sort_dimension__add(const char *tok)
1587{
1588 unsigned int i;
1589
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001590 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1591 struct sort_dimension *sd = &common_sort_dimensions[i];
John Kacurdd68ada2009-09-24 18:02:49 +02001592
John Kacurdd68ada2009-09-24 18:02:49 +02001593 if (strncasecmp(tok, sd->name, strlen(tok)))
1594 continue;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001595
John Kacurdd68ada2009-09-24 18:02:49 +02001596 if (sd->entry == &sort_parent) {
1597 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
1598 if (ret) {
1599 char err[BUFSIZ];
1600
1601 regerror(ret, &parent_regex, err, sizeof(err));
Arnaldo Carvalho de Melo2aefa4f2010-04-02 12:30:57 -03001602 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
1603 return -EINVAL;
John Kacurdd68ada2009-09-24 18:02:49 +02001604 }
1605 sort__has_parent = 1;
Namhyung Kim930477b2013-04-05 10:26:36 +09001606 } else if (sd->entry == &sort_sym) {
Namhyung Kim1af556402012-09-14 17:35:27 +09001607 sort__has_sym = 1;
Kan Liang94ba4622015-02-09 05:39:44 +00001608 /*
1609 * perf diff displays the performance difference amongst
1610 * two or more perf.data files. Those files could come
1611 * from different binaries. So we should not compare
1612 * their ips, but the name of symbol.
1613 */
1614 if (sort__mode == SORT_MODE__DIFF)
1615 sd->entry->se_collapse = sort__sym_sort;
1616
Namhyung Kim68f6d022013-12-18 14:21:10 +09001617 } else if (sd->entry == &sort_dso) {
1618 sort__has_dso = 1;
Kan Liang2e7ea3a2015-09-04 10:45:43 -04001619 } else if (sd->entry == &sort_socket) {
1620 sort__has_socket = 1;
John Kacurdd68ada2009-09-24 18:02:49 +02001621 }
1622
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001623 return __sort_dimension__add(sd);
John Kacurdd68ada2009-09-24 18:02:49 +02001624 }
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001625
Namhyung Kima2ce0672014-03-04 09:06:42 +09001626 for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
1627 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
1628
1629 if (strncasecmp(tok, hd->name, strlen(tok)))
1630 continue;
1631
1632 return __hpp_dimension__add(hd);
1633 }
1634
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001635 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1636 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1637
1638 if (strncasecmp(tok, sd->name, strlen(tok)))
1639 continue;
1640
Namhyung Kim55369fc2013-04-01 20:35:20 +09001641 if (sort__mode != SORT_MODE__BRANCH)
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001642 return -EINVAL;
1643
1644 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
1645 sort__has_sym = 1;
1646
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001647 __sort_dimension__add(sd);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001648 return 0;
1649 }
1650
Namhyung Kimafab87b2013-04-03 21:26:11 +09001651 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1652 struct sort_dimension *sd = &memory_sort_dimensions[i];
1653
1654 if (strncasecmp(tok, sd->name, strlen(tok)))
1655 continue;
1656
1657 if (sort__mode != SORT_MODE__MEMORY)
1658 return -EINVAL;
1659
1660 if (sd->entry == &sort_mem_daddr_sym)
1661 sort__has_sym = 1;
1662
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001663 __sort_dimension__add(sd);
Namhyung Kimafab87b2013-04-03 21:26:11 +09001664 return 0;
1665 }
1666
John Kacurdd68ada2009-09-24 18:02:49 +02001667 return -ESRCH;
1668}
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001669
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001670static const char *get_default_sort_order(void)
1671{
1672 const char *default_sort_orders[] = {
1673 default_sort_order,
1674 default_branch_sort_order,
1675 default_mem_sort_order,
1676 default_top_sort_order,
1677 default_diff_sort_order,
1678 };
1679
1680 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
1681
1682 return default_sort_orders[sort__mode];
1683}
1684
Jiri Olsa1a1c0ff2014-08-23 14:59:48 +02001685static int setup_sort_order(void)
1686{
1687 char *new_sort_order;
1688
1689 /*
1690 * Append '+'-prefixed sort order to the default sort
1691 * order string.
1692 */
1693 if (!sort_order || is_strict_order(sort_order))
1694 return 0;
1695
1696 if (sort_order[1] == '\0') {
1697 error("Invalid --sort key: `+'");
1698 return -EINVAL;
1699 }
1700
1701 /*
1702 * We allocate new sort_order string, but we never free it,
1703 * because it's checked over the rest of the code.
1704 */
1705 if (asprintf(&new_sort_order, "%s,%s",
1706 get_default_sort_order(), sort_order + 1) < 0) {
1707 error("Not enough memory to set up --sort");
1708 return -ENOMEM;
1709 }
1710
1711 sort_order = new_sort_order;
1712 return 0;
1713}
1714
Namhyung Kima7d945b2014-03-04 10:46:34 +09001715static int __setup_sorting(void)
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001716{
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001717 char *tmp, *tok, *str;
Jiri Olsa1a1c0ff2014-08-23 14:59:48 +02001718 const char *sort_keys;
Namhyung Kim55309982013-02-06 14:57:16 +09001719 int ret = 0;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001720
Jiri Olsa1a1c0ff2014-08-23 14:59:48 +02001721 ret = setup_sort_order();
1722 if (ret)
1723 return ret;
1724
1725 sort_keys = sort_order;
Namhyung Kima7d945b2014-03-04 10:46:34 +09001726 if (sort_keys == NULL) {
Jiri Olsa2f3f9bc2014-08-22 15:58:38 +02001727 if (is_strict_order(field_order)) {
Namhyung Kima7d945b2014-03-04 10:46:34 +09001728 /*
1729 * If user specified field order but no sort order,
1730 * we'll honor it and not add default sort orders.
1731 */
1732 return 0;
1733 }
1734
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001735 sort_keys = get_default_sort_order();
Namhyung Kima7d945b2014-03-04 10:46:34 +09001736 }
Namhyung Kim512ae1b2014-03-18 11:31:39 +09001737
1738 str = strdup(sort_keys);
Namhyung Kim5936f542013-02-06 14:57:17 +09001739 if (str == NULL) {
1740 error("Not enough memory to setup sort keys");
1741 return -ENOMEM;
1742 }
1743
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001744 for (tok = strtok_r(str, ", ", &tmp);
1745 tok; tok = strtok_r(NULL, ", ", &tmp)) {
Namhyung Kim55309982013-02-06 14:57:16 +09001746 ret = sort_dimension__add(tok);
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001747 if (ret == -EINVAL) {
1748 error("Invalid --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001749 break;
Namhyung Kimfc5871e2012-12-27 18:11:46 +09001750 } else if (ret == -ESRCH) {
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001751 error("Unknown --sort key: `%s'", tok);
Namhyung Kim55309982013-02-06 14:57:16 +09001752 break;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001753 }
1754 }
1755
1756 free(str);
Namhyung Kim55309982013-02-06 14:57:16 +09001757 return ret;
Arnaldo Carvalho de Meloc8829c72009-12-14 20:09:29 -02001758}
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001759
Jiri Olsaf2998422014-05-23 17:15:47 +02001760void perf_hpp__set_elide(int idx, bool elide)
Namhyung Kime67d49a2014-03-18 13:00:59 +09001761{
Jiri Olsaf2998422014-05-23 17:15:47 +02001762 struct perf_hpp_fmt *fmt;
1763 struct hpp_sort_entry *hse;
Namhyung Kime67d49a2014-03-18 13:00:59 +09001764
Jiri Olsaf2998422014-05-23 17:15:47 +02001765 perf_hpp__for_each_format(fmt) {
1766 if (!perf_hpp__is_sort_entry(fmt))
1767 continue;
1768
1769 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1770 if (hse->se->se_width_idx == idx) {
1771 fmt->elide = elide;
1772 break;
1773 }
Namhyung Kime67d49a2014-03-18 13:00:59 +09001774 }
Namhyung Kime67d49a2014-03-18 13:00:59 +09001775}
1776
Jiri Olsaf2998422014-05-23 17:15:47 +02001777static bool __get_elide(struct strlist *list, const char *list_name, FILE *fp)
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001778{
1779 if (list && strlist__nr_entries(list) == 1) {
1780 if (fp != NULL)
1781 fprintf(fp, "# %s: %s\n", list_name,
1782 strlist__entry(list, 0)->s);
Jiri Olsaf2998422014-05-23 17:15:47 +02001783 return true;
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001784 }
Jiri Olsaf2998422014-05-23 17:15:47 +02001785 return false;
1786}
1787
1788static bool get_elide(int idx, FILE *output)
1789{
1790 switch (idx) {
1791 case HISTC_SYMBOL:
1792 return __get_elide(symbol_conf.sym_list, "symbol", output);
1793 case HISTC_DSO:
1794 return __get_elide(symbol_conf.dso_list, "dso", output);
1795 case HISTC_COMM:
1796 return __get_elide(symbol_conf.comm_list, "comm", output);
1797 default:
1798 break;
1799 }
1800
1801 if (sort__mode != SORT_MODE__BRANCH)
1802 return false;
1803
1804 switch (idx) {
1805 case HISTC_SYMBOL_FROM:
1806 return __get_elide(symbol_conf.sym_from_list, "sym_from", output);
1807 case HISTC_SYMBOL_TO:
1808 return __get_elide(symbol_conf.sym_to_list, "sym_to", output);
1809 case HISTC_DSO_FROM:
1810 return __get_elide(symbol_conf.dso_from_list, "dso_from", output);
1811 case HISTC_DSO_TO:
1812 return __get_elide(symbol_conf.dso_to_list, "dso_to", output);
1813 default:
1814 break;
1815 }
1816
1817 return false;
Arnaldo Carvalho de Meloc351c282009-12-16 13:49:27 -02001818}
Namhyung Kim08e71542013-04-03 21:26:19 +09001819
1820void sort__setup_elide(FILE *output)
1821{
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001822 struct perf_hpp_fmt *fmt;
1823 struct hpp_sort_entry *hse;
Namhyung Kim7524f632013-11-08 17:53:42 +09001824
Jiri Olsaf2998422014-05-23 17:15:47 +02001825 perf_hpp__for_each_format(fmt) {
1826 if (!perf_hpp__is_sort_entry(fmt))
1827 continue;
Namhyung Kim08e71542013-04-03 21:26:19 +09001828
Jiri Olsaf2998422014-05-23 17:15:47 +02001829 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1830 fmt->elide = get_elide(hse->se->se_width_idx, output);
Namhyung Kim08e71542013-04-03 21:26:19 +09001831 }
1832
Namhyung Kim7524f632013-11-08 17:53:42 +09001833 /*
1834 * It makes no sense to elide all of sort entries.
1835 * Just revert them to show up again.
1836 */
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001837 perf_hpp__for_each_format(fmt) {
1838 if (!perf_hpp__is_sort_entry(fmt))
1839 continue;
1840
Jiri Olsaf2998422014-05-23 17:15:47 +02001841 if (!fmt->elide)
Namhyung Kim7524f632013-11-08 17:53:42 +09001842 return;
1843 }
1844
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001845 perf_hpp__for_each_format(fmt) {
1846 if (!perf_hpp__is_sort_entry(fmt))
1847 continue;
1848
Jiri Olsaf2998422014-05-23 17:15:47 +02001849 fmt->elide = false;
Namhyung Kimcfaa1542014-05-19 14:19:30 +09001850 }
Namhyung Kim08e71542013-04-03 21:26:19 +09001851}
Namhyung Kima7d945b2014-03-04 10:46:34 +09001852
1853static int output_field_add(char *tok)
1854{
1855 unsigned int i;
1856
1857 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
1858 struct sort_dimension *sd = &common_sort_dimensions[i];
1859
1860 if (strncasecmp(tok, sd->name, strlen(tok)))
1861 continue;
1862
1863 return __sort_dimension__add_output(sd);
1864 }
1865
1866 for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
1867 struct hpp_dimension *hd = &hpp_sort_dimensions[i];
1868
1869 if (strncasecmp(tok, hd->name, strlen(tok)))
1870 continue;
1871
1872 return __hpp_dimension__add_output(hd);
1873 }
1874
1875 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
1876 struct sort_dimension *sd = &bstack_sort_dimensions[i];
1877
1878 if (strncasecmp(tok, sd->name, strlen(tok)))
1879 continue;
1880
1881 return __sort_dimension__add_output(sd);
1882 }
1883
1884 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
1885 struct sort_dimension *sd = &memory_sort_dimensions[i];
1886
1887 if (strncasecmp(tok, sd->name, strlen(tok)))
1888 continue;
1889
1890 return __sort_dimension__add_output(sd);
1891 }
1892
1893 return -ESRCH;
1894}
1895
1896static void reset_dimensions(void)
1897{
1898 unsigned int i;
1899
1900 for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++)
1901 common_sort_dimensions[i].taken = 0;
1902
1903 for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++)
1904 hpp_sort_dimensions[i].taken = 0;
1905
1906 for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++)
1907 bstack_sort_dimensions[i].taken = 0;
1908
1909 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++)
1910 memory_sort_dimensions[i].taken = 0;
1911}
1912
Jiri Olsa2f3f9bc2014-08-22 15:58:38 +02001913bool is_strict_order(const char *order)
1914{
1915 return order && (*order != '+');
1916}
1917
Namhyung Kima7d945b2014-03-04 10:46:34 +09001918static int __setup_output_field(void)
1919{
Jiri Olsa2f3f9bc2014-08-22 15:58:38 +02001920 char *tmp, *tok, *str, *strp;
1921 int ret = -EINVAL;
Namhyung Kima7d945b2014-03-04 10:46:34 +09001922
1923 if (field_order == NULL)
1924 return 0;
1925
Jiri Olsa2f3f9bc2014-08-22 15:58:38 +02001926 strp = str = strdup(field_order);
Namhyung Kima7d945b2014-03-04 10:46:34 +09001927 if (str == NULL) {
1928 error("Not enough memory to setup output fields");
1929 return -ENOMEM;
1930 }
1931
Jiri Olsa2f3f9bc2014-08-22 15:58:38 +02001932 if (!is_strict_order(field_order))
1933 strp++;
1934
1935 if (!strlen(strp)) {
1936 error("Invalid --fields key: `+'");
1937 goto out;
1938 }
1939
1940 for (tok = strtok_r(strp, ", ", &tmp);
Namhyung Kima7d945b2014-03-04 10:46:34 +09001941 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1942 ret = output_field_add(tok);
1943 if (ret == -EINVAL) {
1944 error("Invalid --fields key: `%s'", tok);
1945 break;
1946 } else if (ret == -ESRCH) {
1947 error("Unknown --fields key: `%s'", tok);
1948 break;
1949 }
1950 }
1951
Jiri Olsa2f3f9bc2014-08-22 15:58:38 +02001952out:
Namhyung Kima7d945b2014-03-04 10:46:34 +09001953 free(str);
1954 return ret;
1955}
1956
1957int setup_sorting(void)
1958{
1959 int err;
1960
1961 err = __setup_sorting();
1962 if (err < 0)
1963 return err;
1964
1965 if (parent_pattern != default_parent_pattern) {
1966 err = sort_dimension__add("parent");
1967 if (err < 0)
1968 return err;
1969 }
1970
1971 reset_dimensions();
1972
1973 /*
1974 * perf diff doesn't use default hpp output fields.
1975 */
1976 if (sort__mode != SORT_MODE__DIFF)
1977 perf_hpp__init();
1978
1979 err = __setup_output_field();
1980 if (err < 0)
1981 return err;
1982
1983 /* copy sort keys to output fields */
1984 perf_hpp__setup_output_field();
1985 /* and then copy output fields to sort keys */
1986 perf_hpp__append_sort_keys();
1987
1988 return 0;
1989}
Namhyung Kim1c89fe92014-05-07 18:42:24 +09001990
1991void reset_output_field(void)
1992{
1993 sort__need_collapse = 0;
1994 sort__has_parent = 0;
1995 sort__has_sym = 0;
1996 sort__has_dso = 0;
1997
Namhyung Kimd69b2962014-05-23 10:59:01 +09001998 field_order = NULL;
1999 sort_order = NULL;
2000
Namhyung Kim1c89fe92014-05-07 18:42:24 +09002001 reset_dimensions();
2002 perf_hpp__reset_output_field();
2003}