Commit ac2f445f authored by Adrian Hunter's avatar Adrian Hunter Committed by Arnaldo Carvalho de Melo
Browse files

perf auxtrace: Add support for queuing AUX area samples



Add functions to queue AUX area samples in advance
(auxtrace_queue_data()) or individually (auxtrace_queues__add_sample())
or find out what queue a sample belongs on
(auxtrace_queues__sample_queue()).

auxtrace_queue_data() can also queue snapshot data which keeps snapshots
and samples ordered with respect to each other in case support for that
is desired.

Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lore.kernel.org/lkml/20191115124225.5247-12-adrian.hunter@intel.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 103ed40e
Loading
Loading
Loading
Loading
+107 −0
Original line number Diff line number Diff line
@@ -1004,6 +1004,113 @@ struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
	}
}

struct auxtrace_queue *auxtrace_queues__sample_queue(struct auxtrace_queues *queues,
						     struct perf_sample *sample,
						     struct perf_session *session)
{
	struct perf_sample_id *sid;
	unsigned int idx;
	u64 id;

	id = sample->id;
	if (!id)
		return NULL;

	sid = perf_evlist__id2sid(session->evlist, id);
	if (!sid)
		return NULL;

	idx = sid->idx;

	if (idx >= queues->nr_queues)
		return NULL;

	return &queues->queue_array[idx];
}

int auxtrace_queues__add_sample(struct auxtrace_queues *queues,
				struct perf_session *session,
				struct perf_sample *sample, u64 data_offset,
				u64 reference)
{
	struct auxtrace_buffer buffer = {
		.pid = -1,
		.data_offset = data_offset,
		.reference = reference,
		.size = sample->aux_sample.size,
	};
	struct perf_sample_id *sid;
	u64 id = sample->id;
	unsigned int idx;

	if (!id)
		return -EINVAL;

	sid = perf_evlist__id2sid(session->evlist, id);
	if (!sid)
		return -ENOENT;

	idx = sid->idx;
	buffer.tid = sid->tid;
	buffer.cpu = sid->cpu;

	return auxtrace_queues__add_buffer(queues, session, idx, &buffer, NULL);
}

struct queue_data {
	bool samples;
	bool events;
};

static int auxtrace_queue_data_cb(struct perf_session *session,
				  union perf_event *event, u64 offset,
				  void *data)
{
	struct queue_data *qd = data;
	struct perf_sample sample;
	int err;

	if (qd->events && event->header.type == PERF_RECORD_AUXTRACE) {
		if (event->header.size < sizeof(struct perf_record_auxtrace))
			return -EINVAL;
		offset += event->header.size;
		return session->auxtrace->queue_data(session, NULL, event,
						     offset);
	}

	if (!qd->samples || event->header.type != PERF_RECORD_SAMPLE)
		return 0;

	err = perf_evlist__parse_sample(session->evlist, event, &sample);
	if (err)
		return err;

	if (!sample.aux_sample.size)
		return 0;

	offset += sample.aux_sample.data - (void *)event;

	return session->auxtrace->queue_data(session, &sample, NULL, offset);
}

int auxtrace_queue_data(struct perf_session *session, bool samples, bool events)
{
	struct queue_data qd = {
		.samples = samples,
		.events = events,
	};

	if (auxtrace__dont_decode(session))
		return 0;

	if (!session->auxtrace || !session->auxtrace->queue_data)
		return -EINVAL;

	return perf_session__peek_events(session, session->header.data_offset,
					 session->header.data_size,
					 auxtrace_queue_data_cb, &qd);
}

void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd)
{
	size_t adj = buffer->data_offset & (page_size - 1);
+15 −0
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ struct auxtrace_index {
 * struct auxtrace - session callbacks to allow AUX area data decoding.
 * @process_event: lets the decoder see all session events
 * @process_auxtrace_event: process a PERF_RECORD_AUXTRACE event
 * @queue_data: queue an AUX sample or PERF_RECORD_AUXTRACE event for later
 *              processing
 * @dump_auxtrace_sample: dump AUX area sample data
 * @flush_events: process any remaining data
 * @free_events: free resources associated with event processing
@@ -154,6 +156,9 @@ struct auxtrace {
	int (*process_auxtrace_event)(struct perf_session *session,
				      union perf_event *event,
				      struct perf_tool *tool);
	int (*queue_data)(struct perf_session *session,
			  struct perf_sample *sample, union perf_event *event,
			  u64 data_offset);
	void (*dump_auxtrace_sample)(struct perf_session *session,
				     struct perf_sample *sample);
	int (*flush_events)(struct perf_session *session,
@@ -467,9 +472,19 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues,
			       struct perf_session *session,
			       union perf_event *event, off_t data_offset,
			       struct auxtrace_buffer **buffer_ptr);
struct auxtrace_queue *
auxtrace_queues__sample_queue(struct auxtrace_queues *queues,
			      struct perf_sample *sample,
			      struct perf_session *session);
int auxtrace_queues__add_sample(struct auxtrace_queues *queues,
				struct perf_session *session,
				struct perf_sample *sample, u64 data_offset,
				u64 reference);
void auxtrace_queues__free(struct auxtrace_queues *queues);
int auxtrace_queues__process_index(struct auxtrace_queues *queues,
				   struct perf_session *session);
int auxtrace_queue_data(struct perf_session *session, bool samples,
			bool events);
struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
					      struct auxtrace_buffer *buffer);
void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd);