| Don Zickus | 9b32ba7 | 2014-06-01 15:38:29 +0200 | [diff] [blame] | 1 | #include <sys/mman.h> | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 2 | #include "sort.h" | 
| Arnaldo Carvalho de Melo | 8a6c5b2 | 2010-07-20 14:42:52 -0300 | [diff] [blame] | 3 | #include "hist.h" | 
| Namhyung Kim | 4dfced3 | 2013-09-13 16:28:57 +0900 | [diff] [blame] | 4 | #include "comm.h" | 
| Namhyung Kim | 08e7154 | 2013-04-03 21:26:19 +0900 | [diff] [blame] | 5 | #include "symbol.h" | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 6 | #include "evsel.h" | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 7 |  | 
 | 8 | regex_t		parent_regex; | 
| Arnaldo Carvalho de Melo | edb7c60 | 2010-05-17 16:22:41 -0300 | [diff] [blame] | 9 | const char	default_parent_pattern[] = "^sys_|^do_page_fault"; | 
 | 10 | const char	*parent_pattern = default_parent_pattern; | 
 | 11 | const char	default_sort_order[] = "comm,dso,symbol"; | 
| Andi Kleen | 40997d6 | 2015-07-18 08:24:53 -0700 | [diff] [blame] | 12 | const char	default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles"; | 
| Namhyung Kim | 512ae1b | 2014-03-18 11:31:39 +0900 | [diff] [blame] | 13 | const char	default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; | 
 | 14 | const char	default_top_sort_order[] = "dso,symbol"; | 
 | 15 | const char	default_diff_sort_order[] = "dso,symbol"; | 
 | 16 | const char	*sort_order; | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 17 | const char	*field_order; | 
| Greg Price | b21484f | 2012-12-06 21:48:05 -0800 | [diff] [blame] | 18 | regex_t		ignore_callees_regex; | 
 | 19 | int		have_ignore_callees = 0; | 
| Frederic Weisbecker | af0a6fa | 2009-10-22 23:23:22 +0200 | [diff] [blame] | 20 | int		sort__need_collapse = 0; | 
 | 21 | int		sort__has_parent = 0; | 
| Namhyung Kim | 1af55640 | 2012-09-14 17:35:27 +0900 | [diff] [blame] | 22 | int		sort__has_sym = 0; | 
| Namhyung Kim | 68f6d02 | 2013-12-18 14:21:10 +0900 | [diff] [blame] | 23 | int		sort__has_dso = 0; | 
| Kan Liang | 2e7ea3a | 2015-09-04 10:45:43 -0400 | [diff] [blame] | 24 | int		sort__has_socket = 0; | 
| Namhyung Kim | 55369fc | 2013-04-01 20:35:20 +0900 | [diff] [blame] | 25 | enum sort_mode	sort__mode = SORT_MODE__NORMAL; | 
| Frederic Weisbecker | a4fb581 | 2009-10-22 23:23:23 +0200 | [diff] [blame] | 26 |  | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 27 |  | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 28 | static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 29 | { | 
 | 30 | 	int n; | 
 | 31 | 	va_list ap; | 
 | 32 |  | 
 | 33 | 	va_start(ap, fmt); | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 34 | 	n = vsnprintf(bf, size, fmt, ap); | 
| Jiri Olsa | 0ca0c13 | 2012-09-06 17:46:56 +0200 | [diff] [blame] | 35 | 	if (symbol_conf.field_sep && n > 0) { | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 36 | 		char *sep = bf; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 37 |  | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 38 | 		while (1) { | 
| Jiri Olsa | 0ca0c13 | 2012-09-06 17:46:56 +0200 | [diff] [blame] | 39 | 			sep = strchr(sep, *symbol_conf.field_sep); | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 40 | 			if (sep == NULL) | 
 | 41 | 				break; | 
 | 42 | 			*sep = '.'; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 43 | 		} | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 44 | 	} | 
 | 45 | 	va_end(ap); | 
| Anton Blanchard | b832796 | 2012-03-07 11:42:49 +1100 | [diff] [blame] | 46 |  | 
 | 47 | 	if (n >= (int)size) | 
 | 48 | 		return size - 1; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 49 | 	return n; | 
 | 50 | } | 
 | 51 |  | 
| Frederic Weisbecker | b9c5143 | 2013-09-11 14:46:56 +0200 | [diff] [blame] | 52 | static int64_t cmp_null(const void *l, const void *r) | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 53 | { | 
 | 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 |  | 
 | 64 | static int64_t | 
 | 65 | sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 66 | { | 
| Adrian Hunter | 3805123 | 2013-07-04 16:20:31 +0300 | [diff] [blame] | 67 | 	return right->thread->tid - left->thread->tid; | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 68 | } | 
 | 69 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 70 | static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf, | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 71 | 				       size_t size, unsigned int width) | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 72 | { | 
| Frederic Weisbecker | b9c5143 | 2013-09-11 14:46:56 +0200 | [diff] [blame] | 73 | 	const char *comm = thread__comm_str(he->thread); | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 74 |  | 
 | 75 | 	width = max(7U, width) - 6; | 
 | 76 | 	return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid, | 
 | 77 | 			       width, width, comm ?: ""); | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 78 | } | 
 | 79 |  | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 80 | struct sort_entry sort_thread = { | 
| Namhyung Kim | 8246de8 | 2014-07-31 14:47:35 +0900 | [diff] [blame] | 81 | 	.se_header	= "  Pid:Command", | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 82 | 	.se_cmp		= sort__thread_cmp, | 
 | 83 | 	.se_snprintf	= hist_entry__thread_snprintf, | 
 | 84 | 	.se_width_idx	= HISTC_THREAD, | 
 | 85 | }; | 
 | 86 |  | 
 | 87 | /* --sort comm */ | 
 | 88 |  | 
 | 89 | static int64_t | 
 | 90 | sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 91 | { | 
| Frederic Weisbecker | fedd63d | 2013-09-11 17:18:09 +0200 | [diff] [blame] | 92 | 	/* Compare the addr that should be unique among comm */ | 
| Jiri Olsa | 2f15bd8 | 2015-05-15 17:54:28 +0200 | [diff] [blame] | 93 | 	return strcmp(comm__str(right->comm), comm__str(left->comm)); | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 94 | } | 
 | 95 |  | 
 | 96 | static int64_t | 
 | 97 | sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) | 
 | 98 | { | 
| Namhyung Kim | 4dfced3 | 2013-09-13 16:28:57 +0900 | [diff] [blame] | 99 | 	/* Compare the addr that should be unique among comm */ | 
| Jiri Olsa | 2f15bd8 | 2015-05-15 17:54:28 +0200 | [diff] [blame] | 100 | 	return strcmp(comm__str(right->comm), comm__str(left->comm)); | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 101 | } | 
 | 102 |  | 
| Namhyung Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 103 | static int64_t | 
 | 104 | sort__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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 109 | static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 110 | 				     size_t size, unsigned int width) | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 111 | { | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 112 | 	return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm)); | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 113 | } | 
 | 114 |  | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 115 | struct sort_entry sort_comm = { | 
 | 116 | 	.se_header	= "Command", | 
 | 117 | 	.se_cmp		= sort__comm_cmp, | 
 | 118 | 	.se_collapse	= sort__comm_collapse, | 
| Namhyung Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 119 | 	.se_sort	= sort__comm_sort, | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 120 | 	.se_snprintf	= hist_entry__comm_snprintf, | 
 | 121 | 	.se_width_idx	= HISTC_COMM, | 
 | 122 | }; | 
 | 123 |  | 
 | 124 | /* --sort dso */ | 
 | 125 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 126 | static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r) | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 127 | { | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 128 | 	struct dso *dso_l = map_l ? map_l->dso : NULL; | 
 | 129 | 	struct dso *dso_r = map_r ? map_r->dso : NULL; | 
| Arnaldo Carvalho de Melo | 439d473 | 2009-10-02 03:29:58 -0300 | [diff] [blame] | 130 | 	const char *dso_name_l, *dso_name_r; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 131 |  | 
 | 132 | 	if (!dso_l || !dso_r) | 
| Namhyung Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 133 | 		return cmp_null(dso_r, dso_l); | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 134 |  | 
| Arnaldo Carvalho de Melo | 439d473 | 2009-10-02 03:29:58 -0300 | [diff] [blame] | 135 | 	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 Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 144 | } | 
 | 145 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 146 | static int64_t | 
 | 147 | sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 148 | { | 
| Namhyung Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 149 | 	return _sort__dso_cmp(right->ms.map, left->ms.map); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 150 | } | 
 | 151 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 152 | static 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 Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 158 | 		return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name); | 
