Commit 62daacb5 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar

perf tools: Reorganize event processing routines, lotsa dups killed

While implementing event__preprocess_sample, that will do all of
the symbol lookup in one convenient function, I noticed that
util/process_event.[ch] were not being used at all, then started
looking if there were other functions that could be shared
and...

All those functions really don't need to receive offset + head,
the only thing they did was common to all of them, so do it at
one place instead.

Stats about number of each type of event processed now is done
in a central place.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-11-git-send-email-acme@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 1de8e245
...@@ -369,7 +369,6 @@ LIB_H += util/sort.h ...@@ -369,7 +369,6 @@ LIB_H += util/sort.h
LIB_H += util/hist.h LIB_H += util/hist.h
LIB_H += util/thread.h LIB_H += util/thread.h
LIB_H += util/data_map.h LIB_H += util/data_map.h
LIB_H += util/process_events.h
LIB_OBJS += util/abspath.o LIB_OBJS += util/abspath.o
LIB_OBJS += util/alias.o LIB_OBJS += util/alias.o
...@@ -412,7 +411,6 @@ LIB_OBJS += util/svghelper.o ...@@ -412,7 +411,6 @@ LIB_OBJS += util/svghelper.o
LIB_OBJS += util/sort.o LIB_OBJS += util/sort.o
LIB_OBJS += util/hist.o LIB_OBJS += util/hist.o
LIB_OBJS += util/data_map.o LIB_OBJS += util/data_map.o
LIB_OBJS += util/process_events.o
BUILTIN_OBJS += builtin-annotate.o BUILTIN_OBJS += builtin-annotate.o
......
...@@ -19,12 +19,12 @@ ...@@ -19,12 +19,12 @@
#include "perf.h" #include "perf.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/event.h"
#include "util/parse-options.h" #include "util/parse-options.h"
#include "util/parse-events.h" #include "util/parse-events.h"
#include "util/thread.h" #include "util/thread.h"
#include "util/sort.h" #include "util/sort.h"
#include "util/hist.h" #include "util/hist.h"
#include "util/process_events.h"
static char const *input_name = "perf.data"; static char const *input_name = "perf.data";
...@@ -136,8 +136,7 @@ static int hist_entry__add(struct thread *thread, struct map *map, ...@@ -136,8 +136,7 @@ static int hist_entry__add(struct thread *thread, struct map *map,
return 0; return 0;
} }
static int static int process_sample_event(event_t *event)
process_sample_event(event_t *event, unsigned long offset, unsigned long head)
{ {
char level; char level;
u64 ip = event->ip.ip; u64 ip = event->ip.ip;
...@@ -145,12 +144,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -145,12 +144,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
struct symbol *sym = NULL; struct symbol *sym = NULL;
struct thread *thread = threads__findnew(event->ip.pid); struct thread *thread = threads__findnew(event->ip.pid);
dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", dump_printf("(IP, %d): %d: %p\n", event->header.misc,
(void *)(offset + head), event->ip.pid, (void *)(long)ip);
(void *)(long)(event->header.size),
event->header.misc,
event->ip.pid,
(void *)(long)ip);
if (thread == NULL) { if (thread == NULL) {
fprintf(stderr, "problem processing %d event, skipping it.\n", fprintf(stderr, "problem processing %d event, skipping it.\n",
...@@ -198,46 +193,24 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -198,46 +193,24 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
"skipping event\n"); "skipping event\n");
return -1; return -1;
} }
total++;
return 0; return 0;
} }
static int static int event__process(event_t *self)
process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{ {
struct thread *thread = threads__findnew(event->comm.pid); switch (self->header.type) {
dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
return -1;
}
total_comm++;
return 0;
}
static int
process_event(event_t *event, unsigned long offset, unsigned long head)
{
switch (event->header.type) {
case PERF_RECORD_SAMPLE: case PERF_RECORD_SAMPLE:
return process_sample_event(event, offset, head); return process_sample_event(self);
case PERF_RECORD_MMAP: case PERF_RECORD_MMAP:
return process_mmap_event(event, offset, head); return event__process_mmap(self);
case PERF_RECORD_COMM: case PERF_RECORD_COMM:
return process_comm_event(event, offset, head); return event__process_comm(self);
case PERF_RECORD_FORK: case PERF_RECORD_FORK:
return process_task_event(event, offset, head); return event__process_task(self);
/* /*
* We dont process them right now but they are fine: * We dont process them right now but they are fine:
*/ */
...@@ -621,15 +594,12 @@ static int __cmd_annotate(void) ...@@ -621,15 +594,12 @@ static int __cmd_annotate(void)
(void *)(long)event->header.size, (void *)(long)event->header.size,
event->header.type); event->header.type);
if (!size || process_event(event, offset, head) < 0) { if (!size || event__process(event) < 0) {
dump_printf("%p [%p]: skipping unknown header type: %d\n", dump_printf("%p [%p]: skipping unknown header type: %d\n",
(void *)(offset + head), (void *)(offset + head),
(void *)(long)(event->header.size), (void *)(long)(event->header.size),
event->header.type); event->header.type);
total_unknown++;
/* /*
* assume we lost track of the stream, check alignment, and * assume we lost track of the stream, check alignment, and
* increment a single u64 in the hope to catch on again 'soon'. * increment a single u64 in the hope to catch on again 'soon'.
...@@ -649,14 +619,11 @@ static int __cmd_annotate(void) ...@@ -649,14 +619,11 @@ static int __cmd_annotate(void)
rc = EXIT_SUCCESS; rc = EXIT_SUCCESS;
close(input); close(input);
dump_printf(" IP events: %10ld\n", total);
dump_printf(" mmap events: %10ld\n", total_mmap);
dump_printf(" comm events: %10ld\n", total_comm);
dump_printf(" fork events: %10ld\n", total_fork);
dump_printf(" unknown events: %10ld\n", total_unknown);
if (dump_trace) if (dump_trace) {
event__print_totals();
return 0; return 0;
}
if (verbose > 3) if (verbose > 3)
threads__fprintf(stdout); threads__fprintf(stdout);
...@@ -665,7 +632,7 @@ static int __cmd_annotate(void) ...@@ -665,7 +632,7 @@ static int __cmd_annotate(void)
dsos__fprintf(stdout); dsos__fprintf(stdout);
collapse__resort(); collapse__resort();
output__resort(total); output__resort(event__total[0]);
find_annotations(); find_annotations();
......
...@@ -33,9 +33,6 @@ static bool raw_ip; ...@@ -33,9 +33,6 @@ static bool raw_ip;
static char default_sort_order[] = "frag,hit,bytes"; static char default_sort_order[] = "frag,hit,bytes";
static char *cwd;
static int cwdlen;
static int *cpunode_map; static int *cpunode_map;
static int max_cpu_num; static int max_cpu_num;
...@@ -126,25 +123,6 @@ static void setup_cpunode_map(void) ...@@ -126,25 +123,6 @@ static void setup_cpunode_map(void)
} }
} }
static int
process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{
struct thread *thread = threads__findnew(event->comm.pid);
dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
return -1;
}
return 0;
}
static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, static void insert_alloc_stat(unsigned long call_site, unsigned long ptr,
int bytes_req, int bytes_alloc, int cpu) int bytes_req, int bytes_alloc, int cpu)
{ {
...@@ -340,8 +318,7 @@ process_raw_event(event_t *raw_event __used, void *more_data, ...@@ -340,8 +318,7 @@ process_raw_event(event_t *raw_event __used, void *more_data,
} }
} }
static int static int process_sample_event(event_t *event)
process_sample_event(event_t *event, unsigned long offset, unsigned long head)
{ {
u64 ip = event->ip.ip; u64 ip = event->ip.ip;
u64 timestamp = -1; u64 timestamp = -1;
...@@ -366,9 +343,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -366,9 +343,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
more_data += sizeof(u64); more_data += sizeof(u64);
} }
dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.misc, event->header.misc,
event->ip.pid, event->ip.tid, event->ip.pid, event->ip.tid,
(void *)(long)ip, (void *)(long)ip,
...@@ -403,7 +378,7 @@ static int sample_type_check(u64 type) ...@@ -403,7 +378,7 @@ static int sample_type_check(u64 type)
static struct perf_file_handler file_handler = { static struct perf_file_handler file_handler = {
.process_sample_event = process_sample_event, .process_sample_event = process_sample_event,
.process_comm_event = process_comm_event, .process_comm_event = event__process_comm,
.sample_type_check = sample_type_check, .sample_type_check = sample_type_check,
}; };
...@@ -413,7 +388,7 @@ static int read_events(void) ...@@ -413,7 +388,7 @@ static int read_events(void)
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
return mmap_dispatch_perf_file(&header, input_name, 0, 0, return mmap_dispatch_perf_file(&header, input_name, 0, 0,
&cwdlen, &cwd); &event__cwdlen, &event__cwd);
} }
static double fragmentation(unsigned long n_req, unsigned long n_alloc) static double fragmentation(unsigned long n_req, unsigned long n_alloc)
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "util/thread.h" #include "util/thread.h"
#include "util/sort.h" #include "util/sort.h"
#include "util/hist.h" #include "util/hist.h"
#include "util/process_events.h"
static char const *input_name = "perf.data"; static char const *input_name = "perf.data";
...@@ -655,8 +654,7 @@ static int validate_chain(struct ip_callchain *chain, event_t *event) ...@@ -655,8 +654,7 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
return 0; return 0;
} }
static int static int process_sample_event(event_t *event)
process_sample_event(event_t *event, unsigned long offset, unsigned long head)
{ {
char level; char level;
struct symbol *sym = NULL; struct symbol *sym = NULL;
...@@ -673,9 +671,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -673,9 +671,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
more_data += sizeof(u64); more_data += sizeof(u64);
} }
dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.misc, event->header.misc,
event->ip.pid, event->ip.tid, event->ip.pid, event->ip.tid,
(void *)(long)ip, (void *)(long)ip,
...@@ -743,47 +739,27 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -743,47 +739,27 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
return -1; return -1;
} }
total += period; event__stats.total += period;
return 0; return 0;
} }
static int static int process_comm_event(event_t *event)
process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{ {
struct thread *thread = threads__findnew(event->comm.pid); struct thread *thread = threads__findnew(event->comm.pid);
dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", dump_printf(": %s:%d\n", event->comm.comm, event->comm.pid);
(void *)(offset + head),
(void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
if (thread == NULL || if (thread == NULL ||
thread__set_comm_adjust(thread, event->comm.comm)) { thread__set_comm_adjust(thread, event->comm.comm)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
return -1; return -1;
} }
total_comm++;
return 0;
}
static int
process_lost_event(event_t *event, unsigned long offset, unsigned long head)
{
dump_printf("%p [%p]: PERF_RECORD_LOST: id:%Ld: lost:%Ld\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->lost.id,
event->lost.lost);
total_lost += event->lost.lost;
return 0; return 0;
} }
static int static int process_read_event(event_t *event)
process_read_event(event_t *event, unsigned long offset, unsigned long head)
{ {
struct perf_event_attr *attr; struct perf_event_attr *attr;
...@@ -799,14 +775,9 @@ process_read_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -799,14 +775,9 @@ process_read_event(event_t *event, unsigned long offset, unsigned long head)
event->read.value); event->read.value);
} }
dump_printf("%p [%p]: PERF_RECORD_READ: %d %d %s %Lu\n", dump_printf(": %d %d %s %Lu\n", event->read.pid, event->read.tid,
(void *)(offset + head), attr ? __event_name(attr->type, attr->config) : "FAIL",
(void *)(long)(event->header.size), event->read.value);
event->read.pid,
event->read.tid,
attr ? __event_name(attr->type, attr->config)
: "FAIL",
event->read.value);
return 0; return 0;
} }
...@@ -842,11 +813,11 @@ static int sample_type_check(u64 type) ...@@ -842,11 +813,11 @@ static int sample_type_check(u64 type)
static struct perf_file_handler file_handler = { static struct perf_file_handler file_handler = {
.process_sample_event = process_sample_event, .process_sample_event = process_sample_event,
.process_mmap_event = process_mmap_event, .process_mmap_event = event__process_mmap,
.process_comm_event = process_comm_event, .process_comm_event = process_comm_event,
.process_exit_event = process_task_event, .process_exit_event = event__process_task,
.process_fork_event = process_task_event, .process_fork_event = event__process_task,
.process_lost_event = process_lost_event, .process_lost_event = event__process_lost,
.process_read_event = process_read_event, .process_read_event = process_read_event,
.sample_type_check = sample_type_check, .sample_type_check = sample_type_check,
}; };
...@@ -866,19 +837,14 @@ static int __cmd_report(void) ...@@ -866,19 +837,14 @@ static int __cmd_report(void)
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
ret = mmap_dispatch_perf_file(&header, input_name, force, ret = mmap_dispatch_perf_file(&header, input_name, force,
full_paths, &cwdlen, &cwd); full_paths, &event__cwdlen, &event__cwd);
if (ret) if (ret)
return ret; return ret;
dump_printf(" IP events: %10ld\n", total); if (dump_trace) {
dump_printf(" mmap events: %10ld\n", total_mmap); event__print_totals();
dump_printf(" comm events: %10ld\n", total_comm);
dump_printf(" fork events: %10ld\n", total_fork);
dump_printf(" lost events: %10ld\n", total_lost);
dump_printf(" unknown events: %10ld\n", file_handler.total_unknown);
if (dump_trace)
return 0; return 0;
}
if (verbose > 3) if (verbose > 3)
threads__fprintf(stdout); threads__fprintf(stdout);
...@@ -887,8 +853,8 @@ static int __cmd_report(void) ...@@ -887,8 +853,8 @@ static int __cmd_report(void)
dsos__fprintf(stdout); dsos__fprintf(stdout);
collapse__resort(); collapse__resort();
output__resort(total); output__resort(event__stats.total);
output__fprintf(stdout, total); output__fprintf(stdout, event__stats.total);
if (show_threads) if (show_threads)
perf_read_values_destroy(&show_threads_values); perf_read_values_destroy(&show_threads_values);
......
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
static char const *input_name = "perf.data"; static char const *input_name = "perf.data";
static unsigned long total_comm = 0;
static struct perf_header *header; static struct perf_header *header;
static u64 sample_type; static u64 sample_type;
...@@ -32,9 +30,6 @@ static char *sort_order = default_sort_order; ...@@ -32,9 +30,6 @@ static char *sort_order = default_sort_order;
static int profile_cpu = -1; static int profile_cpu = -1;
static char *cwd;
static int cwdlen;
#define PR_SET_NAME 15 /* Set process name */ #define PR_SET_NAME 15 /* Set process name */
#define MAX_CPUS 4096 #define MAX_CPUS 4096
...@@ -633,27 +628,6 @@ static void test_calibrations(void) ...@@ -633,27 +628,6 @@ static void test_calibrations(void)
printf("the sleep test took %Ld nsecs\n", T1-T0); printf("the sleep test took %Ld nsecs\n", T1-T0);
} }
static int
process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{
struct thread *thread = threads__findnew(event->comm.tid);
dump_printf("%p [%p]: perf_event_comm: %s:%d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
dump_printf("problem processing perf_event_comm, skipping event.\n");
return -1;
}
total_comm++;
return 0;
}
struct raw_event_sample { struct raw_event_sample {
u32 size; u32 size;
char data[0]; char data[0];
...@@ -1622,8 +1596,7 @@ process_raw_event(event_t *raw_event __used, void *more_data, ...@@ -1622,8 +1596,7 @@ process_raw_event(event_t *raw_event __used, void *more_data,
process_sched_migrate_task_event(raw, event, cpu, timestamp, thread); process_sched_migrate_task_event(raw, event, cpu, timestamp, thread);
} }
static int static int process_sample_event(event_t *event)
process_sample_event(event_t *event, unsigned long offset, unsigned long head)
{ {
struct thread *thread; struct thread *thread;
u64 ip = event->ip.ip; u64 ip = event->ip.ip;
...@@ -1653,9 +1626,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -1653,9 +1626,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
more_data += sizeof(u64); more_data += sizeof(u64);
} }
dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.misc, event->header.misc,
event->ip.pid, event->ip.tid, event->ip.pid, event->ip.tid,
(void *)(long)ip, (void *)(long)ip,
...@@ -1677,10 +1648,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -1677,10 +1648,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
return 0; return 0;
} }
static int static int process_lost_event(event_t *event __used)
process_lost_event(event_t *event __used,
unsigned long offset __used,
unsigned long head __used)
{ {
nr_lost_chunks++; nr_lost_chunks++;
nr_lost_events += event->lost.lost; nr_lost_events += event->lost.lost;
...@@ -1704,7 +1672,7 @@ static int sample_type_check(u64 type) ...@@ -1704,7 +1672,7 @@ static int sample_type_check(u64 type)
static struct perf_file_handler file_handler = { static struct perf_file_handler file_handler = {
.process_sample_event = process_sample_event, .process_sample_event = process_sample_event,
.process_comm_event = process_comm_event, .process_comm_event = event__process_comm,
.process_lost_event = process_lost_event, .process_lost_event = process_lost_event,
.sample_type_check = sample_type_check, .sample_type_check = sample_type_check,
}; };
...@@ -1715,7 +1683,7 @@ static int read_events(void) ...@@ -1715,7 +1683,7 @@ static int read_events(void)
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
return mmap_dispatch_perf_file(&header, input_name, 0, 0, return mmap_dispatch_perf_file(&header, input_name, 0, 0,
&cwdlen, &cwd); &event__cwdlen, &event__cwd);
} }
static void print_bad_events(void) static void print_bad_events(void)
......
...@@ -991,25 +991,6 @@ static void event__process_sample(const event_t *self, int counter) ...@@ -991,25 +991,6 @@ static void event__process_sample(const event_t *self, int counter)
} }
} }
static void event__process_mmap(event_t *self)
{
struct thread *thread = threads__findnew(self->mmap.pid);
if (thread != NULL) {
struct map *map = map__new(&self->mmap, MAP__FUNCTION, NULL, 0);
if (map != NULL)
thread__insert_map(thread, map);
}
}
static void event__process_comm(event_t *self)
{
struct thread *thread = threads__findnew(self->comm.pid);
if (thread != NULL)
thread__set_comm(thread, self->comm.comm);
}
static int event__process(event_t *event) static int event__process(event_t *event)
{ {
switch (event->header.type) { switch (event->header.type) {
......
...@@ -16,38 +16,10 @@ ...@@ -16,38 +16,10 @@
static char const *input_name = "perf.data"; static char const *input_name = "perf.data";
static unsigned long total = 0;
static unsigned long total_comm = 0;
static struct perf_header *header; static struct perf_header *header;
static u64 sample_type; static u64 sample_type;
static char *cwd; static int process_sample_event(event_t *event)
static int cwdlen;
static int
process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{
struct thread *thread = threads__findnew(event->comm.pid);
dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
return -1;
}
total_comm++;
return 0;
}
static int
process_sample_event(event_t *event, unsigned long offset, unsigned long head)
{ {
u64 ip = event->ip.ip; u64 ip = event->ip.ip;
u64 timestamp = -1; u64 timestamp = -1;
...@@ -72,9 +44,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -72,9 +44,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
more_data += sizeof(u64); more_data += sizeof(u64);
} }
dump_printf("%p [%p]: PERF_RECORD_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.misc, event->header.misc,
event->ip.pid, event->ip.tid, event->ip.pid, event->ip.tid,
(void *)(long)ip, (void *)(long)ip,
...@@ -101,7 +71,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) ...@@ -101,7 +71,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
*/ */
print_event(cpu, raw->data, raw->size, timestamp, thread->comm); print_event(cpu, raw->data, raw->size, timestamp, thread->comm);
} }
total += period; event__stats.total += period;
return 0; return 0;
} }
...@@ -122,7 +92,7 @@ static int sample_type_check(u64 type) ...@@ -122,7 +92,7 @@ static int sample_type_check(u64 type)
static struct perf_file_handler file_handler = { static struct perf_file_handler file_handler = {
.process_sample_event = process_sample_event, .process_sample_event = process_sample_event,
.process_comm_event = process_comm_event, .process_comm_event = event__process_comm,
.sample_type_check = sample_type_check, .sample_type_check = sample_type_check,
}; };
...@@ -132,7 +102,7 @@ static int __cmd_trace(void) ...@@ -132,7 +102,7 @@ static int __cmd_trace(void)
register_perf_file_handler(&file_handler); register_perf_file_handler(&file_handler);
return mmap_dispatch_perf_file(&header, input_name, return mmap_dispatch_perf_file(&header, input_name,
0, 0, &cwdlen, &cwd); 0, 0, &event__cwdlen, &event__cwd);
} }
static const char * const annotate_usage[] = { static const char * const annotate_usage[] = {
......
...@@ -8,11 +8,9 @@ static struct perf_file_handler *curr_handler; ...@@ -8,11 +8,9 @@ static struct perf_file_handler *curr_handler;
static unsigned long mmap_window = 32; static unsigned long mmap_window = 32;
static char __cwd[PATH_MAX]; static char __cwd[PATH_MAX];
static int static int process_event_stub(event_t *event __used)
process_event_stub(event_t *event __used,
unsigned long offset __used,
unsigned long head __used)
{ {
dump_printf(": unhandled!\n");
return 0; return 0;
} }
...@@ -40,30 +38,62 @@ void register_perf_file_handler(struct perf_file_handler *handler) ...@@ -40,30 +38,62 @@ void register_perf_file_handler(struct perf_file_handler *handler)
curr_handler = handler; curr_handler = handler;
} }
static const char *event__name[] = {
[0] = "TOTAL",
[PERF_RECORD_MMAP] = "MMAP",
[PERF_RECORD_LOST] = "LOST",
[PERF_RECORD_COMM] = "COMM",
[PERF_RECORD_EXIT] = "EXIT",
[PERF_RECORD_THROTTLE] = "THROTTLE",
[PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
[PERF_RECORD_FORK] = "FORK",
[PERF_RECORD_READ] = "READ",
[PERF_RECORD_SAMPLE] = "SAMPLE",
};
unsigned long event__total[PERF_RECORD_MAX];
void event__print_totals(void)
{
int i;
for (i = 0; i < PERF_RECORD_MAX; ++i)
pr_info("%10s events: %10ld\n",
event__name[i], event__total[i]);
}
static int static int
process_event(event_t *event, unsigned long offset, unsigned long head) process_event(event_t *event, unsigned long offset, unsigned long head)
{ {
trace_event(event); trace_event(event);
if (event->header.type < PERF_RECORD_MAX) {
dump_printf("%p [%p]: PERF_RECORD_%s",
(void *)(offset + head),
(void *)(long)(event->header.size),
event__name[event->header.type]);
++event__total[0];
++event__total[event->header.type];
}
switch (event->header.type) { switch (event->header.type) {
case PERF_RECORD_SAMPLE: case PERF_RECORD_SAMPLE:
return curr_handler->process_sample_event(event, offset, head); return curr_handler->process_sample_event(event);
case PERF_RECORD_MMAP: case PERF_RECORD_MMAP:
return curr_handler->process_mmap_event(event, offset, head); return curr_handler->process_mmap_event(event);
case PERF_RECORD_COMM: case PERF_RECORD_COMM:
return curr_handler->process_comm_event(event, offset, head); return curr_handler->process_comm_event(event);
case PERF_RECORD_FORK: case PERF_RECORD_FORK:
return curr_handler->process_fork_event(event, offset, head); return curr_handler->process_fork_event(event);
case PERF_RECORD_EXIT: case PERF_RECORD_EXIT:
return curr_handler->process_exit_event(event, offset, head); return curr_handler->process_exit_event(event);
case PERF_RECORD_LOST: case PERF_RECORD_LOST:
return curr_handler->process_lost_event(event, offset, head); return curr_handler->process_lost_event(event);
case PERF_RECORD_READ: case PERF_RECORD_READ:
return curr_handler->process_read_event(event, offset, head); return curr_handler->process_read_event(event);
case PERF_RECORD_THROTTLE: case PERF_RECORD_THROTTLE:
return curr_handler->process_throttle_event(event, offset, head); return curr_handler->process_throttle_event(event);
case PERF_RECORD_UNTHROTTLE: case PERF_RECORD_UNTHROTTLE:
return curr_handler->process_unthrottle_event(event, offset, head); return curr_handler->process_unthrottle_event(event);
default: default:
curr_handler->total_unknown++; curr_handler->total_unknown++;
return -1; return -1;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include "event.h" #include "event.h"
#include "header.h" #include "header.h"
typedef int (*event_type_handler_t)(event_t *, unsigned long, unsigned long); typedef int (*event_type_handler_t)(event_t *);
struct perf_file_handler { struct perf_file_handler {
event_type_handler_t process_sample_event; event_type_handler_t process_sample_event;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "event.h" #include "event.h"
#include "debug.h" #include "debug.h"
#include "string.h" #include "string.h"
#include "thread.h"
static pid_t event__synthesize_comm(pid_t pid, int full, static pid_t event__synthesize_comm(pid_t pid, int full,
int (*process)(event_t *event)) int (*process)(event_t *event))
...@@ -175,3 +176,76 @@ void event__synthesize_threads(int (*process)(event_t *event)) ...@@ -175,3 +176,76 @@ void event__synthesize_threads(int (*process)(event_t *event))
closedir(proc); closedir(proc);
} }
char *event__cwd;
int event__cwdlen;
struct events_stats event__stats;
int event__process_comm(event_t *self)
{
struct thread *thread = threads__findnew(self->comm.pid);
dump_printf("PERF_RECORD_COMM: %s:%d\n",
self->comm.comm, self->comm.pid);
if (thread == NULL || thread__set_comm(thread, self->comm.comm)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
return -1;
}
return 0;
}
int event__process_lost(event_t *self)
{
dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
event__stats.lost += self->lost.lost;
return 0;
}
int event__process_mmap(event_t *self)
{
struct thread *thread = threads__findnew(self->mmap.pid);
struct map *map = map__new(&self->mmap, MAP__FUNCTION,
event__cwd, event__cwdlen);
dump_printf(" %d/%d: [%p(%p) @ %p]: %s\n",
self->mmap.pid, self->mmap.tid,
(void *)(long)self->mmap.start,
(void *)(long)self->mmap.len,
(void *)(long)self->mmap.pgoff,
self->mmap.filename);
if (thread == NULL || map == NULL)
dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
else
thread__insert_map(thread, map);
return 0;
}
int event__process_task(event_t *self)
{
struct thread *thread = threads__findnew(self->fork.pid);
struct thread *parent = threads__findnew(self->fork.ppid);
dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
self->fork.ppid, self->fork.ptid);
/*
* A thread clone will have the same PID for both parent and child.
*/
if (thread == parent)
return 0;
if (self->header.type == PERF_RECORD_EXIT)
return 0;
if (thread == NULL || parent == NULL ||
thread__fork(thread, parent) < 0) {
dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
return -1;
}
return 0;
}
...@@ -80,6 +80,13 @@ typedef union event_union { ...@@ -80,6 +80,13 @@ typedef union event_union {
struct sample_event sample; struct sample_event sample;
} event_t; } event_t;
struct events_stats {
unsigned long total;
unsigned long lost;
};
void event__print_totals(void);
enum map_type { enum map_type {
MAP__FUNCTION = 0, MAP__FUNCTION = 0,
...@@ -135,4 +142,14 @@ void map__fixup_end(struct map *self); ...@@ -135,4 +142,14 @@ void map__fixup_end(struct map *self);
int event__synthesize_thread(pid_t pid, int (*process)(event_t *event)); int event__synthesize_thread(pid_t pid, int (*process)(event_t *event));
void event__synthesize_threads(int (*process)(event_t *event)); void event__synthesize_threads(int (*process)(event_t *event));
extern char *event__cwd;
extern int event__cwdlen;
extern struct events_stats event__stats;
extern unsigned long event__total[PERF_RECORD_MAX];
int event__process_comm(event_t *self);
int event__process_lost(event_t *self);
int event__process_mmap(event_t *self);
int event__process_task(event_t *self);
#endif /* __PERF_RECORD_H */ #endif /* __PERF_RECORD_H */
...@@ -10,13 +10,6 @@ struct callchain_param callchain_param = { ...@@ -10,13 +10,6 @@ struct callchain_param callchain_param = {
.min_percent = 0.5 .min_percent = 0.5
}; };
unsigned long total;
unsigned long total_mmap;
unsigned long total_comm;
unsigned long total_fork;
unsigned long total_unknown;
unsigned long total_lost;
/* /*
* histogram, sorted on item, collects counts * histogram, sorted on item, collects counts
*/ */
......
#include "process_event.h"
char *cwd;
int cwdlen;
int
process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
{
struct map *map = map__new(&event->mmap, cwd, cwdlen);
struct thread *thread = threads__findnew(event->mmap.pid);
dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->mmap.pid,
event->mmap.tid,
(void *)(long)event->mmap.start,
(void *)(long)event->mmap.len,
(void *)(long)event->mmap.pgoff,
event->mmap.filename);
if (thread == NULL || map == NULL) {
dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
return 0;
}
thread__insert_map(thread, map);
total_mmap++;
return 0;
}
int
process_comm_event(event_t *event, unsigned long offset, unsigned long head)
{
struct thread *thread = threads__findnew(event->comm.pid);
dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
if (thread == NULL ||
thread__set_comm_adjust(thread, event->comm.comm)) {
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
return -1;
}
total_comm++;
return 0;
}
#ifndef __PROCESS_EVENT_H
#define __PROCESS_EVENT_H
#include "../builtin.h"
#include "util.h"
#include "color.h"
#include <linux/list.h>
#include "cache.h"
#include <linux/rbtree.h>
#include "symbol.h"
#include "string.h"
#include "../perf.h"
#include "debug.h"
#include "parse-options.h"
#include "parse-events.h"
#include "thread.h"
#include "sort.h"
#include "hist.h"
extern char *cwd;
extern int cwdlen;
extern int process_mmap_event(event_t *, unsigned long, unsigned long);
extern int process_comm_event(event_t *, unsigned long , unsigned long);
#endif /* __PROCESS_H */
#include "process_events.h"
char *cwd;
int cwdlen;
int
process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
{
struct map *map = map__new(&event->mmap, MAP__FUNCTION, cwd, cwdlen);
struct thread *thread = threads__findnew(event->mmap.pid);
dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->mmap.pid,
event->mmap.tid,
(void *)(long)event->mmap.start,
(void *)(long)event->mmap.len,
(void *)(long)event->mmap.pgoff,
event->mmap.filename);
if (thread == NULL || map == NULL) {
dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
return 0;
}
thread__insert_map(thread, map);
total_mmap++;
return 0;
}
int
process_task_event(event_t *event, unsigned long offset, unsigned long head)
{
struct thread *thread = threads__findnew(event->fork.pid);
struct thread *parent = threads__findnew(event->fork.ppid);
dump_printf("%p [%p]: PERF_RECORD_%s: (%d:%d):(%d:%d)\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.type == PERF_RECORD_FORK ? "FORK" : "EXIT",
event->fork.pid, event->fork.tid,
event->fork.ppid, event->fork.ptid);
/*
* A thread clone will have the same PID for both
* parent and child.
*/
if (thread == parent)
return 0;
if (event->header.type == PERF_RECORD_EXIT)
return 0;
if (!thread || !parent || thread__fork(thread, parent)) {
dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
return -1;
}
total_fork++;
return 0;
}
#ifndef __PROCESS_EVENTS_H
#define __PROCESS_EVENTS_H
#include "../builtin.h"
#include "util.h"
#include "color.h"
#include <linux/list.h>
#include "cache.h"
#include <linux/rbtree.h>
#include "symbol.h"
#include "string.h"
#include "callchain.h"
#include "strlist.h"
#include "values.h"
#include "../perf.h"
#include "debug.h"
#include "header.h"
#include "parse-options.h"
#include "parse-events.h"
#include "data_map.h"
#include "thread.h"
#include "sort.h"
#include "hist.h"
extern char *cwd;
extern int cwdlen;
extern int process_mmap_event(event_t *, unsigned long , unsigned long);
extern int process_task_event(event_t *, unsigned long, unsigned long);
#endif /* __PROCESS_EVENTS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment