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: Adrian 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: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
103ed40e4b
commit
ac2f445fc8
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user