4 char default_parent_pattern
[] = "^sys_|^do_page_fault";
5 char *parent_pattern
= default_parent_pattern
;
6 char default_sort_order
[] = "comm,dso,symbol";
7 char *sort_order
= default_sort_order
;
8 int sort__need_collapse
= 0;
9 int sort__has_parent
= 0;
11 enum sort_type sort__first_dimension
;
13 unsigned int dsos__col_width
;
14 unsigned int comms__col_width
;
15 unsigned int threads__col_width
;
16 static unsigned int parent_symbol__col_width
;
19 LIST_HEAD(hist_entry__sort_list
);
21 struct sort_entry sort_thread
= {
22 .header
= "Command: Pid",
23 .cmp
= sort__thread_cmp
,
24 .print
= sort__thread_print
,
25 .width
= &threads__col_width
,
28 struct sort_entry sort_comm
= {
30 .cmp
= sort__comm_cmp
,
31 .collapse
= sort__comm_collapse
,
32 .print
= sort__comm_print
,
33 .width
= &comms__col_width
,
36 struct sort_entry sort_dso
= {
37 .header
= "Shared Object",
39 .print
= sort__dso_print
,
40 .width
= &dsos__col_width
,
43 struct sort_entry sort_sym
= {
46 .print
= sort__sym_print
,
49 struct sort_entry sort_parent
= {
50 .header
= "Parent symbol",
51 .cmp
= sort__parent_cmp
,
52 .print
= sort__parent_print
,
53 .width
= &parent_symbol__col_width
,
56 struct sort_dimension
{
58 struct sort_entry
*entry
;
62 static struct sort_dimension sort_dimensions
[] = {
63 { .name
= "pid", .entry
= &sort_thread
, },
64 { .name
= "comm", .entry
= &sort_comm
, },
65 { .name
= "dso", .entry
= &sort_dso
, },
66 { .name
= "symbol", .entry
= &sort_sym
, },
67 { .name
= "parent", .entry
= &sort_parent
, },
70 int64_t cmp_null(void *l
, void *r
)
83 sort__thread_cmp(struct hist_entry
*left
, struct hist_entry
*right
)
85 return right
->thread
->pid
- left
->thread
->pid
;
88 int repsep_fprintf(FILE *fp
, const char *fmt
, ...)
95 n
= vfprintf(fp
, fmt
, ap
);
98 n
= vasprintf(&bf
, fmt
, ap
);
103 sep
= strchr(sep
, *field_sep
);
117 sort__thread_print(FILE *fp
, struct hist_entry
*self
, unsigned int width
)
119 return repsep_fprintf(fp
, "%*s:%5d", width
- 6,
120 self
->thread
->comm
?: "", self
->thread
->pid
);
124 sort__comm_print(FILE *fp
, struct hist_entry
*self
, unsigned int width
)
126 return repsep_fprintf(fp
, "%*s", width
, self
->thread
->comm
);
132 sort__dso_cmp(struct hist_entry
*left
, struct hist_entry
*right
)
134 struct dso
*dso_l
= left
->map
? left
->map
->dso
: NULL
;
135 struct dso
*dso_r
= right
->map
? right
->map
->dso
: NULL
;
136 const char *dso_name_l
, *dso_name_r
;
138 if (!dso_l
|| !dso_r
)
139 return cmp_null(dso_l
, dso_r
);
142 dso_name_l
= dso_l
->long_name
;
143 dso_name_r
= dso_r
->long_name
;
145 dso_name_l
= dso_l
->short_name
;
146 dso_name_r
= dso_r
->short_name
;
149 return strcmp(dso_name_l
, dso_name_r
);
153 sort__dso_print(FILE *fp
, struct hist_entry
*self
, unsigned int width
)
155 if (self
->map
&& self
->map
->dso
) {
156 const char *dso_name
= !verbose
? self
->map
->dso
->short_name
:
157 self
->map
->dso
->long_name
;
158 return repsep_fprintf(fp
, "%-*s", width
, dso_name
);
161 return repsep_fprintf(fp
, "%*llx", width
, (u64
)self
->ip
);
167 sort__sym_cmp(struct hist_entry
*left
, struct hist_entry
*right
)
171 if (left
->sym
== right
->sym
)
174 ip_l
= left
->sym
? left
->sym
->start
: left
->ip
;
175 ip_r
= right
->sym
? right
->sym
->start
: right
->ip
;
177 return (int64_t)(ip_r
- ip_l
);
182 sort__sym_print(FILE *fp
, struct hist_entry
*self
, unsigned int width __used
)
187 char o
= self
->map
? dso__symtab_origin(self
->map
->dso
) : '!';
188 ret
+= repsep_fprintf(fp
, "%#018llx %c ", (u64
)self
->ip
, o
);
191 ret
+= repsep_fprintf(fp
, "[%c] ", self
->level
);
193 ret
+= repsep_fprintf(fp
, "%s", self
->sym
->name
);
195 ret
+= repsep_fprintf(fp
, "%#016llx", (u64
)self
->ip
);
203 sort__comm_cmp(struct hist_entry
*left
, struct hist_entry
*right
)
205 return right
->thread
->pid
- left
->thread
->pid
;
209 sort__comm_collapse(struct hist_entry
*left
, struct hist_entry
*right
)
211 char *comm_l
= left
->thread
->comm
;
212 char *comm_r
= right
->thread
->comm
;
214 if (!comm_l
|| !comm_r
)
215 return cmp_null(comm_l
, comm_r
);
217 return strcmp(comm_l
, comm_r
);
223 sort__parent_cmp(struct hist_entry
*left
, struct hist_entry
*right
)
225 struct symbol
*sym_l
= left
->parent
;
226 struct symbol
*sym_r
= right
->parent
;
228 if (!sym_l
|| !sym_r
)
229 return cmp_null(sym_l
, sym_r
);
231 return strcmp(sym_l
->name
, sym_r
->name
);
235 sort__parent_print(FILE *fp
, struct hist_entry
*self
, unsigned int width
)
237 return repsep_fprintf(fp
, "%-*s", width
,
238 self
->parent
? self
->parent
->name
: "[other]");
241 int sort_dimension__add(const char *tok
)
245 for (i
= 0; i
< ARRAY_SIZE(sort_dimensions
); i
++) {
246 struct sort_dimension
*sd
= &sort_dimensions
[i
];
251 if (strncasecmp(tok
, sd
->name
, strlen(tok
)))
254 if (sd
->entry
->collapse
)
255 sort__need_collapse
= 1;
257 if (sd
->entry
== &sort_parent
) {
258 int ret
= regcomp(&parent_regex
, parent_pattern
, REG_EXTENDED
);
262 regerror(ret
, &parent_regex
, err
, sizeof(err
));
263 fprintf(stderr
, "Invalid regex: %s\n%s",
264 parent_pattern
, err
);
267 sort__has_parent
= 1;
270 if (list_empty(&hist_entry__sort_list
)) {
271 if (!strcmp(sd
->name
, "pid"))
272 sort__first_dimension
= SORT_PID
;
273 else if (!strcmp(sd
->name
, "comm"))
274 sort__first_dimension
= SORT_COMM
;
275 else if (!strcmp(sd
->name
, "dso"))
276 sort__first_dimension
= SORT_DSO
;
277 else if (!strcmp(sd
->name
, "symbol"))
278 sort__first_dimension
= SORT_SYM
;
279 else if (!strcmp(sd
->name
, "parent"))
280 sort__first_dimension
= SORT_PARENT
;
283 list_add_tail(&sd
->entry
->list
, &hist_entry__sort_list
);
292 void setup_sorting(const char * const usagestr
[], const struct option
*opts
)
294 char *tmp
, *tok
, *str
= strdup(sort_order
);
296 for (tok
= strtok_r(str
, ", ", &tmp
);
297 tok
; tok
= strtok_r(NULL
, ", ", &tmp
)) {
298 if (sort_dimension__add(tok
) < 0) {
299 error("Unknown --sort key: `%s'", tok
);
300 usage_with_options(usagestr
, opts
);
307 void sort_entry__setup_elide(struct sort_entry
*self
, struct strlist
*list
,
308 const char *list_name
, FILE *fp
)
310 if (list
&& strlist__nr_entries(list
) == 1) {
312 fprintf(fp
, "# %s: %s\n", list_name
,
313 strlist__entry(list
, 0)->s
);