| Arnaldo Carvalho de Melo | 439d473 | 2009-10-02 03:29:58 -0300 | [diff] [blame] | 159 | 	} | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 160 |  | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 161 | 	return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]"); | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 162 | } | 
 | 163 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 164 | static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 165 | 				    size_t size, unsigned int width) | 
 | 166 | { | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 167 | 	return _hist_entry__dso_snprintf(he->ms.map, bf, size, width); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 168 | } | 
 | 169 |  | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 170 | struct 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 Kim | 2037be5 | 2013-12-18 14:21:09 +0900 | [diff] [blame] | 179 | static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip) | 
 | 180 | { | 
 | 181 | 	return (int64_t)(right_ip - left_ip); | 
 | 182 | } | 
 | 183 |  | 
| Namhyung Kim | 51f27d1 | 2013-02-06 14:57:15 +0900 | [diff] [blame] | 184 | static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 185 | { | 
 | 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 Brosseau | c05676c | 2015-06-17 16:41:10 -0700 | [diff] [blame] | 192 | 	if (sym_l->start != sym_r->start) | 
 | 193 | 		return (int64_t)(sym_r->start - sym_l->start); | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 194 |  | 
| Yannick Brosseau | c05676c | 2015-06-17 16:41:10 -0700 | [diff] [blame] | 195 | 	return (int64_t)(sym_r->end - sym_l->end); | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 196 | } | 
 | 197 |  | 
 | 198 | static int64_t | 
 | 199 | sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 200 | { | 
| Namhyung Kim | 09600e0 | 2013-10-15 11:01:56 +0900 | [diff] [blame] | 201 | 	int64_t ret; | 
 | 202 |  | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 203 | 	if (!left->ms.sym && !right->ms.sym) | 
| Namhyung Kim | 2037be5 | 2013-12-18 14:21:09 +0900 | [diff] [blame] | 204 | 		return _sort__addr_cmp(left->ip, right->ip); | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 205 |  | 
| Namhyung Kim | 09600e0 | 2013-10-15 11:01:56 +0900 | [diff] [blame] | 206 | 	/* | 
 | 207 | 	 * comparing symbol address alone is not enough since it's a | 
 | 208 | 	 * relative address within a dso. | 
 | 209 | 	 */ | 
| Namhyung Kim | 68f6d02 | 2013-12-18 14:21:10 +0900 | [diff] [blame] | 210 | 	if (!sort__has_dso) { | 
 | 211 | 		ret = sort__dso_cmp(left, right); | 
 | 212 | 		if (ret != 0) | 
 | 213 | 			return ret; | 
 | 214 | 	} | 
| Namhyung Kim | 09600e0 | 2013-10-15 11:01:56 +0900 | [diff] [blame] | 215 |  | 
| Namhyung Kim | 51f27d1 | 2013-02-06 14:57:15 +0900 | [diff] [blame] | 216 | 	return _sort__sym_cmp(left->ms.sym, right->ms.sym); | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 217 | } | 
 | 218 |  | 
| Namhyung Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 219 | static int64_t | 
 | 220 | sort__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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 228 | static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, | 
 | 229 | 				     u64 ip, char level, char *bf, size_t size, | 
| Namhyung Kim | 4335552 | 2012-12-27 18:11:39 +0900 | [diff] [blame] | 230 | 				     unsigned int width) | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 231 | { | 
 | 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 Kim | ded19d5 | 2013-04-01 20:35:19 +0900 | [diff] [blame] | 237 | 				       BITS_PER_LONG / 4 + 2, ip, o); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 238 | 	} | 
 | 239 |  | 
 | 240 | 	ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 241 | 	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 Kim | 6266774 | 2013-01-24 16:10:42 +0100 | [diff] [blame] | 245 | 					ip - map->unmap_ip(map, sym->start)); | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 246 | 			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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 254 | 		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 Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 261 | 	if (ret > width) | 
 | 262 | 		bf[width] = '\0'; | 
 | 263 |  | 
 | 264 | 	return width; | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 265 | } | 
 | 266 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 267 | static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, | 
| Namhyung Kim | 4335552 | 2012-12-27 18:11:39 +0900 | [diff] [blame] | 268 | 				    size_t size, unsigned int width) | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 269 | { | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 270 | 	return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip, | 
 | 271 | 					 he->level, bf, size, width); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 272 | } | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 273 |  | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 274 | struct sort_entry sort_sym = { | 
 | 275 | 	.se_header	= "Symbol", | 
 | 276 | 	.se_cmp		= sort__sym_cmp, | 
| Namhyung Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 277 | 	.se_sort	= sort__sym_sort, | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 278 | 	.se_snprintf	= hist_entry__sym_snprintf, | 
 | 279 | 	.se_width_idx	= HISTC_SYMBOL, | 
 | 280 | }; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 281 |  | 
| Arnaldo Carvalho de Melo | 409a8be | 2012-05-30 10:33:24 -0300 | [diff] [blame] | 282 | /* --sort srcline */ | 
 | 283 |  | 
 | 284 | static int64_t | 
 | 285 | sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 286 | { | 
| Namhyung Kim | 4adcc43 | 2013-09-11 14:09:33 +0900 | [diff] [blame] | 287 | 	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 Kleen | 85c116a | 2014-11-12 18:05:27 -0800 | [diff] [blame] | 293 | 					   map__rip_2objdump(map, left->ip), | 
 | 294 | 						    left->ms.sym, true); | 
| Namhyung Kim | 4adcc43 | 2013-09-11 14:09:33 +0900 | [diff] [blame] | 295 | 		} | 
 | 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 Kleen | 85c116a | 2014-11-12 18:05:27 -0800 | [diff] [blame] | 303 | 					     map__rip_2objdump(map, right->ip), | 
 | 304 | 						     right->ms.sym, true); | 
| Namhyung Kim | 4adcc43 | 2013-09-11 14:09:33 +0900 | [diff] [blame] | 305 | 		} | 
 | 306 | 	} | 
| Namhyung Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 307 | 	return strcmp(right->srcline, left->srcline); | 
| Arnaldo Carvalho de Melo | 409a8be | 2012-05-30 10:33:24 -0300 | [diff] [blame] | 308 | } | 
 | 309 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 310 | static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 311 | 					size_t size, unsigned int width) | 
| Arnaldo Carvalho de Melo | 409a8be | 2012-05-30 10:33:24 -0300 | [diff] [blame] | 312 | { | 
| Arnaldo Carvalho de Melo | b2d5367 | 2014-11-18 18:02:51 -0300 | [diff] [blame] | 313 | 	return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline); | 
| Arnaldo Carvalho de Melo | 409a8be | 2012-05-30 10:33:24 -0300 | [diff] [blame] | 314 | } | 
 | 315 |  | 
 | 316 | struct 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 Kleen | 31191a8 | 2015-08-07 15:54:24 -0700 | [diff] [blame] | 323 | /* --sort srcfile */ | 
 | 324 |  | 
 | 325 | static char no_srcfile[1]; | 
 | 326 |  | 
 | 327 | static char *get_srcfile(struct hist_entry *e) | 
 | 328 | { | 
 | 329 | 	char *sf, *p; | 
 | 330 | 	struct map *map = e->ms.map; | 
 | 331 |  | 
| Andi Kleen | 2f84b42 | 2015-09-01 11:47:19 -0700 | [diff] [blame] | 332 | 	sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), | 
 | 333 | 			 e->ms.sym, false, true); | 
| Andi Kleen | 76b1065 | 2015-08-11 06:36:55 -0700 | [diff] [blame] | 334 | 	if (!strcmp(sf, SRCLINE_UNKNOWN)) | 
 | 335 | 		return no_srcfile; | 
| Andi Kleen | 31191a8 | 2015-08-07 15:54:24 -0700 | [diff] [blame] | 336 | 	p = strchr(sf, ':'); | 
 | 337 | 	if (p && *sf) { | 
 | 338 | 		*p = 0; | 
 | 339 | 		return sf; | 
 | 340 | 	} | 
 | 341 | 	free(sf); | 
 | 342 | 	return no_srcfile; | 
 | 343 | } | 
 | 344 |  | 
 | 345 | static int64_t | 
 | 346 | sort__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 |  | 
 | 363 | static 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 |  | 
 | 369 | struct 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 Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 376 | /* --sort parent */ | 
 | 377 |  | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 378 | static int64_t | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 379 | sort__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 Kim | 202e7a6 | 2014-03-04 11:01:41 +0900 | [diff] [blame] | 387 | 	return strcmp(sym_r->name, sym_l->name); | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 388 | } | 
 | 389 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 390 | static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, | 
| Arnaldo Carvalho de Melo | a4e3b95 | 2010-03-31 11:33:40 -0300 | [diff] [blame] | 391 | 				       size_t size, unsigned int width) | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 392 | { | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 393 | 	return repsep_snprintf(bf, size, "%-*.*s", width, width, | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 394 | 			      he->parent ? he->parent->name : "[other]"); | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 395 | } | 
 | 396 |  | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 397 | struct 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 Sharma | f60f359 | 2010-06-04 11:27:10 -0300 | [diff] [blame] | 404 | /* --sort cpu */ | 
 | 405 |  | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 406 | static int64_t | 
