Skip to content

Commit

Permalink
perf tools: Add support for PERF_SAMPLE_IDENTIFIER
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Adrian Hunter authored and Arnaldo Carvalho de Melo committed Aug 29, 2013
1 parent faf9670 commit 7556257
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 22 deletions.
2 changes: 1 addition & 1 deletion tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ static int process_read_event(struct perf_tool *tool,
static int perf_report__setup_sample_type(struct perf_report *rep)
{
struct perf_session *self = rep->session;
u64 sample_type = perf_evlist__sample_type(self->evlist);
u64 sample_type = perf_evlist__combined_sample_type(self->evlist);

if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/tests/mmap-basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int test__basic_mmap(void)
}

evsels[i]->attr.wakeup_events = 1;
perf_evsel__set_sample_id(evsels[i]);
perf_evsel__set_sample_id(evsels[i], false);

perf_evlist__add(evlist, evsels[i]);

Expand Down
3 changes: 2 additions & 1 deletion tools/perf/util/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ struct read_event {
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \
PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \
PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
PERF_SAMPLE_IDENTIFIER)

struct sample_event {
struct perf_event_header header;
Expand Down
111 changes: 103 additions & 8 deletions tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ struct perf_evlist *perf_evlist__new(void)
return evlist;
}

/**
* perf_evlist__set_id_pos - set the positions of event ids.
* @evlist: selected event list
*
* Events with compatible sample types all have the same id_pos
* and is_pos. For convenience, put a copy on evlist.
*/
void perf_evlist__set_id_pos(struct perf_evlist *evlist)
{
struct perf_evsel *first = perf_evlist__first(evlist);

evlist->id_pos = first->id_pos;
evlist->is_pos = first->is_pos;
}

static void perf_evlist__purge(struct perf_evlist *evlist)
{
struct perf_evsel *pos, *n;
Expand Down Expand Up @@ -79,15 +94,20 @@ void perf_evlist__delete(struct perf_evlist *evlist)
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
{
list_add_tail(&entry->node, &evlist->entries);
++evlist->nr_entries;
if (!evlist->nr_entries++)
perf_evlist__set_id_pos(evlist);
}

void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
struct list_head *list,
int nr_entries)
{
bool set_id_pos = !evlist->nr_entries;

list_splice_tail(list, &evlist->entries);
evlist->nr_entries += nr_entries;
if (set_id_pos)
perf_evlist__set_id_pos(evlist);
}

void __perf_evlist__set_leader(struct list_head *list)
Expand Down Expand Up @@ -349,6 +369,55 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
return NULL;
}

static int perf_evlist__event2id(struct perf_evlist *evlist,
union perf_event *event, u64 *id)
{
const u64 *array = event->sample.array;
ssize_t n;

n = (event->header.size - sizeof(event->header)) >> 3;

if (event->header.type == PERF_RECORD_SAMPLE) {
if (evlist->id_pos >= n)
return -1;
*id = array[evlist->id_pos];
} else {
if (evlist->is_pos > n)
return -1;
n -= evlist->is_pos;
*id = array[n];
}
return 0;
}

static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
union perf_event *event)
{
struct hlist_head *head;
struct perf_sample_id *sid;
int hash;
u64 id;

if (evlist->nr_entries == 1)
return perf_evlist__first(evlist);

if (perf_evlist__event2id(evlist, event, &id))
return NULL;

/* Synthesized events have an id of zero */
if (!id)
return perf_evlist__first(evlist);

hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
head = &evlist->heads[hash];

hlist_for_each_entry(sid, head, node) {
if (sid->id == id)
return sid->evsel;
}
return NULL;
}

union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
{
struct perf_mmap *md = &evlist->mmap[idx];
Expand Down Expand Up @@ -659,20 +728,40 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)

bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
{
struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
struct perf_evsel *pos;

list_for_each_entry_continue(pos, &evlist->entries, node) {
if (first->attr.sample_type != pos->attr.sample_type)
if (evlist->nr_entries == 1)
return true;

if (evlist->id_pos < 0 || evlist->is_pos < 0)
return false;

list_for_each_entry(pos, &evlist->entries, node) {
if (pos->id_pos != evlist->id_pos ||
pos->is_pos != evlist->is_pos)
return false;
}

return true;
}

u64 perf_evlist__sample_type(struct perf_evlist *evlist)
u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
{
struct perf_evsel *first = perf_evlist__first(evlist);
return first->attr.sample_type;
struct perf_evsel *evsel;

if (evlist->combined_sample_type)
return evlist->combined_sample_type;

list_for_each_entry(evsel, &evlist->entries, node)
evlist->combined_sample_type |= evsel->attr.sample_type;

return evlist->combined_sample_type;
}

u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist)
{
evlist->combined_sample_type = 0;
return __perf_evlist__combined_sample_type(evlist);
}

bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
Expand Down Expand Up @@ -727,6 +816,9 @@ u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)

if (sample_type & PERF_SAMPLE_CPU)
size += sizeof(data->cpu) * 2;

if (sample_type & PERF_SAMPLE_IDENTIFIER)
size += sizeof(data->id);
out:
return size;
}
Expand Down Expand Up @@ -885,7 +977,10 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
struct perf_sample *sample)
{
struct perf_evsel *evsel = perf_evlist__first(evlist);
struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);

if (!evsel)
return -EFAULT;
return perf_evsel__parse_sample(evsel, event, sample);
}

Expand Down
8 changes: 7 additions & 1 deletion tools/perf/util/evlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ struct perf_evlist {
int nr_fds;
int nr_mmaps;
int mmap_len;
int id_pos;
int is_pos;
u64 combined_sample_type;
struct {
int cork_fd;
pid_t pid;
Expand Down Expand Up @@ -85,6 +88,8 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
int perf_evlist__open(struct perf_evlist *evlist);
void perf_evlist__close(struct perf_evlist *evlist);

void perf_evlist__set_id_pos(struct perf_evlist *evlist);
bool perf_can_sample_identifier(void);
void perf_evlist__config(struct perf_evlist *evlist,
struct perf_record_opts *opts);

Expand Down Expand Up @@ -121,7 +126,8 @@ void __perf_evlist__set_leader(struct list_head *list);
void perf_evlist__set_leader(struct perf_evlist *evlist);

u64 perf_evlist__read_format(struct perf_evlist *evlist);
u64 perf_evlist__sample_type(struct perf_evlist *evlist);
u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist);
u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist);
bool perf_evlist__sample_id_all(struct perf_evlist *evlist);
u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);

Expand Down
Loading

0 comments on commit 7556257

Please sign in to comment.