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

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

perf evsel: Provide a new constructor for tracepoints

The existing constructor receives a perf_event_attr filled with the
event type and the config.

To reduce the boilerplate for tracepoints, provide a new constructor,
perf_evsel__newtp() that receives the tracepoint name and will open
the debugfs file, call into libtraceevent new pevent_parse_format file
to fill its ->tp_format member, so that users can then just call
perf_evsel__field() to access its fields.

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>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/n/tip-6du8dl1hz0y5l4cybodye7hn@git.kernel.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 2b29175d
Loading
Loading
Loading
Loading
+82 −6
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <byteswap.h>
#include <linux/bitops.h>
#include "asm/bug.h"
#include "debugfs.h"
#include "event-parse.h"
#include "evsel.h"
#include "evlist.h"
@@ -69,6 +70,72 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
	return evsel;
}

static struct event_format *event_format__new(const char *sys, const char *name)
{
	int fd, n;
	char *filename;
	void *bf = NULL, *nbf;
	size_t size = 0, alloc_size = 0;
	struct event_format *format = NULL;

	if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0)
		goto out;

	fd = open(filename, O_RDONLY);
	if (fd < 0)
		goto out_free_filename;

	do {
		if (size == alloc_size) {
			alloc_size += BUFSIZ;
			nbf = realloc(bf, alloc_size);
			if (nbf == NULL)
				goto out_free_bf;
			bf = nbf;
		}

		n = read(fd, bf + size, BUFSIZ);
		if (n < 0)
			goto out_free_bf;
		size += n;
	} while (n > 0);

	pevent_parse_format(&format, bf, size, sys);

out_free_bf:
	free(bf);
	close(fd);
out_free_filename:
	free(filename);
out:
	return format;
}

struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx)
{
	struct perf_evsel *evsel = zalloc(sizeof(*evsel));

	if (evsel != NULL) {
		struct perf_event_attr attr = {
			.type = PERF_TYPE_TRACEPOINT,
		};

		evsel->tp_format = event_format__new(sys, name);
		if (evsel->tp_format == NULL)
			goto out_free;

		attr.config = evsel->tp_format->id;
		perf_evsel__init(evsel, &attr, idx);
		evsel->name = evsel->tp_format->name;
	}

	return evsel;

out_free:
	free(evsel);
	return NULL;
}

const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
	"cycles",
	"instructions",
@@ -495,6 +562,10 @@ void perf_evsel__delete(struct perf_evsel *evsel)
	perf_evsel__exit(evsel);
	close_cgroup(evsel->cgrp);
	free(evsel->group_name);
	if (evsel->tp_format && evsel->name == evsel->tp_format->name) {
		evsel->name = NULL;
		pevent_free_format(evsel->tp_format);
	}
	free(evsel->name);
	free(evsel);
}
@@ -1002,10 +1073,15 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
	return 0;
}

struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
{
	return pevent_find_field(evsel->tp_format, name);
}

char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,
			 const char *name)
{
	struct format_field *field = pevent_find_field(evsel->tp_format, name);
	struct format_field *field = perf_evsel__field(evsel, name);
	int offset;

	if (!field)
@@ -1024,7 +1100,7 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
		       const char *name)
{
	struct format_field *field = pevent_find_field(evsel->tp_format, name);
	struct format_field *field = perf_evsel__field(evsel, name);
	u64 val;

	if (!field)
+5 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ struct perf_evlist;
struct perf_record_opts;

struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx);
void perf_evsel__init(struct perf_evsel *evsel,
		      struct perf_event_attr *attr, int idx);
void perf_evsel__exit(struct perf_evsel *evsel);
@@ -128,6 +129,10 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
		       const char *name);

struct format_field;

struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);

#define perf_evsel__match(evsel, t, c)		\
	(evsel->attr.type == PERF_TYPE_##t &&	\
	 evsel->attr.config == PERF_COUNT_##c)