| Arun Sharma | f60f359 | 2010-06-04 11:27:10 -0300 | [diff] [blame] | 407 | sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 408 | { | 
 | 409 | 	return right->cpu - left->cpu; | 
 | 410 | } | 
 | 411 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 412 | static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, | 
 | 413 | 				    size_t size, unsigned int width) | 
| Arun Sharma | f60f359 | 2010-06-04 11:27:10 -0300 | [diff] [blame] | 414 | { | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 415 | 	return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu); | 
| Arun Sharma | f60f359 | 2010-06-04 11:27:10 -0300 | [diff] [blame] | 416 | } | 
 | 417 |  | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 418 | struct 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 Liang | 2e7ea3a | 2015-09-04 10:45:43 -0400 | [diff] [blame] | 425 | /* --sort socket */ | 
 | 426 |  | 
 | 427 | static int64_t | 
 | 428 | sort__socket_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 429 | { | 
 | 430 | 	return right->socket - left->socket; | 
 | 431 | } | 
 | 432 |  | 
 | 433 | static 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 |  | 
 | 439 | struct 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 Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 446 | /* sort keys for branch stacks */ | 
 | 447 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 448 | static int64_t | 
 | 449 | sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 450 | { | 
| Jiri Olsa | 288a4b9 | 2014-10-16 16:07:07 +0200 | [diff] [blame] | 451 | 	if (!left->branch_info || !right->branch_info) | 
 | 452 | 		return cmp_null(left->branch_info, right->branch_info); | 
 | 453 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 454 | 	return _sort__dso_cmp(left->branch_info->from.map, | 
 | 455 | 			      right->branch_info->from.map); | 
 | 456 | } | 
 | 457 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 458 | static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 459 | 				    size_t size, unsigned int width) | 
 | 460 | { | 
| Jiri Olsa | 288a4b9 | 2014-10-16 16:07:07 +0200 | [diff] [blame] | 461 | 	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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 466 | } | 
 | 467 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 468 | static int64_t | 
 | 469 | sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 470 | { | 
| Jiri Olsa | 8b62fa5 | 2014-10-16 16:07:06 +0200 | [diff] [blame] | 471 | 	if (!left->branch_info || !right->branch_info) | 
 | 472 | 		return cmp_null(left->branch_info, right->branch_info); | 
 | 473 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 474 | 	return _sort__dso_cmp(left->branch_info->to.map, | 
 | 475 | 			      right->branch_info->to.map); | 
 | 476 | } | 
 | 477 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 478 | static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 479 | 				       size_t size, unsigned int width) | 
 | 480 | { | 
| Jiri Olsa | 8b62fa5 | 2014-10-16 16:07:06 +0200 | [diff] [blame] | 481 | 	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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 486 | } | 
 | 487 |  | 
 | 488 | static int64_t | 
 | 489 | sort__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 Olsa | 1b9e97a | 2014-10-16 16:07:05 +0200 | [diff] [blame] | 494 | 	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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 500 | 	if (!from_l->sym && !from_r->sym) | 
| Namhyung Kim | 2037be5 | 2013-12-18 14:21:09 +0900 | [diff] [blame] | 501 | 		return _sort__addr_cmp(from_l->addr, from_r->addr); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 502 |  | 
| Namhyung Kim | 51f27d1 | 2013-02-06 14:57:15 +0900 | [diff] [blame] | 503 | 	return _sort__sym_cmp(from_l->sym, from_r->sym); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 504 | } | 
 | 505 |  | 
 | 506 | static int64_t | 
 | 507 | sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 508 | { | 
| Jiri Olsa | 38cdbd3 | 2014-10-16 16:07:04 +0200 | [diff] [blame] | 509 | 	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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 516 |  | 
 | 517 | 	if (!to_l->sym && !to_r->sym) | 
| Namhyung Kim | 2037be5 | 2013-12-18 14:21:09 +0900 | [diff] [blame] | 518 | 		return _sort__addr_cmp(to_l->addr, to_r->addr); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 519 |  | 
| Namhyung Kim | 51f27d1 | 2013-02-06 14:57:15 +0900 | [diff] [blame] | 520 | 	return _sort__sym_cmp(to_l->sym, to_r->sym); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 521 | } | 
 | 522 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 523 | static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, | 
| Namhyung Kim | 4335552 | 2012-12-27 18:11:39 +0900 | [diff] [blame] | 524 | 					 size_t size, unsigned int width) | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 525 | { | 
| Jiri Olsa | 1b9e97a | 2014-10-16 16:07:05 +0200 | [diff] [blame] | 526 | 	if (he->branch_info) { | 
 | 527 | 		struct addr_map_symbol *from = &he->branch_info->from; | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 528 |  | 
| Jiri Olsa | 1b9e97a | 2014-10-16 16:07:05 +0200 | [diff] [blame] | 529 | 		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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 534 | } | 
 | 535 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 536 | static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, | 
| Namhyung Kim | 4335552 | 2012-12-27 18:11:39 +0900 | [diff] [blame] | 537 | 				       size_t size, unsigned int width) | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 538 | { | 
| Jiri Olsa | 38cdbd3 | 2014-10-16 16:07:04 +0200 | [diff] [blame] | 539 | 	if (he->branch_info) { | 
 | 540 | 		struct addr_map_symbol *to = &he->branch_info->to; | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 541 |  | 
| Jiri Olsa | 38cdbd3 | 2014-10-16 16:07:04 +0200 | [diff] [blame] | 542 | 		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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 547 | } | 
 | 548 |  | 
| Namhyung Kim | 14d1ac7 | 2012-12-27 18:11:38 +0900 | [diff] [blame] | 549 | struct 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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 556 | struct 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 |  | 
 | 563 | struct 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 |  | 
 | 570 | struct 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 |  | 
 | 577 | static int64_t | 
 | 578 | sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 579 | { | 
| Jiri Olsa | 428560e | 2014-10-16 16:07:03 +0200 | [diff] [blame] | 580 | 	unsigned char mp, p; | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 581 |  | 
| Jiri Olsa | 428560e | 2014-10-16 16:07:03 +0200 | [diff] [blame] | 582 | 	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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 587 | 	return mp || p; | 
 | 588 | } | 
 | 589 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 590 | static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf, | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 591 | 				    size_t size, unsigned int width){ | 
 | 592 | 	static const char *out = "N/A"; | 
 | 593 |  | 
| Jiri Olsa | 428560e | 2014-10-16 16:07:03 +0200 | [diff] [blame] | 594 | 	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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 600 |  | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 601 | 	return repsep_snprintf(bf, size, "%-*.*s", width, width, out); | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 602 | } | 
 | 603 |  | 
| Andi Kleen | 0e332f0 | 2015-07-18 08:24:46 -0700 | [diff] [blame] | 604 | static int64_t | 
 | 605 | sort__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 |  | 
 | 611 | static 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 |  | 
 | 620 | struct 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 Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 627 | /* --sort daddr_sym */ | 
 | 628 | static int64_t | 
 | 629 | sort__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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 641 | static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf, | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 642 | 				    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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 648 | 	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 Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 652 | 	} | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 653 | 	return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 654 | 					 width); | 
 | 655 | } | 
 | 656 |  | 
 | 657 | static int64_t | 
| Don Zickus | 28e6db2 | 2015-10-05 20:06:07 +0200 | [diff] [blame^] | 658 | sort__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 |  | 
 | 670 | static 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 |  | 
 | 686 | static int64_t | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 687 | sort__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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 700 | static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf, | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 701 | 				    size_t size, unsigned int width) | 
 | 702 | { | 
 | 703 | 	struct map *map = NULL; | 
 | 704 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 705 | 	if (he->mem_info) | 
 | 706 | 		map = he->mem_info->daddr.map; | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 707 |  | 
 | 708 | 	return _hist_entry__dso_snprintf(map, bf, size, width); | 
 | 709 | } | 
 | 710 |  | 
 | 711 | static int64_t | 
 | 712 | sort__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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 730 | static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf, | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 731 | 				    size_t size, unsigned int width) | 
 | 732 | { | 
 | 733 | 	const char *out; | 
 | 734 | 	u64 mask = PERF_MEM_LOCK_NA; | 
 | 735 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 736 | 	if (he->mem_info) | 
 | 737 | 		mask = he->mem_info->data_src.mem_lock; | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 738 |  | 
 | 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 |  | 
 | 749 | static int64_t | 
 | 750 | sort__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 |  | 
 | 768 | static 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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 779 | static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf, | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 780 | 				    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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 790 | 	if (he->mem_info) | 
 | 791 | 		m = he->mem_info->data_src.mem_dtlb; | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 792 |  | 
 | 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 |  | 
 | 819 | static int64_t | 
 | 820 | sort__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 |  | 
 | 838 | static 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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 856 | static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf, | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 857 | 				    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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 865 | 	if (he->mem_info) | 
 | 866 | 		m  = he->mem_info->data_src.mem_lvl; | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 867 |  | 
 | 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 |  | 
 | 896 | static int64_t | 
 | 897 | sort__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 |  | 
 | 915 | static 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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 924 | static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf, | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 925 | 				    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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 934 | 	if (he->mem_info) | 
 | 935 | 		m = he->mem_info->data_src.mem_snoop; | 
| Stephane Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 936 |  | 
 | 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 Zickus | 9b32ba7 | 2014-06-01 15:38:29 +0200 | [diff] [blame] | 954 | static inline  u64 cl_address(u64 address) | 
 | 955 | { | 
 | 956 | 	/* return the cacheline of the address */ | 
 | 957 | 	return (address & ~(cacheline_size - 1)); | 
 | 958 | } | 
 | 959 |  | 
 | 960 | static int64_t | 
 | 961 | sort__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 |  | 
 | 1013 | addr: | 
 | 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 |  | 
 | 1024 | static 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 Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 1052 | struct 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 Kleen | 0548429 | 2013-01-24 16:10:29 +0100 | [diff] [blame] | 1059 | static u64 he_weight(struct hist_entry *he) | 
 | 1060 | { | 
 | 1061 | 	return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0; | 
 | 1062 | } | 
 | 1063 |  | 
 | 1064 | static int64_t | 
 | 1065 | sort__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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1070 | static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, | 
| Andi Kleen | 0548429 | 2013-01-24 16:10:29 +0100 | [diff] [blame] | 1071 | 				    size_t size, unsigned int width) | 
 | 1072 | { | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1073 | 	return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he)); | 
