perf tools: Add support for PERF_SAMPLE_IDENTIFIER
Enable parsing of samples with sample format bit PERF_SAMPLE_IDENTIFIER. In addition, if the kernel supports it, prefer it to selecting PERF_SAMPLE_ID thereby allowing non-matching sample types. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> 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> Link: http://lkml.kernel.org/r/1377591794-30553-8-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
faf967068e
commit
75562573ba
@@ -31,7 +31,7 @@ static struct {
|
||||
|
||||
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
||||
|
||||
static int __perf_evsel__sample_size(u64 sample_type)
|
||||
int __perf_evsel__sample_size(u64 sample_type)
|
||||
{
|
||||
u64 mask = sample_type & PERF_SAMPLE_MASK;
|
||||
int size = 0;
|
||||
@@ -47,6 +47,72 @@ static int __perf_evsel__sample_size(u64 sample_type)
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* __perf_evsel__calc_id_pos - calculate id_pos.
|
||||
* @sample_type: sample type
|
||||
*
|
||||
* This function returns the position of the event id (PERF_SAMPLE_ID or
|
||||
* PERF_SAMPLE_IDENTIFIER) in a sample event i.e. in the array of struct
|
||||
* sample_event.
|
||||
*/
|
||||
static int __perf_evsel__calc_id_pos(u64 sample_type)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_IDENTIFIER)
|
||||
return 0;
|
||||
|
||||
if (!(sample_type & PERF_SAMPLE_ID))
|
||||
return -1;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_IP)
|
||||
idx += 1;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_TID)
|
||||
idx += 1;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_TIME)
|
||||
idx += 1;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_ADDR)
|
||||
idx += 1;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* __perf_evsel__calc_is_pos - calculate is_pos.
|
||||
* @sample_type: sample type
|
||||
*
|
||||
* This function returns the position (counting backwards) of the event id
|
||||
* (PERF_SAMPLE_ID or PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if
|
||||
* sample_id_all is used there is an id sample appended to non-sample events.
|
||||
*/
|
||||
static int __perf_evsel__calc_is_pos(u64 sample_type)
|
||||
{
|
||||
int idx = 1;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_IDENTIFIER)
|
||||
return 1;
|
||||
|
||||
if (!(sample_type & PERF_SAMPLE_ID))
|
||||
return -1;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_CPU)
|
||||
idx += 1;
|
||||
|
||||
if (sample_type & PERF_SAMPLE_STREAM_ID)
|
||||
idx += 1;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void perf_evsel__calc_id_pos(struct perf_evsel *evsel)
|
||||
{
|
||||
evsel->id_pos = __perf_evsel__calc_id_pos(evsel->attr.sample_type);
|
||||
evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type);
|
||||
}
|
||||
|
||||
void hists__init(struct hists *hists)
|
||||
{
|
||||
memset(hists, 0, sizeof(*hists));
|
||||
@@ -63,6 +129,7 @@ void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
|
||||
if (!(evsel->attr.sample_type & bit)) {
|
||||
evsel->attr.sample_type |= bit;
|
||||
evsel->sample_size += sizeof(u64);
|
||||
perf_evsel__calc_id_pos(evsel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,12 +139,19 @@ void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
|
||||
if (evsel->attr.sample_type & bit) {
|
||||
evsel->attr.sample_type &= ~bit;
|
||||
evsel->sample_size -= sizeof(u64);
|
||||
perf_evsel__calc_id_pos(evsel);
|
||||
}
|
||||
}
|
||||
|
||||
void perf_evsel__set_sample_id(struct perf_evsel *evsel)
|
||||
void perf_evsel__set_sample_id(struct perf_evsel *evsel,
|
||||
bool can_sample_identifier)
|
||||
{
|
||||
perf_evsel__set_sample_bit(evsel, ID);
|
||||
if (can_sample_identifier) {
|
||||
perf_evsel__reset_sample_bit(evsel, ID);
|
||||
perf_evsel__set_sample_bit(evsel, IDENTIFIER);
|
||||
} else {
|
||||
perf_evsel__set_sample_bit(evsel, ID);
|
||||
}
|
||||
evsel->attr.read_format |= PERF_FORMAT_ID;
|
||||
}
|
||||
|
||||
@@ -90,6 +164,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
|
||||
INIT_LIST_HEAD(&evsel->node);
|
||||
hists__init(&evsel->hists);
|
||||
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
|
||||
perf_evsel__calc_id_pos(evsel);
|
||||
}
|
||||
|
||||
struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
|
||||
@@ -509,7 +584,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
|
||||
* We need ID even in case of single event, because
|
||||
* PERF_SAMPLE_READ process ID specific data.
|
||||
*/
|
||||
perf_evsel__set_sample_id(evsel);
|
||||
perf_evsel__set_sample_id(evsel, false);
|
||||
|
||||
/*
|
||||
* Apply group format only if we belong to group
|
||||
@@ -1088,6 +1163,11 @@ static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
|
||||
array += ((event->header.size -
|
||||
sizeof(event->header)) / sizeof(u64)) - 1;
|
||||
|
||||
if (type & PERF_SAMPLE_IDENTIFIER) {
|
||||
sample->id = *array;
|
||||
array--;
|
||||
}
|
||||
|
||||
if (type & PERF_SAMPLE_CPU) {
|
||||
u.val64 = *array;
|
||||
if (swapped) {
|
||||
@@ -1184,6 +1264,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
|
||||
if (evsel->sample_size + sizeof(event->header) > event->header.size)
|
||||
return -EFAULT;
|
||||
|
||||
data->id = -1ULL;
|
||||
if (type & PERF_SAMPLE_IDENTIFIER) {
|
||||
data->id = *array;
|
||||
array++;
|
||||
}
|
||||
|
||||
if (type & PERF_SAMPLE_IP) {
|
||||
data->ip = *array;
|
||||
array++;
|
||||
@@ -1214,7 +1300,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
|
||||
array++;
|
||||
}
|
||||
|
||||
data->id = -1ULL;
|
||||
if (type & PERF_SAMPLE_ID) {
|
||||
data->id = *array;
|
||||
array++;
|
||||
@@ -1396,6 +1481,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
|
||||
|
||||
array = event->sample.array;
|
||||
|
||||
if (type & PERF_SAMPLE_IDENTIFIER) {
|
||||
*array = sample->id;
|
||||
array++;
|
||||
}
|
||||
|
||||
if (type & PERF_SAMPLE_IP) {
|
||||
*array = sample->ip;
|
||||
array++;
|
||||
@@ -1584,6 +1674,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
|
||||
bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
|
||||
bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
|
||||
bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
|
||||
bit_name(IDENTIFIER),
|
||||
{ .name = NULL, }
|
||||
};
|
||||
#undef bit_name
|
||||
|
Reference in New Issue
Block a user