Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d6e66832
Loading
Loading
Loading
Loading
+87 −45
Original line number Original line Diff line number Diff line
@@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
	return printed;
	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)
static int trace__run(struct trace *trace)
{
{
	struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
	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;
	int err = -1, i, nr_events = 0, before;


	if (evlist == NULL) {
	if (evlist == NULL) {
@@ -125,21 +200,23 @@ static int trace__run(struct trace *trace)
		goto out;
		goto out;
	}
	}


	evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
	evsel = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
	if (evsel_enter == NULL) {
	if (evsel == NULL) {
		printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
		printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
		goto out_delete_evlist;
		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);
	evsel = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
	if (evsel_exit == NULL) {
	if (evsel == NULL) {
		printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
		printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
		goto out_delete_evlist;
		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);
	err = perf_evlist__create_maps(evlist, &trace->opts.target);
	if (err < 0) {
	if (err < 0) {
@@ -170,9 +247,8 @@ static int trace__run(struct trace *trace)


		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
			const u32 type = event->header.type;
			const u32 type = event->header.type;
			struct syscall *sc;
			tracepoint_handler handler;
			struct perf_sample sample;
			struct perf_sample sample;
			int id;


			++nr_events;
			++nr_events;


@@ -200,45 +276,11 @@ static int trace__run(struct trace *trace)
				continue;
				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)
			if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
				printf("%d ", sample.tid);
				printf("%d ", sample.tid);


			if (evsel == evsel_enter) {
			handler = evsel->handler.func;
				void *args = perf_evsel__rawptr(evsel, &sample, "args");
			handler(trace, evsel, &sample);

				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');
			}
		}
		}
	}
	}