aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-09-28 16:58:36 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-10-02 17:36:25 -0400
commitba3d7deeef7fafdab7814e298fa2db0fc63bb5d0 (patch)
tree5dd5c2d31387fda6dacf69f4ef29aefa4a07d572 /tools/perf/builtin-trace.c
parentd6e66832a710c0e6d1376e8d39ee108636a177e7 (diff)
perf trace: Use evsel->handler.func
I.e. we don't need to resolve the evsel via the id and then check if it is this or that event, just stash the right handler at evsel creation time, then use evsel->handler.func() straight away. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-bpz3axzr4f2cjppf4egm28wf@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r--tools/perf/builtin-trace.c132
1 files changed, 87 insertions, 45 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8f113dab8bf1..76b1202c03c8 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
114 return printed; 114 return printed;
115} 115}
116 116
117typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
118 struct perf_sample *sample);
119
120static struct syscall *trace__syscall_info(struct trace *trace,
121 struct perf_evsel *evsel,
122 struct perf_sample *sample)
123{
124 int id = perf_evsel__intval(evsel, sample, "id");
125
126 if (id < 0) {
127 printf("Invalid syscall %d id, skipping...\n", id);
128 return NULL;
129 }
130
131 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
132 trace__read_syscall_info(trace, id))
133 goto out_cant_read;
134
135 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
136 goto out_cant_read;
137
138 return &trace->syscalls.table[id];
139
140out_cant_read:
141 printf("Problems reading syscall %d information\n", id);
142 return NULL;
143}
144
145static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
146 struct perf_sample *sample)
147{
148 void *args;
149 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
150
151 if (sc == NULL)
152 return -1;
153
154 args = perf_evsel__rawptr(evsel, sample, "args");
155 if (args == NULL) {
156 printf("Problems reading syscall arguments\n");
157 return -1;
158 }
159
160 printf("%s(", sc->name);
161 syscall__fprintf_args(sc, args, stdout);
162
163 return 0;
164}
165
166static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
167 struct perf_sample *sample)
168{
169 int ret;
170 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
171
172 if (sc == NULL)
173 return -1;
174
175 ret = perf_evsel__intval(evsel, sample, "ret");
176
177 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
178 char bf[256];
179 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
180 *e = audit_errno_to_name(-ret);
181
182 printf(") = -1 %s %s", e, emsg);
183 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
184 printf(") = 0 Timeout");
185 else
186 printf(") = %d", ret);
187
188 putchar('\n');
189 return 0;
190}
191
117static int trace__run(struct trace *trace) 192static int trace__run(struct trace *trace)
118{ 193{
119 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); 194 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
120 struct perf_evsel *evsel, *evsel_enter, *evsel_exit; 195 struct perf_evsel *evsel;
121 int err = -1, i, nr_events = 0, before; 196 int err = -1, i, nr_events = 0, before;
122 197
123 if (evlist == NULL) { 198 if (evlist == NULL) {
@@ -125,21 +200,23 @@ static int trace__run(struct trace *trace)
125 goto out; 200 goto out;
126 } 201 }
127 202
128 evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0); 203 evsel = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
129 if (evsel_enter == NULL) { 204 if (evsel == NULL) {
130 printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n"); 205 printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
131 goto out_delete_evlist; 206 goto out_delete_evlist;
132 } 207 }
133 208
134 perf_evlist__add(evlist, evsel_enter); 209 evsel->handler.func = trace__sys_enter;
210 perf_evlist__add(evlist, evsel);
135 211
136 evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1); 212 evsel = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
137 if (evsel_exit == NULL) { 213 if (evsel == NULL) {
138 printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n"); 214 printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
139 goto out_delete_evlist; 215 goto out_delete_evlist;
140 } 216 }
141 217
142 perf_evlist__add(evlist, evsel_exit); 218 evsel->handler.func = trace__sys_exit;
219 perf_evlist__add(evlist, evsel);
143 220
144 err = perf_evlist__create_maps(evlist, &trace->opts.target); 221 err = perf_evlist__create_maps(evlist, &trace->opts.target);
145 if (err < 0) { 222 if (err < 0) {
@@ -170,9 +247,8 @@ again:
170 247
171 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 248 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
172 const u32 type = event->header.type; 249 const u32 type = event->header.type;
173 struct syscall *sc; 250 tracepoint_handler handler;
174 struct perf_sample sample; 251 struct perf_sample sample;
175 int id;
176 252
177 ++nr_events; 253 ++nr_events;
178 254
@@ -200,45 +276,11 @@ again:
200 continue; 276 continue;
201 } 277 }
202 278
203 id = perf_evsel__intval(evsel, &sample, "id");
204 if (id < 0) {
205 printf("Invalid syscall %d id, skipping...\n", id);
206 continue;
207 }
208
209 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
210 trace__read_syscall_info(trace, id))
211 continue;
212
213 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
214 continue;
215
216 sc = &trace->syscalls.table[id];
217
218 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) 279 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
219 printf("%d ", sample.tid); 280 printf("%d ", sample.tid);
220 281
221 if (evsel == evsel_enter) { 282 handler = evsel->handler.func;
222 void *args = perf_evsel__rawptr(evsel, &sample, "args"); 283 handler(trace, evsel, &sample);
223
224 printf("%s(", sc->name);
225 syscall__fprintf_args(sc, args, stdout);
226 } else if (evsel == evsel_exit) {
227 int ret = perf_evsel__intval(evsel, &sample, "ret");
228
229 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
230 char bf[256];
231 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
232 *e = audit_errno_to_name(-ret);
233
234 printf(") = -1 %s %s", e, emsg);
235 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
236 printf(") = 0 Timeout");
237 else
238 printf(") = %d", ret);
239
240 putchar('\n');
241 }
242 } 284 }
243 } 285 }
244 286