perf trace: Use evsel->handler.func
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 28 Sep 2012 20:58:36 +0000 (17:58 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 2 Oct 2012 21:36:25 +0000 (18:36 -0300)
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>
tools/perf/builtin-trace.c

index 8f113dab8bf1371bf508e138cb32993007a4cc68..76b1202c03c80e7edb33d3f2de5028295f0043fd 100644 (file)
@@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
        return printed;
 }
 
+typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
+                                 struct perf_sample *sample);
+
+static struct syscall *trace__syscall_info(struct trace *trace,
+                                          struct perf_evsel *evsel,
+                                          struct perf_sample *sample)
+{
+       int id = perf_evsel__intval(evsel, sample, "id");
+
+       if (id < 0) {
+               printf("Invalid syscall %d id, skipping...\n", id);
+               return NULL;
+       }
+
+       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
+           trace__read_syscall_info(trace, id))
+               goto out_cant_read;
+
+       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
+               goto out_cant_read;
+
+       return &trace->syscalls.table[id];
+
+out_cant_read:
+       printf("Problems reading syscall %d information\n", id);
+       return NULL;
+}
+
+static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
+                           struct perf_sample *sample)
+{
+       void *args;
+       struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+
+       if (sc == NULL)
+               return -1;
+
+       args = perf_evsel__rawptr(evsel, sample, "args");
+       if (args == NULL) {
+               printf("Problems reading syscall arguments\n");
+               return -1;
+       }
+
+       printf("%s(", sc->name);
+       syscall__fprintf_args(sc, args, stdout);
+
+       return 0;
+}
+
+static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
+                          struct perf_sample *sample)
+{
+       int ret;
+       struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+
+       if (sc == NULL)
+               return -1;
+
+       ret = perf_evsel__intval(evsel, sample, "ret");
+
+       if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
+               char bf[256];
+               const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
+                          *e = audit_errno_to_name(-ret);
+
+               printf(") = -1 %s %s", e, emsg);
+       } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
+               printf(") = 0 Timeout");
+       else
+               printf(") = %d", ret);
+
+       putchar('\n');
+       return 0;
+}
+
 static int trace__run(struct trace *trace)
 {
        struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
-       struct perf_evsel *evsel, *evsel_enter, *evsel_exit;
+       struct perf_evsel *evsel;
        int err = -1, i, nr_events = 0, before;
 
        if (evlist == NULL) {
@@ -125,21 +200,23 @@ static int trace__run(struct trace *trace)
                goto out;
        }
 
-       evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
-       if (evsel_enter == NULL) {
+       evsel = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
+       if (evsel == NULL) {
                printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
                goto out_delete_evlist;
        }
 
-       perf_evlist__add(evlist, evsel_enter);
+       evsel->handler.func = trace__sys_enter;
+       perf_evlist__add(evlist, evsel);
 
-       evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
-       if (evsel_exit == NULL) {
+       evsel = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
+       if (evsel == NULL) {
                printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
                goto out_delete_evlist;
        }
 
-       perf_evlist__add(evlist, evsel_exit);
+       evsel->handler.func = trace__sys_exit;
+       perf_evlist__add(evlist, evsel);
 
        err = perf_evlist__create_maps(evlist, &trace->opts.target);
        if (err < 0) {
@@ -170,9 +247,8 @@ again:
 
                while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
                        const u32 type = event->header.type;
-                       struct syscall *sc;
+                       tracepoint_handler handler;
                        struct perf_sample sample;
-                       int id;
 
                        ++nr_events;
 
@@ -200,45 +276,11 @@ again:
                                continue;
                        }
 
-                       id = perf_evsel__intval(evsel, &sample, "id");
-                       if (id < 0) {
-                               printf("Invalid syscall %d id, skipping...\n", id);
-                               continue;
-                       }
-
-                       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
-                           trace__read_syscall_info(trace, id))
-                               continue;
-
-                       if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
-                               continue;
-
-                       sc = &trace->syscalls.table[id];
-
                        if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
                                printf("%d ", sample.tid);
 
-                       if (evsel == evsel_enter) {
-                               void *args = perf_evsel__rawptr(evsel, &sample, "args");
-
-                               printf("%s(", sc->name);
-                               syscall__fprintf_args(sc, args, stdout);
-                       } else if (evsel == evsel_exit) {
-                               int ret = perf_evsel__intval(evsel, &sample, "ret");
-
-                               if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
-                                       char bf[256];
-                                       const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
-                                                  *e = audit_errno_to_name(-ret);
-
-                                       printf(") = -1 %s %s", e, emsg);
-                               } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
-                                       printf(") = 0 Timeout");
-                               else
-                                       printf(") = %d", ret);
-
-                               putchar('\n');
-                       }
+                       handler = evsel->handler.func;
+                       handler(trace, evsel, &sample);
                }
        }