Skip to content

Commit

Permalink
perf: Make common SAMPLE_EVENT parser
Browse files Browse the repository at this point in the history
Currently, sample event data is parsed for each commands, and it
is assuming that the data is not including other data. (E.g.
timechart, trace, etc. can't parse the event if it has
PERF_SAMPLE_CALLCHAIN)

So, even if we record the superset data for multiple commands at
a time, commands can't parse. etc.

To fix it, this makes common sample event parser, and use it to
parse sample event correctly. (PERF_SAMPLE_READ is unsupported
for now though, it seems to be not using.)

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <87hbs48imv.fsf@devron.myhome.or.jp>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
OGAWAHirofumi authored and Ingo Molnar committed Dec 6, 2009
1 parent 028c515 commit 180f95e
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 146 deletions.
36 changes: 12 additions & 24 deletions tools/perf/builtin-kmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,35 +320,23 @@ process_raw_event(event_t *raw_event __used, void *more_data,

static int process_sample_event(event_t *event)
{
u64 ip = event->ip.ip;
u64 timestamp = -1;
u32 cpu = -1;
u64 period = 1;
void *more_data = event->ip.__more_data;
struct thread *thread = threads__findnew(event->ip.pid);

if (sample_type & PERF_SAMPLE_TIME) {
timestamp = *(u64 *)more_data;
more_data += sizeof(u64);
}
struct sample_data data;
struct thread *thread;

if (sample_type & PERF_SAMPLE_CPU) {
cpu = *(u32 *)more_data;
more_data += sizeof(u32);
more_data += sizeof(u32); /* reserved */
}
memset(&data, 0, sizeof(data));
data.time = -1;
data.cpu = -1;
data.period = 1;

if (sample_type & PERF_SAMPLE_PERIOD) {
period = *(u64 *)more_data;
more_data += sizeof(u64);
}
event__parse_sample(event, sample_type, &data);

dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
event->header.misc,
event->ip.pid, event->ip.tid,
(void *)(long)ip,
(long long)period);
data.pid, data.tid,
(void *)(long)data.ip,
(long long)data.period);

thread = threads__findnew(event->ip.pid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
Expand All @@ -357,7 +345,7 @@ static int process_sample_event(event_t *event)

dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);

process_raw_event(event, more_data, cpu, timestamp, thread);
process_raw_event(event, data.raw_data, data.cpu, data.time, thread);

return 0;
}
Expand Down
39 changes: 18 additions & 21 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,44 +605,41 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)

static int process_sample_event(event_t *event)
{
u64 ip = event->ip.ip;
u64 period = 1;
void *more_data = event->ip.__more_data;
struct ip_callchain *chain = NULL;
struct sample_data data;
int cpumode;
struct addr_location al;
struct thread *thread = threads__findnew(event->ip.pid);
struct thread *thread;

if (sample_type & PERF_SAMPLE_PERIOD) {
period = *(u64 *)more_data;
more_data += sizeof(u64);
}
memset(&data, 0, sizeof(data));
data.period = 1;

event__parse_sample(event, sample_type, &data);

dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
event->header.misc,
event->ip.pid, event->ip.tid,
(void *)(long)ip,
(long long)period);
data.pid, data.tid,
(void *)(long)data.ip,
(long long)data.period);

if (sample_type & PERF_SAMPLE_CALLCHAIN) {
unsigned int i;

chain = (void *)more_data;

dump_printf("... chain: nr:%Lu\n", chain->nr);
dump_printf("... chain: nr:%Lu\n", data.callchain->nr);

if (validate_chain(chain, event) < 0) {
if (validate_chain(data.callchain, event) < 0) {
pr_debug("call-chain problem with event, "
"skipping it.\n");
return 0;
}

if (dump_trace) {
for (i = 0; i < chain->nr; i++)
dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]);
for (i = 0; i < data.callchain->nr; i++)
dump_printf("..... %2d: %016Lx\n",
i, data.callchain->ips[i]);
}
}

thread = threads__findnew(data.pid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
Expand All @@ -657,7 +654,7 @@ static int process_sample_event(event_t *event)
cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

thread__find_addr_location(thread, cpumode,
MAP__FUNCTION, ip, &al, NULL);
MAP__FUNCTION, data.ip, &al, NULL);
/*
* We have to do this here as we may have a dso with no symbol hit that
* has a name longer than the ones with symbols sampled.
Expand All @@ -675,12 +672,12 @@ static int process_sample_event(event_t *event)
if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
return 0;

if (hist_entry__add(&al, chain, period)) {
if (hist_entry__add(&al, data.callchain, data.period)) {
pr_debug("problem incrementing symbol count, skipping event\n");
return -1;
}

event__stats.total += period;
event__stats.total += data.period;

return 0;
}
Expand Down
38 changes: 12 additions & 26 deletions tools/perf/builtin-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1598,40 +1598,26 @@ process_raw_event(event_t *raw_event __used, void *more_data,

static int process_sample_event(event_t *event)
{
struct sample_data data;
struct thread *thread;
u64 ip = event->ip.ip;
u64 timestamp = -1;
u32 cpu = -1;
u64 period = 1;
void *more_data = event->ip.__more_data;

if (!(sample_type & PERF_SAMPLE_RAW))
return 0;

thread = threads__findnew(event->ip.pid);
memset(&data, 0, sizeof(data));
data.time = -1;
data.cpu = -1;
data.period = -1;

if (sample_type & PERF_SAMPLE_TIME) {
timestamp = *(u64 *)more_data;
more_data += sizeof(u64);
}

if (sample_type & PERF_SAMPLE_CPU) {
cpu = *(u32 *)more_data;
more_data += sizeof(u32);
more_data += sizeof(u32); /* reserved */
}

