perf trace: Introduce 'struct evsel__trace' for evsel->priv needs
authorArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 17 Oct 2019 19:37:18 +0000 (16:37 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 17 Oct 2019 20:27:43 +0000 (17:27 -0300)
For syscalls we need to cache the 'syscall_id' and 'ret' field offsets
but as well have a pointer to the syscall_fmt_arg array for the fields,
so that we can expand strings in filter expressions, so introduce
a 'struct evsel_trace' to have in evsel->priv that allows for that.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Luis Cláudio Gonçalves <lclaudio@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lkml.kernel.org/n/tip-hx8ukasuws5sz6rsar73cocv@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-trace.c

index 1d2ed28..5792278 100644 (file)
@@ -285,21 +285,47 @@ struct syscall_tp {
        };
 };
 
+/*
+ * The evsel->priv as used by 'perf trace'
+ * sc: for raw_syscalls:sys_{enter,exit} and syscalls:sys_{enter,exit}_SYSCALLNAME
+ * fmt: for all the other tracepoints
+ */
+struct evsel_trace {
+       struct syscall_tp       sc;
+       struct syscall_arg_fmt  *fmt;
+};
+
+static struct evsel_trace *evsel_trace__new(void)
+{
+       return zalloc(sizeof(struct evsel_trace));
+}
+
+static void evsel_trace__delete(struct evsel_trace *et)
+{
+       if (et == NULL)
+               return;
+
+       zfree(&et->fmt);
+       free(et);
+}
+
 /*
  * Used with raw_syscalls:sys_{enter,exit} and with the
  * syscalls:sys_{enter,exit}_SYSCALL tracepoints
  */
 static inline struct syscall_tp *__evsel__syscall_tp(struct evsel *evsel)
 {
-       struct syscall_tp *sc = evsel->priv;
+       struct evsel_trace *et = evsel->priv;
 
-       return sc;
+       return &et->sc;
 }
 
 static struct syscall_tp *evsel__syscall_tp(struct evsel *evsel)
 {
        if (evsel->priv == NULL) {
-               evsel->priv = zalloc(sizeof(struct syscall_tp));
+               evsel->priv = evsel_trace__new();
+               if (evsel->priv == NULL)
+                       return NULL;
        }
 
        return __evsel__syscall_tp(evsel);
@@ -310,18 +336,34 @@ static struct syscall_tp *evsel__syscall_tp(struct evsel *evsel)
  */
 static inline struct syscall_arg_fmt *__evsel__syscall_arg_fmt(struct evsel *evsel)
 {
-       struct syscall_arg_fmt *fmt = evsel->priv;
+       struct evsel_trace *et = evsel->priv;
 
-       return fmt;
+       return et->fmt;
 }
 
 static struct syscall_arg_fmt *evsel__syscall_arg_fmt(struct evsel *evsel)
 {
+       struct evsel_trace *et = evsel->priv;
+
        if (evsel->priv == NULL) {
-               evsel->priv = calloc(evsel->tp_format->format.nr_fields, sizeof(struct syscall_arg_fmt));
+               et = evsel->priv = evsel_trace__new();
+
+               if (et == NULL)
+                       return NULL;
+       }
+
+       if (et->fmt == NULL) {
+               et->fmt = calloc(evsel->tp_format->format.nr_fields, sizeof(struct syscall_arg_fmt));
+               if (et->fmt == NULL)
+                       goto out_delete;
        }
 
        return __evsel__syscall_arg_fmt(evsel);
+
+out_delete:
+       evsel_trace__delete(evsel->priv);
+       evsel->priv = NULL;
+       return NULL;
 }
 
 static int perf_evsel__init_tp_uint_field(struct evsel *evsel,