Commit 2b00bb62 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo
Browse files

perf trace: Introduce 'struct evsel__trace' for evsel->priv needs

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 8b913df5
Loading
Loading
Loading
Loading
+48 −6
Original line number Diff line number Diff line
@@ -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,