diff options
author | John Kacur <jkacur@redhat.com> | 2009-09-24 12:02:49 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-24 15:27:52 -0400 |
commit | dd68ada2d417e57b848822a1407b5317a54136c5 (patch) | |
tree | 8d7cc54e3bcf063038532d88ac1f94a54b6650a5 /tools/perf/builtin-annotate.c | |
parent | 8b40f521cf1c9750eab0c04da9075e7484675e9c (diff) |
perf tools: Create util/sort.and use it
Create util/sort.[ch] and move common functionality for
builtin-report.c and builtin-annotate.c there, and make use of it.
Signed-off-by: John Kacur <jkacur@redhat.com>
LKML-Reference: <alpine.LFD.2.00.0909241758390.11383@localhost.localdomain>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r-- | tools/perf/builtin-annotate.c | 211 |
1 files changed, 7 insertions, 204 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index a33087328bd4..059c565b31ea 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -22,12 +22,10 @@ | |||
22 | #include "util/parse-options.h" | 22 | #include "util/parse-options.h" |
23 | #include "util/parse-events.h" | 23 | #include "util/parse-events.h" |
24 | #include "util/thread.h" | 24 | #include "util/thread.h" |
25 | #include "util/sort.h" | ||
25 | 26 | ||
26 | static char const *input_name = "perf.data"; | 27 | static char const *input_name = "perf.data"; |
27 | 28 | ||
28 | static char default_sort_order[] = "comm,symbol"; | ||
29 | static char *sort_order = default_sort_order; | ||
30 | |||
31 | static int force; | 29 | static int force; |
32 | static int input; | 30 | static int input; |
33 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; | 31 | static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; |
@@ -55,207 +53,6 @@ struct sym_ext { | |||
55 | 53 | ||
56 | static struct rb_root hist; | 54 | static struct rb_root hist; |
57 | 55 | ||
58 | struct hist_entry { | ||
59 | struct rb_node rb_node; | ||
60 | |||
61 | struct thread *thread; | ||
62 | struct map *map; | ||
63 | struct dso *dso; | ||
64 | struct symbol *sym; | ||
65 | u64 ip; | ||
66 | char level; | ||
67 | |||
68 | uint32_t count; | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * configurable sorting bits | ||
73 | */ | ||
74 | |||
75 | struct sort_entry { | ||
76 | struct list_head list; | ||
77 | |||
78 | const char *header; | ||
79 | |||
80 | int64_t (*cmp)(struct hist_entry *, struct hist_entry *); | ||
81 | int64_t (*collapse)(struct hist_entry *, struct hist_entry *); | ||
82 | size_t (*print)(FILE *fp, struct hist_entry *); | ||
83 | }; | ||
84 | |||
85 | static int64_t cmp_null(void *l, void *r) | ||
86 | { | ||
87 | if (!l && !r) | ||
88 | return 0; | ||
89 | else if (!l) | ||
90 | return -1; | ||
91 | else | ||
92 | return 1; | ||
93 | } | ||
94 | |||
95 | /* --sort pid */ | ||
96 | |||
97 | static int64_t | ||
98 | sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) | ||
99 | { | ||
100 | return right->thread->pid - left->thread->pid; | ||
101 | } | ||
102 | |||
103 | static size_t | ||
104 | sort__thread_print(FILE *fp, struct hist_entry *self) | ||
105 | { | ||
106 | return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); | ||
107 | } | ||
108 | |||
109 | static struct sort_entry sort_thread = { | ||
110 | .header = " Command: Pid", | ||
111 | .cmp = sort__thread_cmp, | ||
112 | .print = sort__thread_print, | ||
113 | }; | ||
114 | |||
115 | /* --sort comm */ | ||
116 | |||
117 | static int64_t | ||
118 | sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) | ||
119 | { | ||
120 | return right->thread->pid - left->thread->pid; | ||
121 | } | ||
122 | |||
123 | static int64_t | ||
124 | sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) | ||
125 | { | ||
126 | char *comm_l = left->thread->comm; | ||
127 | char *comm_r = right->thread->comm; | ||
128 | |||
129 | if (!comm_l || !comm_r) | ||
130 | return cmp_null(comm_l, comm_r); | ||
131 | |||
132 | return strcmp(comm_l, comm_r); | ||
133 | } | ||
134 | |||
135 | static size_t | ||
136 | sort__comm_print(FILE *fp, struct hist_entry *self) | ||
137 | { | ||
138 | return fprintf(fp, "%16s", self->thread->comm); | ||
139 | } | ||
140 | |||
141 | static struct sort_entry sort_comm = { | ||
142 | .header = " Command", | ||
143 | .cmp = sort__comm_cmp, | ||
144 | .collapse = sort__comm_collapse, | ||
145 | .print = sort__comm_print, | ||
146 | }; | ||
147 | |||
148 | /* --sort dso */ | ||
149 | |||
150 | static int64_t | ||
151 | sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) | ||
152 | { | ||
153 | struct dso *dso_l = left->dso; | ||
154 | struct dso *dso_r = right->dso; | ||
155 | |||
156 | if (!dso_l || !dso_r) | ||
157 | return cmp_null(dso_l, dso_r); | ||
158 | |||
159 | return strcmp(dso_l->name, dso_r->name); | ||
160 | } | ||
161 | |||
162 | static size_t | ||
163 | sort__dso_print(FILE *fp, struct hist_entry *self) | ||
164 | { | ||
165 | if (self->dso) | ||
166 | return fprintf(fp, "%-25s", self->dso->name); | ||
167 | |||
168 | return fprintf(fp, "%016llx ", (u64)self->ip); | ||
169 | } | ||
170 | |||
171 | static struct sort_entry sort_dso = { | ||
172 | .header = "Shared Object ", | ||
173 | .cmp = sort__dso_cmp, | ||
174 | .print = sort__dso_print, | ||
175 | }; | ||
176 | |||
177 | /* --sort symbol */ | ||
178 | |||
179 | static int64_t | ||
180 | sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) | ||
181 | { | ||
182 | u64 ip_l, ip_r; | ||
183 | |||
184 | if (left->sym == right->sym) | ||
185 | return 0; | ||
186 | |||
187 | ip_l = left->sym ? left->sym->start : left->ip; | ||
188 | ip_r = right->sym ? right->sym->start : right->ip; | ||
189 | |||
190 | return (int64_t)(ip_r - ip_l); | ||
191 | } | ||
192 | |||
193 | static size_t | ||
194 | sort__sym_print(FILE *fp, struct hist_entry *self) | ||
195 | { | ||
196 | size_t ret = 0; | ||
197 | |||
198 | if (verbose) | ||
199 | ret += fprintf(fp, "%#018llx ", (u64)self->ip); | ||
200 | |||
201 | if (self->sym) { | ||
202 | ret += fprintf(fp, "[%c] %s", | ||
203 | self->dso == kernel_dso ? 'k' : '.', self->sym->name); | ||
204 | } else { | ||
205 | ret += fprintf(fp, "%#016llx", (u64)self->ip); | ||
206 | } | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static struct sort_entry sort_sym = { | ||
212 | .header = "Symbol", | ||
213 | .cmp = sort__sym_cmp, | ||
214 | .print = sort__sym_print, | ||
215 | }; | ||
216 | |||
217 | static int sort__need_collapse = 0; | ||
218 | |||
219 | struct sort_dimension { | ||
220 | const char *name; | ||
221 | struct sort_entry *entry; | ||
222 | int taken; | ||
223 | }; | ||
224 | |||
225 | static struct sort_dimension sort_dimensions[] = { | ||
226 | { .name = "pid", .entry = &sort_thread, }, | ||
227 | { .name = "comm", .entry = &sort_comm, }, | ||
228 | { .name = "dso", .entry = &sort_dso, }, | ||
229 | { .name = "symbol", .entry = &sort_sym, }, | ||
230 | }; | ||
231 | |||
232 | static LIST_HEAD(hist_entry__sort_list); | ||
233 | |||
234 | static int sort_dimension__add(char *tok) | ||
235 | { | ||
236 | unsigned int i; | ||
237 | |||
238 | for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { | ||
239 | struct sort_dimension *sd = &sort_dimensions[i]; | ||
240 | |||
241 | if (sd->taken) | ||
242 | continue; | ||
243 | |||
244 | if (strncasecmp(tok, sd->name, strlen(tok))) | ||
245 | continue; | ||
246 | |||
247 | if (sd->entry->collapse) | ||
248 | sort__need_collapse = 1; | ||
249 | |||
250 | list_add_tail(&sd->entry->list, &hist_entry__sort_list); | ||
251 | sd->taken = 1; | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | return -ESRCH; | ||
257 | } | ||
258 | |||
259 | static int64_t | 56 | static int64_t |
260 | hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) | 57 | hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) |
261 | { | 58 | { |
@@ -1137,5 +934,11 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) | |||
1137 | 934 | ||
1138 | setup_pager(); | 935 | setup_pager(); |
1139 | 936 | ||
937 | if (field_sep && *field_sep == '.') { | ||
938 | fputs("'.' is the only non valid --field-separator argument\n", | ||
939 | stderr); | ||
940 | exit(129); | ||
941 | } | ||
942 | |||
1140 | return __cmd_annotate(); | 943 | return __cmd_annotate(); |
1141 | } | 944 | } |