| Andi Kleen | 0548429 | 2013-01-24 16:10:29 +0100 | [diff] [blame] | 1074 | } | 
 | 1075 |  | 
 | 1076 | struct 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 |  | 
 | 1083 | static int64_t | 
 | 1084 | sort__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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1089 | static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, | 
| Andi Kleen | 0548429 | 2013-01-24 16:10:29 +0100 | [diff] [blame] | 1090 | 					      size_t size, unsigned int width) | 
 | 1091 | { | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1092 | 	return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight); | 
| Andi Kleen | 0548429 | 2013-01-24 16:10:29 +0100 | [diff] [blame] | 1093 | } | 
 | 1094 |  | 
 | 1095 | struct 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 Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 1102 | struct 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 Zickus | 28e6db2 | 2015-10-05 20:06:07 +0200 | [diff] [blame^] | 1109 | struct 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 Eranian | 98a3b32 | 2013-01-24 16:10:35 +0100 | [diff] [blame] | 1116 | struct 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 |  | 
 | 1123 | struct 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 |  | 
 | 1130 | struct 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 |  | 
 | 1137 | struct 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 |  | 
 | 1144 | struct 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 Zickus | 9b32ba7 | 2014-06-01 15:38:29 +0200 | [diff] [blame] | 1151 | struct 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 Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1158 | static int64_t | 
 | 1159 | sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 1160 | { | 
| Jiri Olsa | 49f4744 | 2014-10-16 16:07:01 +0200 | [diff] [blame] | 1161 | 	if (!left->branch_info || !right->branch_info) | 
 | 1162 | 		return cmp_null(left->branch_info, right->branch_info); | 
 | 1163 |  | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1164 | 	return left->branch_info->flags.abort != | 
 | 1165 | 		right->branch_info->flags.abort; | 
 | 1166 | } | 
 | 1167 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1168 | static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf, | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1169 | 				    size_t size, unsigned int width) | 
 | 1170 | { | 
| Jiri Olsa | 49f4744 | 2014-10-16 16:07:01 +0200 | [diff] [blame] | 1171 | 	static const char *out = "N/A"; | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1172 |  | 
| Jiri Olsa | 49f4744 | 2014-10-16 16:07:01 +0200 | [diff] [blame] | 1173 | 	if (he->branch_info) { | 
 | 1174 | 		if (he->branch_info->flags.abort) | 
 | 1175 | 			out = "A"; | 
 | 1176 | 		else | 
 | 1177 | 			out = "."; | 
 | 1178 | 	} | 
 | 1179 |  | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1180 | 	return repsep_snprintf(bf, size, "%-*s", width, out); | 
 | 1181 | } | 
 | 1182 |  | 
 | 1183 | struct 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 |  | 
 | 1190 | static int64_t | 
 | 1191 | sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 1192 | { | 
| Jiri Olsa | 0199d24 | 2014-10-16 16:07:02 +0200 | [diff] [blame] | 1193 | 	if (!left->branch_info || !right->branch_info) | 
 | 1194 | 		return cmp_null(left->branch_info, right->branch_info); | 
 | 1195 |  | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1196 | 	return left->branch_info->flags.in_tx != | 
 | 1197 | 		right->branch_info->flags.in_tx; | 
 | 1198 | } | 
 | 1199 |  | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1200 | static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf, | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1201 | 				    size_t size, unsigned int width) | 
 | 1202 | { | 
| Jiri Olsa | 0199d24 | 2014-10-16 16:07:02 +0200 | [diff] [blame] | 1203 | 	static const char *out = "N/A"; | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1204 |  | 
| Jiri Olsa | 0199d24 | 2014-10-16 16:07:02 +0200 | [diff] [blame] | 1205 | 	if (he->branch_info) { | 
 | 1206 | 		if (he->branch_info->flags.in_tx) | 
 | 1207 | 			out = "T"; | 
 | 1208 | 		else | 
 | 1209 | 			out = "."; | 
 | 1210 | 	} | 
| Andi Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1211 |  | 
 | 1212 | 	return repsep_snprintf(bf, size, "%-*s", width, out); | 
 | 1213 | } | 
 | 1214 |  | 
 | 1215 | struct 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 Kleen | 475eeab | 2013-09-20 07:40:43 -0700 | [diff] [blame] | 1222 | static int64_t | 
 | 1223 | sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right) | 
 | 1224 | { | 
 | 1225 | 	return left->transaction - right->transaction; | 
 | 1226 | } | 
 | 1227 |  | 
 | 1228 | static inline char *add_str(char *p, const char *str) | 
 | 1229 | { | 
 | 1230 | 	strcpy(p, str); | 
 | 1231 | 	return p + strlen(str); | 
 | 1232 | } | 
 | 1233 |  | 
 | 1234 | static 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 |  | 
 | 1250 | int 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 Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1263 | static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf, | 
| Andi Kleen | 475eeab | 2013-09-20 07:40:43 -0700 | [diff] [blame] | 1264 | 					    size_t size, unsigned int width) | 
 | 1265 | { | 
| Arnaldo Carvalho de Melo | c824c43 | 2013-10-22 19:01:31 -0300 | [diff] [blame] | 1266 | 	u64 t = he->transaction; | 
| Andi Kleen | 475eeab | 2013-09-20 07:40:43 -0700 | [diff] [blame] | 1267 | 	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 |  | 
 | 1287 | struct 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 Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 1294 | struct sort_dimension { | 
 | 1295 | 	const char		*name; | 
 | 1296 | 	struct sort_entry	*entry; | 
 | 1297 | 	int			taken; | 
 | 1298 | }; | 
 | 1299 |  | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 1300 | #define DIM(d, n, func) [d] = { .name = n, .entry = &(func) } | 
 | 1301 |  | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1302 | static struct sort_dimension common_sort_dimensions[] = { | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 1303 | 	DIM(SORT_PID, "pid", sort_thread), | 
 | 1304 | 	DIM(SORT_COMM, "comm", sort_comm), | 
 | 1305 | 	DIM(SORT_DSO, "dso", sort_dso), | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 1306 | 	DIM(SORT_SYM, "symbol", sort_sym), | 
| Roberto Agostino Vitillo | b538752 | 2012-02-09 23:21:01 +0100 | [diff] [blame] | 1307 | 	DIM(SORT_PARENT, "parent", sort_parent), | 
 | 1308 | 	DIM(SORT_CPU, "cpu", sort_cpu), | 
| Kan Liang | 2e7ea3a | 2015-09-04 10:45:43 -0400 | [diff] [blame] | 1309 | 	DIM(SORT_SOCKET, "socket", sort_socket), | 
| Arnaldo Carvalho de Melo | 409a8be | 2012-05-30 10:33:24 -0300 | [diff] [blame] | 1310 | 	DIM(SORT_SRCLINE, "srcline", sort_srcline), | 
| Andi Kleen | 31191a8 | 2015-08-07 15:54:24 -0700 | [diff] [blame] | 1311 | 	DIM(SORT_SRCFILE, "srcfile", sort_srcfile), | 
| Andi Kleen | f9ea55d | 2013-07-18 15:58:53 -0700 | [diff] [blame] | 1312 | 	DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), | 
 | 1313 | 	DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), | 