if (sample_type & PERF_SAMPLE_PERIOD) {
period = *(u64 *)more_data;
more_data += sizeof(u64);
}
event__parse_sample(event, sample_type, &data);

dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
event->header.misc,
event->ip.pid, event->ip.tid,
(void *)(long)ip,
(long long)period);
data.pid, data.tid,
(void *)(long)data.ip,
(long long)data.period);

thread = threads__findnew(data.pid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
Expand All @@ -1640,10 +1626,10 @@ static int process_sample_event(event_t *event)

dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);

if (profile_cpu != -1 && profile_cpu != (int) cpu)
if (profile_cpu != -1 && profile_cpu != (int)data.cpu)
return 0;

process_raw_event(event, more_data, cpu, timestamp, thread);
process_raw_event(event, data.raw_data, data.cpu, data.time, thread);

return 0;
}
Expand Down
56 changes: 15 additions & 41 deletions tools/perf/builtin-timechart.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,48 +483,22 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
static int
process_sample_event(event_t *event)
{
int cursor = 0;
u64 addr = 0;
u64 stamp = 0;
u32 cpu = 0;
u32 pid = 0;
u32 size, *size_ptr;
struct sample_data data;
struct trace_entry *te;

if (sample_type & PERF_SAMPLE_IP)
cursor++;

if (sample_type & PERF_SAMPLE_TID) {
pid = event->sample.array[cursor]>>32;
cursor++;
}
if (sample_type & PERF_SAMPLE_TIME) {
stamp = event->sample.array[cursor++];
memset(&data, 0, sizeof(data));

if (!first_time || first_time > stamp)
first_time = stamp;
if (last_time < stamp)
last_time = stamp;
event__parse_sample(event, sample_type, &data);

if (sample_type & PERF_SAMPLE_TIME) {
if (!first_time || first_time > data.time)
first_time = data.time;
if (last_time < data.time)
last_time = data.time;
}
if (sample_type & PERF_SAMPLE_ADDR)
addr = event->sample.array[cursor++];
if (sample_type & PERF_SAMPLE_ID)
cursor++;
if (sample_type & PERF_SAMPLE_STREAM_ID)
cursor++;
if (sample_type & PERF_SAMPLE_CPU)
cpu = event->sample.array[cursor++] & 0xFFFFFFFF;
if (sample_type & PERF_SAMPLE_PERIOD)
cursor++;

size_ptr = (void *)&event->sample.array[cursor];

size = *size_ptr;
size_ptr++;

te = (void *)size_ptr;
if (sample_type & PERF_SAMPLE_RAW && size > 0) {
te = (void *)data.raw_data;
if (sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) {
char *event_str;
struct power_entry *pe;

Expand All @@ -536,19 +510,19 @@ process_sample_event(event_t *event)
return 0;

if (strcmp(event_str, "power:power_start") == 0)
c_state_start(cpu, stamp, pe->value);
c_state_start(data.cpu, data.time, pe->value);

if (strcmp(event_str, "power:power_end") == 0)
c_state_end(cpu, stamp);
c_state_end(data.cpu, data.time);

if (strcmp(event_str, "power:power_frequency") == 0)
p_state_change(cpu, stamp, pe->value);
p_state_change(data.cpu, data.time, pe->value);

if (strcmp(event_str, "sched:sched_wakeup") == 0)
sched_wakeup(cpu, stamp, pid, te);
sched_wakeup(data.cpu, data.time, data.pid, te);

if (strcmp(event_str, "sched:sched_switch") == 0)
sched_switch(cpu, stamp, te);
sched_switch(data.cpu, data.time, te);
}
return 0;
}
Expand Down
48 changes: 15 additions & 33 deletions tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,58 +66,40 @@ static u64 sample_type;

static int process_sample_event(event_t *event)
{
u64 ip = event->ip.ip;
u64 timestamp = -1;
u32 cpu = -1;
u64 period = 1;
void *more_data = event->ip.__more_data;
struct thread *thread = threads__findnew(event->ip.pid);

if (sample_type & PERF_SAMPLE_TIME) {
timestamp = *(u64 *)more_data;
more_data += sizeof(u64);
}
struct sample_data data;
struct thread *thread;

if (sample_type & PERF_SAMPLE_CPU) {
cpu = *(u32 *)more_data;
more_data += sizeof(u32);
more_data += sizeof(u32); /* reserved */
}
memset(&data, 0, sizeof(data));
data.time = -1;
data.cpu = -1;
data.period = 1;

if (sample_type & PERF_SAMPLE_PERIOD) {
period = *(u64 *)more_data;
more_data += sizeof(u64);
}
event__parse_sample(event, sample_type, &data);

dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
event->header.misc,
event->ip.pid, event->ip.tid,
(void *)(long)ip,
(long long)period);
data.pid, data.tid,
(void *)(long)data.ip,
(long long)data.period);

thread = threads__findnew(event->ip.pid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
return -1;
}

dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);

if (sample_type & PERF_SAMPLE_RAW) {
struct {
u32 size;
char data[0];
} *raw = more_data;

/*
* FIXME: better resolve from pid from the struct trace_entry
* field, although it should be the same than this perf
* event pid
*/
scripting_ops->process_event(cpu, raw->data, raw->size,
timestamp, thread->comm);
scripting_ops->process_event(data.cpu, data.raw_data,
data.raw_size,
data.time, thread->comm);
}
event__stats.total += period;
event__stats.total += data.period;

return 0;
}
Expand Down
Loading

0 comments on commit 180f95e

Please sign in to comment.