perf tools: Add AUX area tracing Snapshot Mode

Add support for making snapshots of AUX area tracing data.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1430404667-10593-9-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Adrian Hunter
2015-04-30 17:37:31 +03:00
committed by Arnaldo Carvalho de Melo
parent 0ad21f6869
commit d20031bb63
3 changed files with 119 additions and 10 deletions

View File

@@ -504,6 +504,29 @@ void auxtrace_record__free(struct auxtrace_record *itr)
itr->free(itr);
}
int auxtrace_record__snapshot_start(struct auxtrace_record *itr)
{
if (itr && itr->snapshot_start)
return itr->snapshot_start(itr);
return 0;
}
int auxtrace_record__snapshot_finish(struct auxtrace_record *itr)
{
if (itr && itr->snapshot_finish)
return itr->snapshot_finish(itr);
return 0;
}
int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
struct auxtrace_mmap *mm,
unsigned char *data, u64 *head, u64 *old)
{
if (itr && itr->find_snapshot)
return itr->find_snapshot(itr, idx, mm, data, head, old);
return 0;
}
int auxtrace_record__options(struct auxtrace_record *itr,
struct perf_evlist *evlist,
struct record_opts *opts)
@@ -520,6 +543,19 @@ u64 auxtrace_record__reference(struct auxtrace_record *itr)
return 0;
}
int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
struct record_opts *opts, const char *str)
{
if (!str)
return 0;
if (itr)
return itr->parse_snapshot_options(itr, opts, str);
pr_err("No AUX area tracing to snapshot\n");
return -EINVAL;
}
struct auxtrace_record *__weak
auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, int *err)
{
@@ -1077,16 +1113,26 @@ int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
return 0;
}
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn)
static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
bool snapshot, size_t snapshot_size)
{
u64 head = auxtrace_mmap__read_head(mm);
u64 old = mm->prev, offset, ref;
u64 head, old = mm->prev, offset, ref;
unsigned char *data = mm->base;
size_t size, head_off, old_off, len1, len2, padding;
union perf_event ev;
void *data1, *data2;
if (snapshot) {
head = auxtrace_mmap__read_snapshot_head(mm);
if (auxtrace_record__find_snapshot(itr, mm->idx, mm, data,
&head, &old))
return -1;
} else {
head = auxtrace_mmap__read_head(mm);
}
if (old == head)
return 0;
@@ -1106,6 +1152,9 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
else
size = mm->len - (old_off - head_off);
if (snapshot && size > snapshot_size)
size = snapshot_size;
ref = auxtrace_record__reference(itr);
if (head > old || size <= head || mm->mask) {
@@ -1153,18 +1202,34 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
mm->prev = head;
auxtrace_mmap__write_tail(mm, head);
if (itr->read_finish) {
int err;
if (!snapshot) {
auxtrace_mmap__write_tail(mm, head);
if (itr->read_finish) {
int err;
err = itr->read_finish(itr, mm->idx);
if (err < 0)
return err;
err = itr->read_finish(itr, mm->idx);
if (err < 0)
return err;
}
}
return 1;
}
int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn)
{
return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0);
}
int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm,
struct auxtrace_record *itr,
struct perf_tool *tool, process_auxtrace_t fn,
size_t snapshot_size)
{
return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size);
}
/**
* struct auxtrace_cache - hash table to implement a cache
* @hashtable: the hashtable