| Andi Kleen | 475eeab | 2013-09-20 07:40:43 -0700 | [diff] [blame] | 1314 | 	DIM(SORT_TRANSACTION, "transaction", sort_transaction), | 
| Frederic Weisbecker | 872a878 | 2011-06-29 03:14:52 +0200 | [diff] [blame] | 1315 | }; | 
 | 1316 |  | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1317 | #undef DIM | 
 | 1318 |  | 
 | 1319 | #define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) } | 
 | 1320 |  | 
 | 1321 | static 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 Kleen | f5d05bc | 2013-09-20 07:40:41 -0700 | [diff] [blame] | 1327 | 	DIM(SORT_IN_TX, "in_tx", sort_in_tx), | 
 | 1328 | 	DIM(SORT_ABORT, "abort", sort_abort), | 
| Andi Kleen | 0e332f0 | 2015-07-18 08:24:46 -0700 | [diff] [blame] | 1329 | 	DIM(SORT_CYCLES, "cycles", sort_cycles), | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1330 | }; | 
 | 1331 |  | 
 | 1332 | #undef DIM | 
 | 1333 |  | 
| Namhyung Kim | afab87b | 2013-04-03 21:26:11 +0900 | [diff] [blame] | 1334 | #define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) } | 
 | 1335 |  | 
 | 1336 | static struct sort_dimension memory_sort_dimensions[] = { | 
| Namhyung Kim | afab87b | 2013-04-03 21:26:11 +0900 | [diff] [blame] | 1337 | 	DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), | 
| Don Zickus | 28e6db2 | 2015-10-05 20:06:07 +0200 | [diff] [blame^] | 1338 | 	DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym), | 
| Namhyung Kim | afab87b | 2013-04-03 21:26:11 +0900 | [diff] [blame] | 1339 | 	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 Zickus | 9b32ba7 | 2014-06-01 15:38:29 +0200 | [diff] [blame] | 1344 | 	DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline), | 
| Namhyung Kim | afab87b | 2013-04-03 21:26:11 +0900 | [diff] [blame] | 1345 | }; | 
 | 1346 |  | 
 | 1347 | #undef DIM | 
 | 1348 |  | 
| Namhyung Kim | a2ce067 | 2014-03-04 09:06:42 +0900 | [diff] [blame] | 1349 | struct 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 |  | 
 | 1357 | static 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 Kim | 594dcbf | 2013-10-30 16:06:59 +0900 | [diff] [blame] | 1363 | 	DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"), | 
| Namhyung Kim | a2ce067 | 2014-03-04 09:06:42 +0900 | [diff] [blame] | 1364 | 	DIM(PERF_HPP__SAMPLES, "sample"), | 
 | 1365 | 	DIM(PERF_HPP__PERIOD, "period"), | 
 | 1366 | }; | 
 | 1367 |  | 
 | 1368 | #undef DIM | 
 | 1369 |  | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1370 | struct hpp_sort_entry { | 
 | 1371 | 	struct perf_hpp_fmt hpp; | 
 | 1372 | 	struct sort_entry *se; | 
 | 1373 | }; | 
 | 1374 |  | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1375 | bool 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 Kim | e0d66c7 | 2014-07-31 14:47:37 +0900 | [diff] [blame] | 1389 | void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists) | 
| Namhyung Kim | 678a500 | 2014-03-20 11:18:54 +0900 | [diff] [blame] | 1390 | { | 
 | 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 Kim | 1ecd445 | 2014-07-31 14:47:40 +0900 | [diff] [blame] | 1397 | 	hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name)); | 
| Namhyung Kim | 678a500 | 2014-03-20 11:18:54 +0900 | [diff] [blame] | 1398 | } | 
 | 1399 |  | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1400 | static 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 Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1404 | 	size_t len = fmt->user_len; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1405 |  | 
 | 1406 | 	hse = container_of(fmt, struct hpp_sort_entry, hpp); | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1407 |  | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1408 | 	if (!len) | 
| Arnaldo Carvalho de Melo | 4ea062ed | 2014-10-09 13:13:41 -0300 | [diff] [blame] | 1409 | 		len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1410 |  | 
| Namhyung Kim | 1ecd445 | 2014-07-31 14:47:40 +0900 | [diff] [blame] | 1411 | 	return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name); | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1412 | } | 
 | 1413 |  | 
 | 1414 | static 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 Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1419 | 	size_t len = fmt->user_len; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1420 |  | 
 | 1421 | 	hse = container_of(fmt, struct hpp_sort_entry, hpp); | 
 | 1422 |  | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1423 | 	if (!len) | 
| Arnaldo Carvalho de Melo | 4ea062ed | 2014-10-09 13:13:41 -0300 | [diff] [blame] | 1424 | 		len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1425 |  | 
 | 1426 | 	return len; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1427 | } | 
 | 1428 |  | 
 | 1429 | static 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 Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1433 | 	size_t len = fmt->user_len; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1434 |  | 
 | 1435 | 	hse = container_of(fmt, struct hpp_sort_entry, hpp); | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1436 |  | 
 | 1437 | 	if (!len) | 
 | 1438 | 		len = hists__col_len(he->hists, hse->se->se_width_idx); | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1439 |  | 
 | 1440 | 	return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); | 
 | 1441 | } | 
 | 1442 |  | 
| Namhyung Kim | 87bbdf7 | 2015-01-08 09:45:46 +0900 | [diff] [blame] | 1443 | static 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 |  | 
 | 1452 | static 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 |  | 
 | 1463 | static 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 Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1474 | static struct hpp_sort_entry * | 
 | 1475 | __sort_dimension__alloc_hpp(struct sort_dimension *sd) | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1476 | { | 
 | 1477 | 	struct hpp_sort_entry *hse; | 
 | 1478 |  | 
 | 1479 | 	hse = malloc(sizeof(*hse)); | 
 | 1480 | 	if (hse == NULL) { | 
 | 1481 | 		pr_err("Memory allocation failed\n"); | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1482 | 		return NULL; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1483 | 	} | 
 | 1484 |  | 
 | 1485 | 	hse->se = sd->entry; | 
| Namhyung Kim | 1ecd445 | 2014-07-31 14:47:40 +0900 | [diff] [blame] | 1486 | 	hse->hpp.name = sd->entry->se_header; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1487 | 	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 Kim | 87bbdf7 | 2015-01-08 09:45:46 +0900 | [diff] [blame] | 1492 | 	hse->hpp.cmp = __sort__hpp_cmp; | 
 | 1493 | 	hse->hpp.collapse = __sort__hpp_collapse; | 
 | 1494 | 	hse->hpp.sort = __sort__hpp_sort; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1495 |  | 
 | 1496 | 	INIT_LIST_HEAD(&hse->hpp.list); | 
 | 1497 | 	INIT_LIST_HEAD(&hse->hpp.sort_list); | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1498 | 	hse->hpp.elide = false; | 
| Namhyung Kim | e0d66c7 | 2014-07-31 14:47:37 +0900 | [diff] [blame] | 1499 | 	hse->hpp.len = 0; | 
| Namhyung Kim | 5b59166 | 2014-07-31 14:47:38 +0900 | [diff] [blame] | 1500 | 	hse->hpp.user_len = 0; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1501 |  | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1502 | 	return hse; | 
 | 1503 | } | 
 | 1504 |  | 
 | 1505 | bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format) | 
 | 1506 | { | 
 | 1507 | 	return format->header == __sort__hpp_header; | 
 | 1508 | } | 
 | 1509 |  | 
 | 1510 | static 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 Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1517 | 	perf_hpp__register_sort_field(&hse->hpp); | 
 | 1518 | 	return 0; | 
 | 1519 | } | 
 | 1520 |  | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1521 | static 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 Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1532 | static int __sort_dimension__add(struct sort_dimension *sd) | 
| Namhyung Kim | 2f532d09 | 2013-04-03 21:26:10 +0900 | [diff] [blame] | 1533 | { | 
 | 1534 | 	if (sd->taken) | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1535 | 		return 0; | 
 | 1536 |  | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1537 | 	if (__sort_dimension__add_hpp_sort(sd) < 0) | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1538 | 		return -1; | 
| Namhyung Kim | 2f532d09 | 2013-04-03 21:26:10 +0900 | [diff] [blame] | 1539 |  | 
 | 1540 | 	if (sd->entry->se_collapse) | 
 | 1541 | 		sort__need_collapse = 1; | 
 | 1542 |  | 
| Namhyung Kim | 2f532d09 | 2013-04-03 21:26:10 +0900 | [diff] [blame] | 1543 | 	sd->taken = 1; | 
| Namhyung Kim | 8b53699 | 2014-03-03 11:46:55 +0900 | [diff] [blame] | 1544 |  | 
 | 1545 | 	return 0; | 
| Namhyung Kim | 2f532d09 | 2013-04-03 21:26:10 +0900 | [diff] [blame] | 1546 | } | 
 | 1547 |  | 
