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

Commit 2c46dbb5 authored by Tom Zanussi's avatar Tom Zanussi Committed by Ingo Molnar
Browse files

perf: Convert perf header attrs into attr events



Bypasses the attr perf header code and replaces it with a
synthesized event and processing function that accomplishes the
same thing, used when reading/writing perf data to/from a pipe.

Making the attrs into events allows them to be streamed over a
pipe along with the rest of the header data (in later patches).
It also paves the way to allowing events to be added and removed
from perf sessions dynamically.

Signed-off-by: default avatarTom Zanussi <tzanussi@gmail.com>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: fweisbec@gmail.com
Cc: rostedt@goodmis.org
Cc: k-keiichi@bx.jp.nec.com
Cc: acme@ghostprotocols.net
LKML-Reference: <1270184365-8281-6-git-send-email-tzanussi@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent c239da3b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -584,6 +584,16 @@ static int __cmd_record(int argc, const char **argv)

	post_processing_offset = lseek(output, 0, SEEK_CUR);

	if (pipe_output) {
		err = event__synthesize_attrs(&session->header,
					      process_synthesized_event,
					      session);
		if (err < 0) {
			pr_err("Couldn't synthesize attrs.\n");
			return err;
		}
	}

	err = event__synthesize_kernel_mmap(process_synthesized_event,
					    session, "_text");
	if (err < 0)
+1 −0
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ static struct perf_event_ops event_ops = {
	.fork	= event__process_task,
	.lost	= event__process_lost,
	.read	= process_read_event,
	.attr	= event__process_attr,
};

extern volatile int session_done;
+1 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
static struct perf_event_ops event_ops = {
	.sample	= process_sample_event,
	.comm	= event__process_comm,
	.attr	= event__process_attr,
};

extern volatile int session_done;
+9 −1
Original line number Diff line number Diff line
@@ -84,7 +84,14 @@ struct build_id_event {
};

enum perf_header_event_type { /* above any possible kernel type */
	PERF_RECORD_HEADER_MAX			= 64,
	PERF_RECORD_HEADER_ATTR			= 64,
	PERF_RECORD_HEADER_MAX
};

struct attr_event {
	struct perf_event_header header;
	struct perf_event_attr attr;
	u64 id[];
};

typedef union event_union {
@@ -96,6 +103,7 @@ typedef union event_union {
	struct lost_event		lost;
	struct read_event		read;
	struct sample_event		sample;
	struct attr_event		attr;
} event_t;

struct events_stats {
+79 −0
Original line number Diff line number Diff line
@@ -807,3 +807,82 @@ perf_header__find_attr(u64 id, struct perf_header *header)

	return NULL;
}

int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
			   event__handler_t process,
			   struct perf_session *session)
{
	event_t *ev;
	size_t size;
	int err;

	size = sizeof(struct perf_event_attr);
	size = ALIGN(size, sizeof(u64));
	size += sizeof(struct perf_event_header);
	size += ids * sizeof(u64);

	ev = malloc(size);

	ev->attr.attr = *attr;
	memcpy(ev->attr.id, id, ids * sizeof(u64));

	ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
	ev->attr.header.size = size;

	err = process(ev, session);

	free(ev);

	return err;
}

int event__synthesize_attrs(struct perf_header *self,
			    event__handler_t process,
			    struct perf_session *session)
{
	struct perf_header_attr	*attr;
	int i, err = 0;

	for (i = 0; i < self->attrs; i++) {
		attr = self->attr[i];

		err = event__synthesize_attr(&attr->attr, attr->ids, attr->id,
					     process, session);
		if (err) {
			pr_debug("failed to create perf header attribute\n");
			return err;
		}
	}

	return err;
}

int event__process_attr(event_t *self, struct perf_session *session)
{
	struct perf_header_attr *attr;
	unsigned int i, ids, n_ids;

	attr = perf_header_attr__new(&self->attr.attr);
	if (attr == NULL)
		return -ENOMEM;

	ids = self->header.size;
	ids -= (void *)&self->attr.id - (void *)self;
	n_ids = ids / sizeof(u64);

	for (i = 0; i < n_ids; i++) {
		if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) {
			perf_header_attr__delete(attr);
			return -ENOMEM;
		}
	}

	if (perf_header__add_attr(&session->header, attr) < 0) {
		perf_header_attr__delete(attr);
		return -ENOMEM;
	}

	perf_session__update_sample_type(session);

	return 0;
}
Loading