| Namhyung Kim | a2ce067 | 2014-03-04 09:06:42 +0900 | [diff] [blame] | 1548 | static 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 Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1558 | static 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 |  | 
 | 1570 | static 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 |  | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1580 | int sort_dimension__add(const char *tok) | 
 | 1581 | { | 
 | 1582 | 	unsigned int i; | 
 | 1583 |  | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1584 | 	for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) { | 
 | 1585 | 		struct sort_dimension *sd = &common_sort_dimensions[i]; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1586 |  | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1587 | 		if (strncasecmp(tok, sd->name, strlen(tok))) | 
 | 1588 | 			continue; | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1589 |  | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1590 | 		if (sd->entry == &sort_parent) { | 
 | 1591 | 			int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); | 
 | 1592 | 			if (ret) { | 
 | 1593 | 				char err[BUFSIZ]; | 
 | 1594 |  | 
 | 1595 | 				regerror(ret, &parent_regex, err, sizeof(err)); | 
| Arnaldo Carvalho de Melo | 2aefa4f | 2010-04-02 12:30:57 -0300 | [diff] [blame] | 1596 | 				pr_err("Invalid regex: %s\n%s", parent_pattern, err); | 
 | 1597 | 				return -EINVAL; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1598 | 			} | 
 | 1599 | 			sort__has_parent = 1; | 
| Namhyung Kim | 930477b | 2013-04-05 10:26:36 +0900 | [diff] [blame] | 1600 | 		} else if (sd->entry == &sort_sym) { | 
| Namhyung Kim | 1af55640 | 2012-09-14 17:35:27 +0900 | [diff] [blame] | 1601 | 			sort__has_sym = 1; | 
| Kan Liang | 94ba462 | 2015-02-09 05:39:44 +0000 | [diff] [blame] | 1602 | 			/* | 
 | 1603 | 			 * perf diff displays the performance difference amongst | 
 | 1604 | 			 * two or more perf.data files. Those files could come | 
 | 1605 | 			 * from different binaries. So we should not compare | 
 | 1606 | 			 * their ips, but the name of symbol. | 
 | 1607 | 			 */ | 
 | 1608 | 			if (sort__mode == SORT_MODE__DIFF) | 
 | 1609 | 				sd->entry->se_collapse = sort__sym_sort; | 
 | 1610 |  | 
| Namhyung Kim | 68f6d02 | 2013-12-18 14:21:10 +0900 | [diff] [blame] | 1611 | 		} else if (sd->entry == &sort_dso) { | 
 | 1612 | 			sort__has_dso = 1; | 
| Kan Liang | 2e7ea3a | 2015-09-04 10:45:43 -0400 | [diff] [blame] | 1613 | 		} else if (sd->entry == &sort_socket) { | 
 | 1614 | 			sort__has_socket = 1; | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1615 | 		} | 
 | 1616 |  | 
| Namhyung Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1617 | 		return __sort_dimension__add(sd); | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1618 | 	} | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1619 |  | 
| Namhyung Kim | a2ce067 | 2014-03-04 09:06:42 +0900 | [diff] [blame] | 1620 | 	for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { | 
 | 1621 | 		struct hpp_dimension *hd = &hpp_sort_dimensions[i]; | 
 | 1622 |  | 
 | 1623 | 		if (strncasecmp(tok, hd->name, strlen(tok))) | 
 | 1624 | 			continue; | 
 | 1625 |  | 
 | 1626 | 		return __hpp_dimension__add(hd); | 
 | 1627 | 	} | 
 | 1628 |  | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1629 | 	for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { | 
 | 1630 | 		struct sort_dimension *sd = &bstack_sort_dimensions[i]; | 
 | 1631 |  | 
 | 1632 | 		if (strncasecmp(tok, sd->name, strlen(tok))) | 
 | 1633 | 			continue; | 
 | 1634 |  | 
| Namhyung Kim | 55369fc | 2013-04-01 20:35:20 +0900 | [diff] [blame] | 1635 | 		if (sort__mode != SORT_MODE__BRANCH) | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1636 | 			return -EINVAL; | 
 | 1637 |  | 
 | 1638 | 		if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) | 
 | 1639 | 			sort__has_sym = 1; | 
 | 1640 |  | 
| Namhyung Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1641 | 		__sort_dimension__add(sd); | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1642 | 		return 0; | 
 | 1643 | 	} | 
 | 1644 |  | 
| Namhyung Kim | afab87b | 2013-04-03 21:26:11 +0900 | [diff] [blame] | 1645 | 	for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { | 
 | 1646 | 		struct sort_dimension *sd = &memory_sort_dimensions[i]; | 
 | 1647 |  | 
 | 1648 | 		if (strncasecmp(tok, sd->name, strlen(tok))) | 
 | 1649 | 			continue; | 
 | 1650 |  | 
 | 1651 | 		if (sort__mode != SORT_MODE__MEMORY) | 
 | 1652 | 			return -EINVAL; | 
 | 1653 |  | 
 | 1654 | 		if (sd->entry == &sort_mem_daddr_sym) | 
 | 1655 | 			sort__has_sym = 1; | 
 | 1656 |  | 
| Namhyung Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1657 | 		__sort_dimension__add(sd); | 
| Namhyung Kim | afab87b | 2013-04-03 21:26:11 +0900 | [diff] [blame] | 1658 | 		return 0; | 
 | 1659 | 	} | 
 | 1660 |  | 
| John Kacur | dd68ada | 2009-09-24 18:02:49 +0200 | [diff] [blame] | 1661 | 	return -ESRCH; | 
 | 1662 | } | 
| Arnaldo Carvalho de Melo | c8829c7 | 2009-12-14 20:09:29 -0200 | [diff] [blame] | 1663 |  | 
| Namhyung Kim | 512ae1b | 2014-03-18 11:31:39 +0900 | [diff] [blame] | 1664 | static const char *get_default_sort_order(void) | 
 | 1665 | { | 
 | 1666 | 	const char *default_sort_orders[] = { | 
 | 1667 | 		default_sort_order, | 
 | 1668 | 		default_branch_sort_order, | 
 | 1669 | 		default_mem_sort_order, | 
 | 1670 | 		default_top_sort_order, | 
 | 1671 | 		default_diff_sort_order, | 
 | 1672 | 	}; | 
 | 1673 |  | 
 | 1674 | 	BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); | 
 | 1675 |  | 
 | 1676 | 	return default_sort_orders[sort__mode]; | 
 | 1677 | } | 
 | 1678 |  | 
| Jiri Olsa | 1a1c0ff | 2014-08-23 14:59:48 +0200 | [diff] [blame] | 1679 | static int setup_sort_order(void) | 
 | 1680 | { | 
 | 1681 | 	char *new_sort_order; | 
 | 1682 |  | 
 | 1683 | 	/* | 
 | 1684 | 	 * Append '+'-prefixed sort order to the default sort | 
 | 1685 | 	 * order string. | 
 | 1686 | 	 */ | 
 | 1687 | 	if (!sort_order || is_strict_order(sort_order)) | 
 | 1688 | 		return 0; | 
 | 1689 |  | 
 | 1690 | 	if (sort_order[1] == '\0') { | 
 | 1691 | 		error("Invalid --sort key: `+'"); | 
 | 1692 | 		return -EINVAL; | 
 | 1693 | 	} | 
 | 1694 |  | 
 | 1695 | 	/* | 
 | 1696 | 	 * We allocate new sort_order string, but we never free it, | 
 | 1697 | 	 * because it's checked over the rest of the code. | 
 | 1698 | 	 */ | 
 | 1699 | 	if (asprintf(&new_sort_order, "%s,%s", | 
 | 1700 | 		     get_default_sort_order(), sort_order + 1) < 0) { | 
 | 1701 | 		error("Not enough memory to set up --sort"); | 
 | 1702 | 		return -ENOMEM; | 
 | 1703 | 	} | 
 | 1704 |  | 
 | 1705 | 	sort_order = new_sort_order; | 
 | 1706 | 	return 0; | 
 | 1707 | } | 
 | 1708 |  | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1709 | static int __setup_sorting(void) | 
| Arnaldo Carvalho de Melo | c8829c7 | 2009-12-14 20:09:29 -0200 | [diff] [blame] | 1710 | { | 
| Namhyung Kim | 512ae1b | 2014-03-18 11:31:39 +0900 | [diff] [blame] | 1711 | 	char *tmp, *tok, *str; | 
| Jiri Olsa | 1a1c0ff | 2014-08-23 14:59:48 +0200 | [diff] [blame] | 1712 | 	const char *sort_keys; | 
| Namhyung Kim | 5530998 | 2013-02-06 14:57:16 +0900 | [diff] [blame] | 1713 | 	int ret = 0; | 
| Arnaldo Carvalho de Melo | c8829c7 | 2009-12-14 20:09:29 -0200 | [diff] [blame] | 1714 |  | 
| Jiri Olsa | 1a1c0ff | 2014-08-23 14:59:48 +0200 | [diff] [blame] | 1715 | 	ret = setup_sort_order(); | 
 | 1716 | 	if (ret) | 
 | 1717 | 		return ret; | 
 | 1718 |  | 
 | 1719 | 	sort_keys = sort_order; | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1720 | 	if (sort_keys == NULL) { | 
| Jiri Olsa | 2f3f9bc | 2014-08-22 15:58:38 +0200 | [diff] [blame] | 1721 | 		if (is_strict_order(field_order)) { | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1722 | 			/* | 
 | 1723 | 			 * If user specified field order but no sort order, | 
 | 1724 | 			 * we'll honor it and not add default sort orders. | 
 | 1725 | 			 */ | 
 | 1726 | 			return 0; | 
 | 1727 | 		} | 
 | 1728 |  | 
| Namhyung Kim | 512ae1b | 2014-03-18 11:31:39 +0900 | [diff] [blame] | 1729 | 		sort_keys = get_default_sort_order(); | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1730 | 	} | 
| Namhyung Kim | 512ae1b | 2014-03-18 11:31:39 +0900 | [diff] [blame] | 1731 |  | 
 | 1732 | 	str = strdup(sort_keys); | 
| Namhyung Kim | 5936f54 | 2013-02-06 14:57:17 +0900 | [diff] [blame] | 1733 | 	if (str == NULL) { | 
 | 1734 | 		error("Not enough memory to setup sort keys"); | 
 | 1735 | 		return -ENOMEM; | 
 | 1736 | 	} | 
 | 1737 |  | 
| Arnaldo Carvalho de Melo | c8829c7 | 2009-12-14 20:09:29 -0200 | [diff] [blame] | 1738 | 	for (tok = strtok_r(str, ", ", &tmp); | 
 | 1739 | 			tok; tok = strtok_r(NULL, ", ", &tmp)) { | 
| Namhyung Kim | 5530998 | 2013-02-06 14:57:16 +0900 | [diff] [blame] | 1740 | 		ret = sort_dimension__add(tok); | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1741 | 		if (ret == -EINVAL) { | 
 | 1742 | 			error("Invalid --sort key: `%s'", tok); | 
| Namhyung Kim | 5530998 | 2013-02-06 14:57:16 +0900 | [diff] [blame] | 1743 | 			break; | 
| Namhyung Kim | fc5871e | 2012-12-27 18:11:46 +0900 | [diff] [blame] | 1744 | 		} else if (ret == -ESRCH) { | 
| Arnaldo Carvalho de Melo | c8829c7 | 2009-12-14 20:09:29 -0200 | [diff] [blame] | 1745 | 			error("Unknown --sort key: `%s'", tok); | 
| Namhyung Kim | 5530998 | 2013-02-06 14:57:16 +0900 | [diff] [blame] | 1746 | 			break; | 
| Arnaldo Carvalho de Melo | c8829c7 | 2009-12-14 20:09:29 -0200 | [diff] [blame] | 1747 | 		} | 
 | 1748 | 	} | 
 | 1749 |  | 
 | 1750 | 	free(str); | 
| Namhyung Kim | 5530998 | 2013-02-06 14:57:16 +0900 | [diff] [blame] | 1751 | 	return ret; | 
| Arnaldo Carvalho de Melo | c8829c7 | 2009-12-14 20:09:29 -0200 | [diff] [blame] | 1752 | } | 
| Arnaldo Carvalho de Melo | c351c28 | 2009-12-16 13:49:27 -0200 | [diff] [blame] | 1753 |  | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1754 | void perf_hpp__set_elide(int idx, bool elide) | 
| Namhyung Kim | e67d49a | 2014-03-18 13:00:59 +0900 | [diff] [blame] | 1755 | { | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1756 | 	struct perf_hpp_fmt *fmt; | 
 | 1757 | 	struct hpp_sort_entry *hse; | 
| Namhyung Kim | e67d49a | 2014-03-18 13:00:59 +0900 | [diff] [blame] | 1758 |  | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1759 | 	perf_hpp__for_each_format(fmt) { | 
 | 1760 | 		if (!perf_hpp__is_sort_entry(fmt)) | 
 | 1761 | 			continue; | 
 | 1762 |  | 
 | 1763 | 		hse = container_of(fmt, struct hpp_sort_entry, hpp); | 
 | 1764 | 		if (hse->se->se_width_idx == idx) { | 
 | 1765 | 			fmt->elide = elide; | 
 | 1766 | 			break; | 
 | 1767 | 		} | 
| Namhyung Kim | e67d49a | 2014-03-18 13:00:59 +0900 | [diff] [blame] | 1768 | 	} | 
| Namhyung Kim | e67d49a | 2014-03-18 13:00:59 +0900 | [diff] [blame] | 1769 | } | 
 | 1770 |  | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1771 | static bool __get_elide(struct strlist *list, const char *list_name, FILE *fp) | 
| Arnaldo Carvalho de Melo | c351c28 | 2009-12-16 13:49:27 -0200 | [diff] [blame] | 1772 | { | 
 | 1773 | 	if (list && strlist__nr_entries(list) == 1) { | 
 | 1774 | 		if (fp != NULL) | 
 | 1775 | 			fprintf(fp, "# %s: %s\n", list_name, | 
 | 1776 | 				strlist__entry(list, 0)->s); | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1777 | 		return true; | 
| Arnaldo Carvalho de Melo | c351c28 | 2009-12-16 13:49:27 -0200 | [diff] [blame] | 1778 | 	} | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1779 | 	return false; | 
 | 1780 | } | 
 | 1781 |  | 
 | 1782 | static bool get_elide(int idx, FILE *output) | 
 | 1783 | { | 
 | 1784 | 	switch (idx) { | 
 | 1785 | 	case HISTC_SYMBOL: | 
 | 1786 | 		return __get_elide(symbol_conf.sym_list, "symbol", output); | 
 | 1787 | 	case HISTC_DSO: | 
 | 1788 | 		return __get_elide(symbol_conf.dso_list, "dso", output); | 
 | 1789 | 	case HISTC_COMM: | 
 | 1790 | 		return __get_elide(symbol_conf.comm_list, "comm", output); | 
 | 1791 | 	default: | 
 | 1792 | 		break; | 
 | 1793 | 	} | 
 | 1794 |  | 
 | 1795 | 	if (sort__mode != SORT_MODE__BRANCH) | 
 | 1796 | 		return false; | 
 | 1797 |  | 
 | 1798 | 	switch (idx) { | 
 | 1799 | 	case HISTC_SYMBOL_FROM: | 
 | 1800 | 		return __get_elide(symbol_conf.sym_from_list, "sym_from", output); | 
 | 1801 | 	case HISTC_SYMBOL_TO: | 
 | 1802 | 		return __get_elide(symbol_conf.sym_to_list, "sym_to", output); | 
 | 1803 | 	case HISTC_DSO_FROM: | 
 | 1804 | 		return __get_elide(symbol_conf.dso_from_list, "dso_from", output); | 
 | 1805 | 	case HISTC_DSO_TO: | 
 | 1806 | 		return __get_elide(symbol_conf.dso_to_list, "dso_to", output); | 
 | 1807 | 	default: | 
 | 1808 | 		break; | 
 | 1809 | 	} | 
 | 1810 |  | 
 | 1811 | 	return false; | 
| Arnaldo Carvalho de Melo | c351c28 | 2009-12-16 13:49:27 -0200 | [diff] [blame] | 1812 | } | 
| Namhyung Kim | 08e7154 | 2013-04-03 21:26:19 +0900 | [diff] [blame] | 1813 |  | 
 | 1814 | void sort__setup_elide(FILE *output) | 
 | 1815 | { | 
| Namhyung Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1816 | 	struct perf_hpp_fmt *fmt; | 
 | 1817 | 	struct hpp_sort_entry *hse; | 
| Namhyung Kim | 7524f63 | 2013-11-08 17:53:42 +0900 | [diff] [blame] | 1818 |  | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1819 | 	perf_hpp__for_each_format(fmt) { | 
 | 1820 | 		if (!perf_hpp__is_sort_entry(fmt)) | 
 | 1821 | 			continue; | 
| Namhyung Kim | 08e7154 | 2013-04-03 21:26:19 +0900 | [diff] [blame] | 1822 |  | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1823 | 		hse = container_of(fmt, struct hpp_sort_entry, hpp); | 
 | 1824 | 		fmt->elide = get_elide(hse->se->se_width_idx, output); | 
| Namhyung Kim | 08e7154 | 2013-04-03 21:26:19 +0900 | [diff] [blame] | 1825 | 	} | 
 | 1826 |  | 
| Namhyung Kim | 7524f63 | 2013-11-08 17:53:42 +0900 | [diff] [blame] | 1827 | 	/* | 
 | 1828 | 	 * It makes no sense to elide all of sort entries. | 
 | 1829 | 	 * Just revert them to show up again. | 
 | 1830 | 	 */ | 
| Namhyung Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1831 | 	perf_hpp__for_each_format(fmt) { | 
 | 1832 | 		if (!perf_hpp__is_sort_entry(fmt)) | 
 | 1833 | 			continue; | 
 | 1834 |  | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1835 | 		if (!fmt->elide) | 
| Namhyung Kim | 7524f63 | 2013-11-08 17:53:42 +0900 | [diff] [blame] | 1836 | 			return; | 
 | 1837 | 	} | 
 | 1838 |  | 
| Namhyung Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1839 | 	perf_hpp__for_each_format(fmt) { | 
 | 1840 | 		if (!perf_hpp__is_sort_entry(fmt)) | 
 | 1841 | 			continue; | 
 | 1842 |  | 
| Jiri Olsa | f299842 | 2014-05-23 17:15:47 +0200 | [diff] [blame] | 1843 | 		fmt->elide = false; | 
| Namhyung Kim | cfaa154 | 2014-05-19 14:19:30 +0900 | [diff] [blame] | 1844 | 	} | 
| Namhyung Kim | 08e7154 | 2013-04-03 21:26:19 +0900 | [diff] [blame] | 1845 | } | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1846 |  | 
 | 1847 | static int output_field_add(char *tok) | 
 | 1848 | { | 
 | 1849 | 	unsigned int i; | 
 | 1850 |  | 
 | 1851 | 	for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) { | 
 | 1852 | 		struct sort_dimension *sd = &common_sort_dimensions[i]; | 
 | 1853 |  | 
 | 1854 | 		if (strncasecmp(tok, sd->name, strlen(tok))) | 
 | 1855 | 			continue; | 
 | 1856 |  | 
 | 1857 | 		return __sort_dimension__add_output(sd); | 
 | 1858 | 	} | 
 | 1859 |  | 
 | 1860 | 	for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { | 
 | 1861 | 		struct hpp_dimension *hd = &hpp_sort_dimensions[i]; | 
 | 1862 |  | 
 | 1863 | 		if (strncasecmp(tok, hd->name, strlen(tok))) | 
 | 1864 | 			continue; | 
 | 1865 |  | 
 | 1866 | 		return __hpp_dimension__add_output(hd); | 
 | 1867 | 	} | 
 | 1868 |  | 
 | 1869 | 	for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { | 
 | 1870 | 		struct sort_dimension *sd = &bstack_sort_dimensions[i]; | 
 | 1871 |  | 
 | 1872 | 		if (strncasecmp(tok, sd->name, strlen(tok))) | 
 | 1873 | 			continue; | 
 | 1874 |  | 
 | 1875 | 		return __sort_dimension__add_output(sd); | 
 | 1876 | 	} | 
 | 1877 |  | 
 | 1878 | 	for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { | 
 | 1879 | 		struct sort_dimension *sd = &memory_sort_dimensions[i]; | 
 | 1880 |  | 
 | 1881 | 		if (strncasecmp(tok, sd->name, strlen(tok))) | 
 | 1882 | 			continue; | 
 | 1883 |  | 
 | 1884 | 		return __sort_dimension__add_output(sd); | 
 | 1885 | 	} | 
 | 1886 |  | 
 | 1887 | 	return -ESRCH; | 
 | 1888 | } | 
 | 1889 |  | 
 | 1890 | static void reset_dimensions(void) | 
 | 1891 | { | 
 | 1892 | 	unsigned int i; | 
 | 1893 |  | 
 | 1894 | 	for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) | 
 | 1895 | 		common_sort_dimensions[i].taken = 0; | 
 | 1896 |  | 
 | 1897 | 	for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) | 
 | 1898 | 		hpp_sort_dimensions[i].taken = 0; | 
 | 1899 |  | 
 | 1900 | 	for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) | 
 | 1901 | 		bstack_sort_dimensions[i].taken = 0; | 
 | 1902 |  | 
 | 1903 | 	for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) | 
 | 1904 | 		memory_sort_dimensions[i].taken = 0; | 
 | 1905 | } | 
 | 1906 |  | 
| Jiri Olsa | 2f3f9bc | 2014-08-22 15:58:38 +0200 | [diff] [blame] | 1907 | bool is_strict_order(const char *order) | 
 | 1908 | { | 
 | 1909 | 	return order && (*order != '+'); | 
 | 1910 | } | 
 | 1911 |  | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1912 | static int __setup_output_field(void) | 
 | 1913 | { | 
| Jiri Olsa | 2f3f9bc | 2014-08-22 15:58:38 +0200 | [diff] [blame] | 1914 | 	char *tmp, *tok, *str, *strp; | 
 | 1915 | 	int ret = -EINVAL; | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1916 |  | 
 | 1917 | 	if (field_order == NULL) | 
 | 1918 | 		return 0; | 
 | 1919 |  | 
 | 1920 | 	reset_dimensions(); | 
 | 1921 |  | 
| Jiri Olsa | 2f3f9bc | 2014-08-22 15:58:38 +0200 | [diff] [blame] | 1922 | 	strp = str = strdup(field_order); | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1923 | 	if (str == NULL) { | 
 | 1924 | 		error("Not enough memory to setup output fields"); | 
 | 1925 | 		return -ENOMEM; | 
 | 1926 | 	} | 
 | 1927 |  | 
| Jiri Olsa | 2f3f9bc | 2014-08-22 15:58:38 +0200 | [diff] [blame] | 1928 | 	if (!is_strict_order(field_order)) | 
 | 1929 | 		strp++; | 
 | 1930 |  | 
 | 1931 | 	if (!strlen(strp)) { | 
 | 1932 | 		error("Invalid --fields key: `+'"); | 
 | 1933 | 		goto out; | 
 | 1934 | 	} | 
 | 1935 |  | 
 | 1936 | 	for (tok = strtok_r(strp, ", ", &tmp); | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1937 | 			tok; tok = strtok_r(NULL, ", ", &tmp)) { | 
 | 1938 | 		ret = output_field_add(tok); | 
 | 1939 | 		if (ret == -EINVAL) { | 
 | 1940 | 			error("Invalid --fields key: `%s'", tok); | 
 | 1941 | 			break; | 
 | 1942 | 		} else if (ret == -ESRCH) { | 
 | 1943 | 			error("Unknown --fields key: `%s'", tok); | 
 | 1944 | 			break; | 
 | 1945 | 		} | 
 | 1946 | 	} | 
 | 1947 |  | 
| Jiri Olsa | 2f3f9bc | 2014-08-22 15:58:38 +0200 | [diff] [blame] | 1948 | out: | 
| Namhyung Kim | a7d945b | 2014-03-04 10:46:34 +0900 | [diff] [blame] | 1949 | 	free(str); | 
 | 1950 | 	return ret; | 
 | 1951 | } | 
 | 1952 |  | 
 | 1953 | int setup_sorting(void) | 
 | 1954 | { | 
 | 1955 | 	int err; | 
 | 1956 |  | 
 | 1957 | 	err = __setup_sorting(); | 
 | 1958 | 	if (err < 0) | 
 | 1959 | 		return err; | 
 | 1960 |  | 
 | 1961 | 	if (parent_pattern != default_parent_pattern) { | 
 | 1962 | 		err = sort_dimension__add("parent"); | 
 | 1963 | 		if (err < 0) | 
 | 1964 | 			return err; | 
 | 1965 | 	} | 
 | 1966 |  | 
 | 1967 | 	reset_dimensions(); | 
 | 1968 |  | 
 | 1969 | 	/* | 
 | 1970 | 	 * perf diff doesn't use default hpp output fields. | 
 | 1971 | 	 */ | 
 | 1972 | 	if (sort__mode != SORT_MODE__DIFF) | 
 | 1973 | 		perf_hpp__init(); | 
 | 1974 |  | 
 | 1975 | 	err = __setup_output_field(); | 
 | 1976 | 	if (err < 0) | 
 | 1977 | 		return err; | 
 | 1978 |  | 
 | 1979 | 	/* copy sort keys to output fields */ | 
 | 1980 | 	perf_hpp__setup_output_field(); | 
 | 1981 | 	/* and then copy output fields to sort keys */ | 
 | 1982 | 	perf_hpp__append_sort_keys(); | 
 | 1983 |  | 
 | 1984 | 	return 0; | 
 | 1985 | } | 
| Namhyung Kim | 1c89fe9 | 2014-05-07 18:42:24 +0900 | [diff] [blame] | 1986 |  | 
 | 1987 | void reset_output_field(void) | 
 | 1988 | { | 
 | 1989 | 	sort__need_collapse = 0; | 
 | 1990 | 	sort__has_parent = 0; | 
 | 1991 | 	sort__has_sym = 0; | 
 | 1992 | 	sort__has_dso = 0; | 
 | 1993 |  | 
| Namhyung Kim | d69b296 | 2014-05-23 10:59:01 +0900 | [diff] [blame] | 1994 | 	field_order = NULL; | 
 | 1995 | 	sort_order = NULL; | 
 | 1996 |  | 
| Namhyung Kim | 1c89fe9 | 2014-05-07 18:42:24 +0900 | [diff] [blame] | 1997 | 	reset_dimensions(); | 
 | 1998 | 	perf_hpp__reset_output_field(); | 
 | 1999 | } |