From cd84c2ac6d6425dd4d1b80a2231e534b9b03df18 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 12 Aug 2009 10:03:49 +0200 Subject: perf tools: Factorize high level dso helpers Factorize multiple definitions of high level dso helpers into the symbol source file. The side effect is a general export of the verbose and eprintf debugging helpers into a new file dedicated to debugging purposes. Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Brice Goglin --- tools/perf/builtin-record.c | 1 - 1 file changed, 1 deletion(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0345aad8eba5..afae3873b47c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -40,7 +40,6 @@ static int inherit = 1; static int force = 0; static int append_file = 0; static int call_graph = 0; -static int verbose = 0; static int inherit_stat = 0; static int no_samples = 0; static int sample_address = 0; -- cgit v1.2.3 From 1fe2c1066ce6a30bda7b27785ee3d9b8e62ffbbd Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 12 Aug 2009 10:19:53 +0200 Subject: perf tools: Factorize the event structure definitions in a single file Factorize the multiple definition of the events structures into a single util/event.h file. Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Brice Goglin --- tools/perf/builtin-annotate.c | 34 --------------------------- tools/perf/builtin-record.c | 18 --------------- tools/perf/builtin-report.c | 53 ------------------------------------------ tools/perf/builtin-top.c | 20 ---------------- tools/perf/util/event.h | 54 +++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/util.h | 2 ++ 6 files changed, 56 insertions(+), 125 deletions(-) create mode 100644 tools/perf/util/event.h (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 1a792990031a..fee663adeea2 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -44,40 +44,6 @@ static int print_line; static unsigned long page_size; static unsigned long mmap_window = 32; -struct ip_event { - struct perf_event_header header; - u64 ip; - u32 pid, tid; -}; - -struct mmap_event { - struct perf_event_header header; - u32 pid, tid; - u64 start; - u64 len; - u64 pgoff; - char filename[PATH_MAX]; -}; - -struct comm_event { - struct perf_event_header header; - u32 pid, tid; - char comm[16]; -}; - -struct fork_event { - struct perf_event_header header; - u32 pid, ppid; -}; - -typedef union event_union { - struct perf_event_header header; - struct ip_event ip; - struct mmap_event mmap; - struct comm_event comm; - struct fork_event fork; -} event_t; - struct sym_ext { struct rb_node node; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index afae3873b47c..718b8f7b6aac 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -59,24 +59,6 @@ static int file_new = 1; struct perf_header *header; -struct mmap_event { - struct perf_event_header header; - u32 pid; - u32 tid; - u64 start; - u64 len; - u64 pgoff; - char filename[PATH_MAX]; -}; - -struct comm_event { - struct perf_event_header header; - u32 pid; - u32 tid; - char comm[16]; -}; - - struct mmap_data { int counter; void *base; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 827eab2edf4b..1efefcc2ffdf 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -75,59 +75,6 @@ struct callchain_param callchain_param = { static u64 sample_type; -struct ip_event { - struct perf_event_header header; - u64 ip; - u32 pid, tid; - unsigned char __more_data[]; -}; - -struct mmap_event { - struct perf_event_header header; - u32 pid, tid; - u64 start; - u64 len; - u64 pgoff; - char filename[PATH_MAX]; -}; - -struct comm_event { - struct perf_event_header header; - u32 pid, tid; - char comm[16]; -}; - -struct fork_event { - struct perf_event_header header; - u32 pid, ppid; - u32 tid, ptid; -}; - -struct lost_event { - struct perf_event_header header; - u64 id; - u64 lost; -}; - -struct read_event { - struct perf_event_header header; - u32 pid,tid; - u64 value; - u64 time_enabled; - u64 time_running; - u64 id; -}; - -typedef union event_union { - struct perf_event_header header; - struct ip_event ip; - struct mmap_event mmap; - struct comm_event comm; - struct fork_event fork; - struct lost_event lost; - struct read_event read; -} event_t; - static int repsep_fprintf(FILE *fp, const char *fmt, ...) { int n; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 0aa567371bd3..9a6dbbff9a9f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -933,26 +933,6 @@ static void mmap_read_counter(struct mmap_data *md) last_read = this_read; for (; old != head;) { - struct ip_event { - struct perf_event_header header; - u64 ip; - u32 pid, target_pid; - }; - struct mmap_event { - struct perf_event_header header; - u32 pid, target_pid; - u64 start; - u64 len; - u64 pgoff; - char filename[PATH_MAX]; - }; - - typedef union event_union { - struct perf_event_header header; - struct ip_event ip; - struct mmap_event mmap; - } event_t; - event_t *event = (event_t *)&data[old & md->mask]; event_t event_copy; diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h new file mode 100644 index 000000000000..91e2fe589f27 --- /dev/null +++ b/tools/perf/util/event.h @@ -0,0 +1,54 @@ +#include "../perf.h" + +struct ip_event { + struct perf_event_header header; + u64 ip; + u32 pid, tid; + unsigned char __more_data[]; +}; + +struct mmap_event { + struct perf_event_header header; + u32 pid, tid; + u64 start; + u64 len; + u64 pgoff; + char filename[PATH_MAX]; +}; + +struct comm_event { + struct perf_event_header header; + u32 pid, tid; + char comm[16]; +}; + +struct fork_event { + struct perf_event_header header; + u32 pid, ppid; + u32 tid, ptid; +}; + +struct lost_event { + struct perf_event_header header; + u64 id; + u64 lost; +}; + +struct read_event { + struct perf_event_header header; + u32 pid,tid; + u64 value; + u64 time_enabled; + u64 time_running; + u64 id; +}; + +typedef union event_union { + struct perf_event_header header; + struct ip_event ip; + struct mmap_event mmap; + struct comm_event comm; + struct fork_event fork; + struct lost_event lost; + struct read_event read; +} event_t; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 68fe157d72fb..be4b52cca2c3 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -83,6 +83,8 @@ #include #include "../../../include/linux/magic.h" +#include "event.h" + #ifndef NO_ICONV #include #endif -- cgit v1.2.3 From 66e274f3b8d7fc89d38997e85b900e188f8d5cc0 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 12 Aug 2009 11:07:25 +0200 Subject: perf tools: Factorize the map helpers Factorize the dso mapping helpers into a single purpose common file "util/map.c" Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Brice Goglin --- tools/perf/Makefile | 1 + tools/perf/builtin-annotate.c | 79 +-------------------------- tools/perf/builtin-record.c | 1 + tools/perf/builtin-report.c | 124 ++---------------------------------------- tools/perf/util/callchain.h | 1 + tools/perf/util/event.h | 30 ++++++++++ tools/perf/util/map.c | 97 +++++++++++++++++++++++++++++++++ tools/perf/util/symbol.h | 1 + tools/perf/util/util.h | 1 - 9 files changed, 137 insertions(+), 198 deletions(-) create mode 100644 tools/perf/util/map.c (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 2aee21baf785..cb9033d3f72f 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -340,6 +340,7 @@ LIB_OBJS += util/header.o LIB_OBJS += util/callchain.o LIB_OBJS += util/values.o LIB_OBJS += util/debug.o +LIB_OBJS += util/map.o BUILTIN_OBJS += builtin-annotate.o BUILTIN_OBJS += builtin-help.o diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index fee663adeea2..543c4524f8c2 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -51,83 +51,6 @@ struct sym_ext { char *path; }; -struct map { - struct list_head node; - u64 start; - u64 end; - u64 pgoff; - u64 (*map_ip)(struct map *, u64); - struct dso *dso; -}; - -static u64 map__map_ip(struct map *map, u64 ip) -{ - return ip - map->start + map->pgoff; -} - -static u64 vdso__map_ip(struct map *map __used, u64 ip) -{ - return ip; -} - -static struct map *map__new(struct mmap_event *event) -{ - struct map *self = malloc(sizeof(*self)); - - if (self != NULL) { - const char *filename = event->filename; - - self->start = event->start; - self->end = event->start + event->len; - self->pgoff = event->pgoff; - - self->dso = dsos__findnew(filename); - if (self->dso == NULL) - goto out_delete; - - if (self->dso == vdso) - self->map_ip = vdso__map_ip; - else - self->map_ip = map__map_ip; - } - return self; -out_delete: - free(self); - return NULL; -} - -static struct map *map__clone(struct map *self) -{ - struct map *map = malloc(sizeof(*self)); - - if (!map) - return NULL; - - memcpy(map, self, sizeof(*self)); - - return map; -} - -static int map__overlap(struct map *l, struct map *r) -{ - if (l->start > r->start) { - struct map *t = l; - l = r; - r = t; - } - - if (l->end > r->start) - return 1; - - return 0; -} - -static size_t map__fprintf(struct map *self, FILE *fp) -{ - return fprintf(fp, " %Lx-%Lx %Lx %s\n", - self->start, self->end, self->pgoff, self->dso->name); -} - struct thread { struct rb_node rb_node; @@ -797,7 +720,7 @@ static int process_mmap_event(event_t *event, unsigned long offset, unsigned long head) { struct thread *thread = threads__findnew(event->mmap.pid); - struct map *map = map__new(&event->mmap); + struct map *map = map__new(&event->mmap, NULL, 0); dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", (void *)(offset + head), diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 718b8f7b6aac..106c6abd1c38 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -15,6 +15,7 @@ #include "util/string.h" #include "util/header.h" +#include "util/event.h" #include #include diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1efefcc2ffdf..93945ecdac86 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -67,6 +67,10 @@ static char callchain_default_opt[] = "fractal,0.5"; static int callchain; +static char __cwd[PATH_MAX]; +static char *cwd = __cwd; +static int cwdlen; + static struct callchain_param callchain_param = { .mode = CHAIN_GRAPH_REL, @@ -102,124 +106,6 @@ static int repsep_fprintf(FILE *fp, const char *fmt, ...) return n; } - - -static char __cwd[PATH_MAX]; -static char *cwd = __cwd; -static int cwdlen; - -static int strcommon(const char *pathname) -{ - int n = 0; - - while (n < cwdlen && pathname[n] == cwd[n]) - ++n; - - return n; -} - -struct map { - struct list_head node; - u64 start; - u64 end; - u64 pgoff; - u64 (*map_ip)(struct map *, u64); - struct dso *dso; -}; - -static u64 map__map_ip(struct map *map, u64 ip) -{ - return ip - map->start + map->pgoff; -} - -static u64 vdso__map_ip(struct map *map __used, u64 ip) -{ - return ip; -} - -static inline int is_anon_memory(const char *filename) -{ - return strcmp(filename, "//anon") == 0; -} - -static struct map *map__new(struct mmap_event *event) -{ - struct map *self = malloc(sizeof(*self)); - - if (self != NULL) { - const char *filename = event->filename; - char newfilename[PATH_MAX]; - int anon; - - if (cwd) { - int n = strcommon(filename); - - if (n == cwdlen) { - snprintf(newfilename, sizeof(newfilename), - ".%s", filename + n); - filename = newfilename; - } - } - - anon = is_anon_memory(filename); - - if (anon) { - snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); - filename = newfilename; - } - - self->start = event->start; - self->end = event->start + event->len; - self->pgoff = event->pgoff; - - self->dso = dsos__findnew(filename); - if (self->dso == NULL) - goto out_delete; - - if (self->dso == vdso || anon) - self->map_ip = vdso__map_ip; - else - self->map_ip = map__map_ip; - } - return self; -out_delete: - free(self); - return NULL; -} - -static struct map *map__clone(struct map *self) -{ - struct map *map = malloc(sizeof(*self)); - - if (!map) - return NULL; - - memcpy(map, self, sizeof(*self)); - - return map; -} - -static int map__overlap(struct map *l, struct map *r) -{ - if (l->start > r->start) { - struct map *t = l; - l = r; - r = t; - } - - if (l->end > r->start) - return 1; - - return 0; -} - -static size_t map__fprintf(struct map *self, FILE *fp) -{ - return fprintf(fp, " %Lx-%Lx %Lx %s\n", - self->start, self->end, self->pgoff, self->dso->name); -} - - struct thread { struct rb_node rb_node; struct list_head maps; @@ -1474,7 +1360,7 @@ static int process_mmap_event(event_t *event, unsigned long offset, unsigned long head) { struct thread *thread = threads__findnew(event->mmap.pid); - struct map *map = map__new(&event->mmap); + struct map *map = map__new(&event->mmap, cwd, cwdlen); dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", (void *)(offset + head), diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index a926ae4f5a16..43cf3ea9e088 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -4,6 +4,7 @@ #include "../perf.h" #include #include +#include "util.h" #include "symbol.h" enum chain_mode { diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 91e2fe589f27..d26dc887ce52 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -1,4 +1,8 @@ +#ifndef __PERF_EVENT_H +#define __PERF_EVENT_H #include "../perf.h" +#include "util.h" +#include struct ip_event { struct perf_event_header header; @@ -52,3 +56,29 @@ typedef union event_union { struct lost_event lost; struct read_event read; } event_t; + +struct map { + struct list_head node; + u64 start; + u64 end; + u64 pgoff; + u64 (*map_ip)(struct map *, u64); + struct dso *dso; +}; + +static inline u64 map__map_ip(struct map *map, u64 ip) +{ + return ip - map->start + map->pgoff; +} + +static inline u64 vdso__map_ip(struct map *map __used, u64 ip) +{ + return ip; +} + +struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen); +struct map *map__clone(struct map *self); +int map__overlap(struct map *l, struct map *r); +size_t map__fprintf(struct map *self, FILE *fp); + +#endif diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c new file mode 100644 index 000000000000..804e02382739 --- /dev/null +++ b/tools/perf/util/map.c @@ -0,0 +1,97 @@ +#include "event.h" +#include "symbol.h" +#include +#include +#include + +static inline int is_anon_memory(const char *filename) +{ + return strcmp(filename, "//anon") == 0; +} + +static int strcommon(const char *pathname, char *cwd, int cwdlen) +{ + int n = 0; + + while (n < cwdlen && pathname[n] == cwd[n]) + ++n; + + return n; +} + + struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) +{ + struct map *self = malloc(sizeof(*self)); + + if (self != NULL) { + const char *filename = event->filename; + char newfilename[PATH_MAX]; + int anon; + + if (cwd) { + int n = strcommon(filename, cwd, cwdlen); + + if (n == cwdlen) { + snprintf(newfilename, sizeof(newfilename), + ".%s", filename + n); + filename = newfilename; + } + } + + anon = is_anon_memory(filename); + + if (anon) { + snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); + filename = newfilename; + } + + self->start = event->start; + self->end = event->start + event->len; + self->pgoff = event->pgoff; + + self->dso = dsos__findnew(filename); + if (self->dso == NULL) + goto out_delete; + + if (self->dso == vdso || anon) + self->map_ip = vdso__map_ip; + else + self->map_ip = map__map_ip; + } + return self; +out_delete: + free(self); + return NULL; +} + +struct map *map__clone(struct map *self) +{ + struct map *map = malloc(sizeof(*self)); + + if (!map) + return NULL; + + memcpy(map, self, sizeof(*self)); + + return map; +} + +int map__overlap(struct map *l, struct map *r) +{ + if (l->start > r->start) { + struct map *t = l; + l = r; + r = t; + } + + if (l->end > r->start) + return 1; + + return 0; +} + +size_t map__fprintf(struct map *self, FILE *fp) +{ + return fprintf(fp, " %Lx-%Lx %Lx %s\n", + self->start, self->end, self->pgoff, self->dso->name); +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index f3490fcd40ee..50f723571241 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -6,6 +6,7 @@ #include #include #include "module.h" +#include "event.h" struct symbol { struct rb_node rb_node; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index be4b52cca2c3..d61a6f037631 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -83,7 +83,6 @@ #include #include "../../../include/linux/magic.h" -#include "event.h" #ifndef NO_ICONV #include -- cgit v1.2.3 From 8f28827a162fd1e8da4e96bed69b06d2606e8322 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 16 Aug 2009 22:05:48 +0200 Subject: perf tools: Librarize trace_event() helper Librarize trace_event() helper so that perf trace can use it too. Also clean up the debug.h includes a bit. It's not good to have it included in perf.h because it doesn't make it flexible against other headers it may need (headers that can also depend on perf.h and then create a recursive header dependency). Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Mike Galbraith LKML-Reference: <1250453149-664-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar --- tools/perf/builtin-annotate.c | 1 + tools/perf/builtin-record.c | 1 + tools/perf/builtin-report.c | 39 +---------------------------- tools/perf/builtin-stat.c | 2 ++ tools/perf/builtin-top.c | 2 ++ tools/perf/perf.h | 1 - tools/perf/util/color.c | 10 +++++--- tools/perf/util/color.h | 1 + tools/perf/util/debug.c | 58 +++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/debug.h | 1 + tools/perf/util/symbol.c | 2 ++ 11 files changed, 76 insertions(+), 42 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6d751516616d..96d421f7161d 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -17,6 +17,7 @@ #include "util/string.h" #include "perf.h" +#include "util/debug.h" #include "util/parse-options.h" #include "util/parse-events.h" diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 65b4115e417d..6a5db675ee4f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -16,6 +16,7 @@ #include "util/header.h" #include "util/event.h" +#include "util/debug.h" #include #include diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c6326deb1636..1e3ad22d53dc 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -20,6 +20,7 @@ #include "util/values.h" #include "perf.h" +#include "util/debug.h" #include "util/header.h" #include "util/parse-options.h" @@ -39,8 +40,6 @@ static char *field_sep; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; -#define cdprintf(x...) do { if (dump_trace) color_fprintf(stdout, color, x); } while (0) - static int full_paths; static int show_nr_samples; @@ -1285,42 +1284,6 @@ process_lost_event(event_t *event, unsigned long offset, unsigned long head) return 0; } -static void trace_event(event_t *event) -{ - unsigned char *raw_event = (void *)event; - const char *color = PERF_COLOR_BLUE; - int i, j; - - if (!dump_trace) - return; - - dump_printf("."); - cdprintf("\n. ... raw event: size %d bytes\n", event->header.size); - - for (i = 0; i < event->header.size; i++) { - if ((i & 15) == 0) { - dump_printf("."); - cdprintf(" %04x: ", i); - } - - cdprintf(" %02x", raw_event[i]); - - if (((i & 15) == 15) || i == event->header.size-1) { - cdprintf(" "); - for (j = 0; j < 15-(i & 15); j++) - cdprintf(" "); - for (j = 0; j < (i & 15); j++) { - if (isprint(raw_event[i-15+j])) - cdprintf("%c", raw_event[i-15+j]); - else - cdprintf("."); - } - cdprintf("\n"); - } - } - dump_printf(".\n"); -} - static int process_read_event(event_t *event, unsigned long offset, unsigned long head) { diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 4b9dd4af61a6..1a2626230660 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -42,6 +42,8 @@ #include "util/util.h" #include "util/parse-options.h" #include "util/parse-events.h" +#include "util/event.h" +#include "util/debug.h" #include #include diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 06f763e4b35b..62b55ecab2c6 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -27,6 +27,8 @@ #include "util/parse-options.h" #include "util/parse-events.h" +#include "util/debug.h" + #include #include diff --git a/tools/perf/perf.h b/tools/perf/perf.h index f5509213f030..e5148e2b6134 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -48,7 +48,6 @@ #include "../../include/linux/perf_counter.h" #include "util/types.h" -#include "util/debug.h" /* * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index e47fdeb85391..e88bca55a599 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -166,7 +166,7 @@ int perf_color_default_config(const char *var, const char *value, void *cb) return perf_default_config(var, value, cb); } -static int color_vfprintf(FILE *fp, const char *color, const char *fmt, +static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args, const char *trail) { int r = 0; @@ -191,6 +191,10 @@ static int color_vfprintf(FILE *fp, const char *color, const char *fmt, return r; } +int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) +{ + return __color_vfprintf(fp, color, fmt, args, NULL); +} int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) @@ -199,7 +203,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) int r; va_start(args, fmt); - r = color_vfprintf(fp, color, fmt, args, NULL); + r = color_vfprintf(fp, color, fmt, args); va_end(args); return r; } @@ -209,7 +213,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) va_list args; int r; va_start(args, fmt); - r = color_vfprintf(fp, color, fmt, args, "\n"); + r = __color_vfprintf(fp, color, fmt, args, "\n"); va_end(args); return r; } diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index 43d0d1b67c45..58d597564b99 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h @@ -32,6 +32,7 @@ int perf_color_default_config(const char *var, const char *value, void *cb); int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty); void color_parse(const char *value, const char *var, char *dst); void color_parse_mem(const char *value, int len, const char *var, char *dst); +int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 8318fdee4778..e8ca98fe0bd4 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c @@ -1,10 +1,15 @@ /* For general debugging purposes */ #include "../perf.h" + #include #include #include +#include "color.h" +#include "event.h" +#include "debug.h" + int verbose = 0; int dump_trace = 0; @@ -35,3 +40,56 @@ int dump_printf(const char *fmt, ...) return ret; } + +static int dump_printf_color(const char *fmt, const char *color, ...) +{ + va_list args; + int ret = 0; + + if (dump_trace) { + va_start(args, color); + ret = color_vfprintf(stdout, color, fmt, args); + va_end(args); + } + + return ret; +} + + +void trace_event(event_t *event) +{ + unsigned char *raw_event = (void *)event; + const char *color = PERF_COLOR_BLUE; + int i, j; + + if (!dump_trace) + return; + + dump_printf("."); + dump_printf_color("\n. ... raw event: size %d bytes\n", color, + event->header.size); + + for (i = 0; i < event->header.size; i++) { + if ((i & 15) == 0) { + dump_printf("."); + dump_printf_color(" %04x: ", color, i); + } + + dump_printf_color(" %02x", color, raw_event[i]); + + if (((i & 15) == 15) || i == event->header.size-1) { + dump_printf_color(" ", color); + for (j = 0; j < 15-(i & 15); j++) + dump_printf_color(" ", color); + for (j = 0; j < (i & 15); j++) { + if (isprint(raw_event[i-15+j])) + dump_printf_color("%c", color, + raw_event[i-15+j]); + else + dump_printf_color(".", color); + } + dump_printf_color("\n", color); + } + } + dump_printf(".\n"); +} diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index a683bd571f1c..437eea58ce40 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -5,3 +5,4 @@ extern int dump_trace; int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +void trace_event(event_t *event); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3159d47ae1cc..fd3d9c8e90fc 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -3,6 +3,8 @@ #include "string.h" #include "symbol.h" +#include "debug.h" + #include #include #include -- cgit v1.2.3 From 5f9c39dca52d3e639ac899e169f408c6fd8396cc Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 17 Aug 2009 16:18:08 +0200 Subject: perf tools: Add perf trace This adds perf trace into the set of perf tools. It is written to fetch the tracepoint samples from perf events and display them, according to the events information given by the debugfs files through the util/trace* tools. It is a rough first shot and doesn't yet handle the cpu, timestamps fields and some other things. Example: perf record -f -e workqueue:workqueue_execution:record -F 1 -a perf trace kblockd/0-236 [000] 0.000000: workqueue_execution: thread=:236 func=cfq_kick_queue+0x0 kondemand/0-360 [000] 0.000000: workqueue_execution: thread=:360 func=do_dbs_timer+0x0 kondemand/0-360 [000] 0.000000: workqueue_execution: thread=:360 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 kondemand/1-361 [000] 0.000000: workqueue_execution: thread=:361 func=do_dbs_timer+0x0 Todo: - A lot of things! Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Mike Galbraith Cc: "Luis Claudio R. Goncalves" Cc: Clark Williams Cc: Jon Masters Cc: Mathieu Desnoyers Cc: Christoph Hellwig Cc: Xiao Guangrong Cc: Zhaolei Cc: Li Zefan Cc: Lai Jiangshan Cc: Masami Hiramatsu Cc: Tom Zanussi Cc: "Frank Ch. Eigler" Cc: Roland McGrath Cc: Jason Baron Cc: Paul Mackerras Cc: Jiaying Zhang Cc: Anton Blanchard LKML-Reference: <1250518688-7207-4-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar --- tools/perf/Makefile | 4 + tools/perf/builtin-record.c | 4 + tools/perf/builtin-trace.c | 277 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/perf.c | 1 + tools/perf/util/util.h | 1 + 5 files changed, 287 insertions(+) create mode 100644 tools/perf/builtin-trace.c (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 5d54ddb83ab1..c481a513f551 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -347,6 +347,9 @@ LIB_OBJS += util/values.o LIB_OBJS += util/debug.o LIB_OBJS += util/map.o LIB_OBJS += util/thread.o +LIB_OBJS += util/trace-event-parse.o +LIB_OBJS += util/trace-event-read.o +LIB_OBJS += util/trace-event-info.o BUILTIN_OBJS += builtin-annotate.o BUILTIN_OBJS += builtin-help.o @@ -355,6 +358,7 @@ BUILTIN_OBJS += builtin-record.o BUILTIN_OBJS += builtin-report.o BUILTIN_OBJS += builtin-stat.o BUILTIN_OBJS += builtin-top.o +BUILTIN_OBJS += builtin-trace.o PERFLIBS = $(LIB_FILE) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 6a5db675ee4f..3ce2f03f217a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -17,6 +17,7 @@ #include "util/header.h" #include "util/event.h" #include "util/debug.h" +#include "util/trace-event.h" #include #include @@ -519,6 +520,9 @@ static int __cmd_record(int argc, const char **argv) signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); + if (raw_samples) + read_tracing_data(); + if (!stat(output_name, &st) && st.st_size) { if (!force && !append_file) { fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c new file mode 100644 index 000000000000..b160a9f61bf3 --- /dev/null +++ b/tools/perf/builtin-trace.c @@ -0,0 +1,277 @@ +#include "builtin.h" + +#include "util/util.h" +#include "util/cache.h" +#include "util/symbol.h" +#include "util/thread.h" +#include "util/header.h" + +#include "util/parse-options.h" + +#include "perf.h" +#include "util/debug.h" + +#include "util/trace-event.h" + +static char const *input_name = "perf.data"; +static int input; +static unsigned long page_size; +static unsigned long mmap_window = 32; + +static unsigned long total = 0; +static unsigned long total_comm = 0; + +static struct rb_root threads; +static struct thread *last_match; + +static struct perf_header *header; +static u64 sample_type; + + +static int +process_comm_event(event_t *event, unsigned long offset, unsigned long head) +{ + struct thread *thread; + + thread = threads__findnew(event->comm.pid, &threads, &last_match); + + 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; +} + +static int +process_sample_event(event_t *event, unsigned long offset, unsigned long head) +{ + char level; + int show = 0; + struct dso *dso = NULL; + struct thread *thread; + u64 ip = event->ip.ip; + u64 period = 1; + void *more_data = event->ip.__more_data; + int cpumode; + + thread = threads__findnew(event->ip.pid, &threads, &last_match); + + if (sample_type & PERF_SAMPLE_PERIOD) { + period = *(u64 *)more_data; + more_data += sizeof(u64); + } + + dump_printf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n", + (void *)(offset + head), + (void *)(long)(event->header.size), + event->header.misc, + event->ip.pid, event->ip.tid, + (void *)(long)ip, + (long long)period); + + dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); + + if (thread == NULL) { + eprintf("problem processing %d event, skipping it.\n", + event->header.type); + return -1; + } + + cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK; + + if (cpumode == PERF_EVENT_MISC_KERNEL) { + show = SHOW_KERNEL; + level = 'k'; + + dso = kernel_dso; + + dump_printf(" ...... dso: %s\n", dso->name); + + } else if (cpumode == PERF_EVENT_MISC_USER) { + + show = SHOW_USER; + level = '.'; + + } else { + show = SHOW_HV; + level = 'H'; + + dso = hypervisor_dso; + + dump_printf(" ...... dso: [hypervisor]\n"); + } + + 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 + */ + print_event(0, raw->data, raw->size, 0, thread->comm); + } + total += period; + + return 0; +} + +static int +process_event(event_t *event, unsigned long offset, unsigned long head) +{ + trace_event(event); + + switch (event->header.type) { + case PERF_EVENT_MMAP ... PERF_EVENT_LOST: + return 0; + + case PERF_EVENT_COMM: + return process_comm_event(event, offset, head); + + case PERF_EVENT_EXIT ... PERF_EVENT_READ: + return 0; + + case PERF_EVENT_SAMPLE: + return process_sample_event(event, offset, head); + + case PERF_EVENT_MAX: + default: + return -1; + } + + return 0; +} + +static int __cmd_trace(void) +{ + int ret, rc = EXIT_FAILURE; + unsigned long offset = 0; + unsigned long head = 0; + struct stat perf_stat; + event_t *event; + uint32_t size; + char *buf; + + trace_report(); + + input = open(input_name, O_RDONLY); + if (input < 0) { + perror("failed to open file"); + exit(-1); + } + + ret = fstat(input, &perf_stat); + if (ret < 0) { + perror("failed to stat file"); + exit(-1); + } + + if (!perf_stat.st_size) { + fprintf(stderr, "zero-sized file, nothing to do!\n"); + exit(0); + } + header = perf_header__read(input); + sample_type = perf_header__sample_type(header); + + if (load_kernel() < 0) { + perror("failed to load kernel symbols"); + return EXIT_FAILURE; + } + +remap: + buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, + MAP_SHARED, input, offset); + if (buf == MAP_FAILED) { + perror("failed to mmap file"); + exit(-1); + } + +more: + event = (event_t *)(buf + head); + + size = event->header.size; + if (!size) + size = 8; + + if (head + event->header.size >= page_size * mmap_window) { + unsigned long shift = page_size * (head / page_size); + int res; + + res = munmap(buf, page_size * mmap_window); + assert(res == 0); + + offset += shift; + head -= shift; + goto remap; + } + + size = event->header.size; + + + if (!size || process_event(event, offset, head) < 0) { + + /* + * assume we lost track of the stream, check alignment, and + * increment a single u64 in the hope to catch on again 'soon'. + */ + + if (unlikely(head & 7)) + head &= ~7ULL; + + size = 8; + } + + head += size; + + if (offset + head < (unsigned long)perf_stat.st_size) + goto more; + + rc = EXIT_SUCCESS; + close(input); + + return rc; +} + +static const char * const annotate_usage[] = { + "perf trace [] ", + NULL +}; + +static const struct option options[] = { + OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, + "dump raw trace in ASCII"), + OPT_BOOLEAN('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), +}; + +int cmd_trace(int argc, const char **argv, const char *prefix __used) +{ + symbol__init(); + page_size = getpagesize(); + + argc = parse_options(argc, argv, options, annotate_usage, 0); + if (argc) { + /* + * Special case: if there's an argument left then assume tha + * it's a symbol filter: + */ + if (argc > 1) + usage_with_options(annotate_usage, options); + } + + + setup_pager(); + + return __cmd_trace(); +} diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 31982ad064b4..fe4589dde950 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -292,6 +292,7 @@ static void handle_internal_command(int argc, const char **argv) { "top", cmd_top, 0 }, { "annotate", cmd_annotate, 0 }, { "version", cmd_version, 0 }, + { "trace", cmd_trace, 0 }, }; unsigned int i; static const char ext[] = STRIP_EXTENSION; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index d61a6f037631..c62ef9720c6a 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -311,6 +311,7 @@ static inline int has_extension(const char *filename, const char *ext) #undef isspace #undef isdigit #undef isalpha +#undef isprint #undef isalnum #undef tolower #undef toupper -- cgit v1.2.3 From 9df37ddd81f54dd41dc4958055c3a3c9b6840aef Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 17 Aug 2009 23:07:50 +0200 Subject: perf tools: Record events info also when :record suffix is used. You can enable a counter's PERF_SAMPLE_RAW attribute in two fashions: - using the -R option (every counters get PERF_SAMPLE_RAW) - using the :record suffix in a trace event counter name Currently we record the events info in a trace.info file from perf record when the former method is used but we omit it with the latter. Check both situations. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Mike Galbraith Cc: Steven Rostedt LKML-Reference: <1250543271-8383-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar --- tools/perf/builtin-record.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 3ce2f03f217a..acbe59444385 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -520,9 +520,6 @@ static int __cmd_record(int argc, const char **argv) signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); - if (raw_samples) - read_tracing_data(); - if (!stat(output_name, &st) && st.st_size) { if (!force && !append_file) { fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", @@ -550,6 +547,17 @@ static int __cmd_record(int argc, const char **argv) else header = perf_header__new(); + + if (raw_samples) { + read_tracing_data(); + } else { + for (i = 0; i < nr_counters; i++) { + if (attrs[i].sample_type & PERF_SAMPLE_RAW) { + read_tracing_data(); + break; + } + } + } atexit(atexit_header); if (!system_wide) { -- cgit v1.2.3 From 1ef2ed1066ae9f8080cd96cba11c2d41118b8792 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 28 Aug 2009 03:09:58 +0200 Subject: perf tools: Only save the event formats we need While opening a trace event counter, every events are saved in the trace.info file. But we only want to save the specifications of the events we are using. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Steven Rostedt LKML-Reference: <1251421798-9101-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar --- tools/perf/builtin-record.c | 4 +-- tools/perf/util/parse-events.c | 47 +++++++++++++++++++----- tools/perf/util/parse-events.h | 13 ++++++- tools/perf/util/trace-event-info.c | 72 ++++++++++++++++++++++++++++++------- tools/perf/util/trace-event-parse.c | 1 + tools/perf/util/trace-event-read.c | 1 + tools/perf/util/trace-event.h | 9 ++--- 7 files changed, 120 insertions(+), 27 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index acbe59444385..add514d53d2e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -549,11 +549,11 @@ static int __cmd_record(int argc, const char **argv) if (raw_samples) { - read_tracing_data(); + read_tracing_data(attrs, nr_counters); } else { for (i = 0; i < nr_counters; i++) { if (attrs[i].sample_type & PERF_SAMPLE_RAW) { - read_tracing_data(); + read_tracing_data(attrs, nr_counters); break; } } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 1cda97b39118..89d46c99bc9c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -158,9 +158,9 @@ int valid_debugfs_mount(const char *debugfs) return 0; } -static const char *tracepoint_id_to_name(u64 config) +struct tracepoint_path *tracepoint_id_to_path(u64 config) { - static char tracepoint_name[2 * MAX_EVENT_LENGTH]; + struct tracepoint_path *path = NULL; DIR *sys_dir, *evt_dir; struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; struct stat st; @@ -170,7 +170,7 @@ static const char *tracepoint_id_to_name(u64 config) char evt_path[MAXPATHLEN]; if (valid_debugfs_mount(debugfs_path)) - return "unkown"; + return NULL; sys_dir = opendir(debugfs_path); if (!sys_dir) @@ -197,10 +197,23 @@ static const char *tracepoint_id_to_name(u64 config) if (id == config) { closedir(evt_dir); closedir(sys_dir); - snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH, - "%s:%s", sys_dirent.d_name, - evt_dirent.d_name); - return tracepoint_name; + path = calloc(1, sizeof(path)); + path->system = malloc(MAX_EVENT_LENGTH); + if (!path->system) { + free(path); + return NULL; + } + path->name = malloc(MAX_EVENT_LENGTH); + if (!path->name) { + free(path->system); + free(path); + return NULL; + } + strncpy(path->system, sys_dirent.d_name, + MAX_EVENT_LENGTH); + strncpy(path->name, evt_dirent.d_name, + MAX_EVENT_LENGTH); + return path; } } closedir(evt_dir); @@ -208,7 +221,25 @@ static const char *tracepoint_id_to_name(u64 config) cleanup: closedir(sys_dir); - return "unkown"; + return NULL; +} + +#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1) +static const char *tracepoint_id_to_name(u64 config) +{ + static char buf[TP_PATH_LEN]; + struct tracepoint_path *path; + + path = tracepoint_id_to_path(config); + if (path) { + snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name); + free(path->name); + free(path->system); + free(path); + } else + snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown"); + + return buf; } static int is_cache_op_valid(u8 cache_type, u8 cache_op) diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 9b1aeea01636..60704c15961f 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -1,10 +1,19 @@ - +#ifndef _PARSE_EVENTS_H +#define _PARSE_EVENTS_H /* * Parse symbolic events/counts passed in as options: */ struct option; +struct tracepoint_path { + char *system; + char *name; + struct tracepoint_path *next; +}; + +extern struct tracepoint_path *tracepoint_id_to_path(u64 config); + extern int nr_counters; extern struct perf_counter_attr attrs[MAX_COUNTERS]; @@ -21,3 +30,5 @@ extern void print_events(void); extern char debugfs_path[]; extern int valid_debugfs_mount(const char *debugfs); + +#endif /* _PARSE_EVENTS_H */ diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 78adff189bba..81615279b876 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -32,7 +32,9 @@ #include #include #include +#include +#include "../perf.h" #include "trace-event.h" @@ -289,7 +291,18 @@ static void read_header_files(void) put_tracing_file(path); } -static void copy_event_system(const char *sys) +static bool name_in_tp_list(char *sys, struct tracepoint_path *tps) +{ + while (tps) { + if (!strcmp(sys, tps->name)) + return true; + tps = tps->next; + } + + return false; +} + +static void copy_event_system(const char *sys, struct tracepoint_path *tps) { unsigned long long size, check_size; struct dirent *dent; @@ -305,7 +318,8 @@ static void copy_event_system(const char *sys) while ((dent = readdir(dir))) { if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) + strcmp(dent->d_name, "..") == 0 || + !name_in_tp_list(dent->d_name, tps)) continue; format = malloc_or_die(strlen(sys) + strlen(dent->d_name) + 10); sprintf(format, "%s/%s/format", sys, dent->d_name); @@ -321,7 +335,8 @@ static void copy_event_system(const char *sys) rewinddir(dir); while ((dent = readdir(dir))) { if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) + strcmp(dent->d_name, "..") == 0 || + !name_in_tp_list(dent->d_name, tps)) continue; format = malloc_or_die(strlen(sys) + strlen(dent->d_name) + 10); sprintf(format, "%s/%s/format", sys, dent->d_name); @@ -340,18 +355,29 @@ static void copy_event_system(const char *sys) } } -static void read_ftrace_files(void) +static void read_ftrace_files(struct tracepoint_path *tps) { char *path; path = get_tracing_file("events/ftrace"); - copy_event_system(path); + copy_event_system(path, tps); put_tracing_file(path); } -static void read_event_files(void) +static bool system_in_tp_list(char *sys, struct tracepoint_path *tps) +{ + while (tps) { + if (!strcmp(sys, tps->system)) + return true; + tps = tps->next; + } + + return false; +} + +static void read_event_files(struct tracepoint_path *tps) { struct dirent *dent; struct stat st; @@ -370,7 +396,8 @@ static void read_event_files(void) while ((dent = readdir(dir))) { if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0 || - strcmp(dent->d_name, "ftrace") == 0) + strcmp(dent->d_name, "ftrace") == 0 || + !system_in_tp_list(dent->d_name, tps)) continue; sys = malloc_or_die(strlen(path) + strlen(dent->d_name) + 2); sprintf(sys, "%s/%s", path, dent->d_name); @@ -388,7 +415,8 @@ static void read_event_files(void) while ((dent = readdir(dir))) { if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0 || - strcmp(dent->d_name, "ftrace") == 0) + strcmp(dent->d_name, "ftrace") == 0 || + !system_in_tp_list(dent->d_name, tps)) continue; sys = malloc_or_die(strlen(path) + strlen(dent->d_name) + 2); sprintf(sys, "%s/%s", path, dent->d_name); @@ -396,7 +424,7 @@ static void read_event_files(void) if (ret >= 0) { if (S_ISDIR(st.st_mode)) { write_or_die(dent->d_name, strlen(dent->d_name) + 1); - copy_event_system(sys); + copy_event_system(sys, tps); } } free(sys); @@ -450,9 +478,27 @@ static void read_ftrace_printk(void) } -void read_tracing_data(void) +static struct tracepoint_path * +get_tracepoints_path(struct perf_counter_attr *pattrs, int nb_counters) +{ + struct tracepoint_path path, *ppath = &path; + int i; + + for (i = 0; i < nb_counters; i++) { + if (pattrs[i].type != PERF_TYPE_TRACEPOINT) + continue; + ppath->next = tracepoint_id_to_path(pattrs[i].config); + if (!ppath->next) + die("%s\n", "No memory to alloc tracepoints list"); + ppath = ppath->next; + } + + return path.next; +} +void read_tracing_data(struct perf_counter_attr *pattrs, int nb_counters) { char buf[BUFSIZ]; + struct tracepoint_path *tps; output_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644); if (output_fd < 0) @@ -483,9 +529,11 @@ void read_tracing_data(void) page_size = getpagesize(); write_or_die(&page_size, 4); + tps = get_tracepoints_path(pattrs, nb_counters); + read_header_files(); - read_ftrace_files(); - read_event_files(); + read_ftrace_files(tps); + read_event_files(tps); read_proc_kallsyms(); read_ftrace_printk(); } diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index b53b27f34e4e..a6577cdd9afd 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -29,6 +29,7 @@ #include #undef _GNU_SOURCE +#include "../perf.h" #include "util.h" #include "trace-event.h" diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 1dac301ae54f..b12e4903739a 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -36,6 +36,7 @@ #include #include +#include "../perf.h" #include "util.h" #include "trace-event.h" diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 3ddb8947be8a..051fcf363825 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -1,6 +1,7 @@ -#ifndef _PARSE_EVENTS_H -#define _PARSE_EVENTS_H +#ifndef _TRACE_EVENTS_H +#define _TRACE_EVENTS_H +#include "parse-events.h" #define __unused __attribute__((unused)) @@ -233,6 +234,6 @@ extern int header_page_data_size; int parse_header_page(char *buf, unsigned long size); -void read_tracing_data(void); +void read_tracing_data(struct perf_counter_attr *pattrs, int nb_counters); -#endif /* _PARSE_EVENTS_H */ +#endif /* _TRACE_EVENTS_H */ -- cgit v1.2.3 From cd6feeeafddbef6abfe4d90fb26e42fd844d34ed Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 2 Sep 2009 20:20:38 +0200 Subject: perf trace: Sample the CPU too Sample, record, parse and print the CPU field - it had all zeroes before. Before (watch the second column, the CPU values): perf-32685 [000] 0.000000: sched_wakeup_new: task perf:32686 [120] success=1 [011] perf-32685 [000] 0.000000: sched_migrate_task: task perf:32685 [120] from: 1 to: 11 perf-32685 [000] 0.000000: sched_process_fork: parent perf:32685 child perf:32686 true-32686 [000] 0.000000: sched_wakeup: task migration/11:25 [0] success=1 [011] true-32686 [000] 0.000000: sched_wakeup: task distccd:12793 [125] success=1 [015] true-32686 [000] 0.000000: sched_wakeup: task distccd:12793 [125] success=1 [015] perf-32685 [000] 0.000000: sched_switch: task perf:32685 [120] (S) ==> swapper:0 [140] true-32686 [000] 0.000000: sched_switch: task perf:32686 [120] (R) ==> migration/11:25 [0] true-32686 [000] 0.000000: sched_switch: task perf:32686 [120] (R) ==> distccd:12793 [125] true-32686 [000] 0.000000: sched_switch: task true:32686 [120] (R) ==> distccd:12793 [125] true-32686 [000] 0.000000: sched_process_exit: task true:32686 [120] true-32686 [000] 0.000000: sched_stat_wait: task: distccd:12793 wait: 6767985949080 [ns] true-32686 [000] 0.000000: sched_stat_wait: task: distccd:12793 wait: 6767986139446 [ns] true-32686 [000] 0.000000: sched_stat_sleep: task: distccd:12793 sleep: 132844 [ns] true-32686 [000] 0.000000: sched_stat_sleep: task: distccd:12793 sleep: 131724 [ns] After: perf-32685 [001] 0.000000: sched_wakeup_new: task perf:32686 [120] success=1 [011] perf-32685 [001] 0.000000: sched_migrate_task: task perf:32685 [120] from: 1 to: 11 perf-32685 [001] 0.000000: sched_process_fork: parent perf:32685 child perf:32686 true-32686 [011] 0.000000: sched_wakeup: task migration/11:25 [0] success=1 [011] true-32686 [015] 0.000000: sched_wakeup: task distccd:12793 [125] success=1 [015] true-32686 [015] 0.000000: sched_wakeup: task distccd:12793 [125] success=1 [015] perf-32685 [001] 0.000000: sched_switch: task perf:32685 [120] (S) ==> swapper:0 [140] true-32686 [011] 0.000000: sched_switch: task perf:32686 [120] (R) ==> migration/11:25 [0] true-32686 [015] 0.000000: sched_switch: task perf:32686 [120] (R) ==> distccd:12793 [125] true-32686 [015] 0.000000: sched_switch: task true:32686 [120] (R) ==> distccd:12793 [125] true-32686 [015] 0.000000: sched_process_exit: task true:32686 [120] true-32686 [015] 0.000000: sched_stat_wait: task: distccd:12793 wait: 6767985949080 [ns] true-32686 [015] 0.000000: sched_stat_wait: task: distccd:12793 wait: 6767986139446 [ns] true-32686 [015] 0.000000: sched_stat_sleep: task: distccd:12793 sleep: 132844 [ns] true-32686 [015] 0.000000: sched_stat_sleep: task: distccd:12793 sleep: 131724 [ns] So we can now see how this workload migrated between CPUs. Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Frederic Weisbecker Cc: Li Zefan Cc: Mike Galbraith Cc: Arnaldo Carvalho de Melo LKML-Reference: Signed-off-by: Ingo Molnar --- tools/perf/builtin-record.c | 4 +++- tools/perf/builtin-trace.c | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index add514d53d2e..ff93f8ecba28 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -403,8 +403,10 @@ static void create_counter(int counter, int cpu, pid_t pid) if (call_graph) attr->sample_type |= PERF_SAMPLE_CALLCHAIN; - if (raw_samples) + if (raw_samples) { attr->sample_type |= PERF_SAMPLE_RAW; + attr->sample_type |= PERF_SAMPLE_CPU; + } attr->mmap = track; attr->comm = track; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8247fd04745a..bbe4c444ef8f 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -58,12 +58,19 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) struct dso *dso = NULL; struct thread *thread; u64 ip = event->ip.ip; + u32 cpu = -1; u64 period = 1; void *more_data = event->ip.__more_data; int cpumode; thread = threads__findnew(event->ip.pid, &threads, &last_match); + 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); @@ -120,7 +127,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) * field, although it should be the same than this perf * event pid */ - print_event(0, raw->data, raw->size, 0, thread->comm); + print_event(cpu, raw->data, raw->size, 0, thread->comm); } total += period; -- cgit v1.2.3 From 6ddf259da76cab6555c2086386f8bcd10bbb86d2 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 3 Sep 2009 12:00:22 +0200 Subject: perf trace: Sample timestamps as well Before: perf-21082 [013] 0.000000: sched_wakeup_new: task perf:21083 [120] success=1 [015] perf-21082 [013] 0.000000: sched_migrate_task: task perf:21082 [120] from: 13 to: 15 perf-21082 [013] 0.000000: sched_process_fork: parent perf:21082 child perf:21083 true-21083 [015] 0.000000: sched_wakeup: task migration/15:33 [0] success=1 [015] perf-21082 [013] 0.000000: sched_switch: task perf:21082 [120] (S) ==> swapper:0 [140] true-21083 [015] 0.000000: sched_switch: task perf:21083 [120] (R) ==> migration/15:33 [0] true-21083 [011] 0.000000: sched_process_exit: task true:21083 [120] After: perf-21082 [013] 14674.797613: sched_wakeup_new: task perf:21083 [120] success=1 [015] perf-21082 [013] 14674.797506: sched_migrate_task: task perf:21082 [120] from: 13 to: 15 perf-21082 [013] 14674.797610: sched_process_fork: parent perf:21082 child perf:21083 true-21083 [015] 14674.797725: sched_wakeup: task migration/15:33 [0] success=1 [015] perf-21082 [013] 14674.797722: sched_switch: task perf:21082 [120] (S) ==> swapper:0 [140] true-21083 [015] 14674.797729: sched_switch: task perf:21083 [120] (R) ==> migration/15:33 [0] true-21083 [011] 14674.798159: sched_process_exit: task true:21083 [120] Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: Signed-off-by: Ingo Molnar --- tools/perf/builtin-record.c | 1 + tools/perf/builtin-trace.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ff93f8ecba28..99a12fe86e9f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -404,6 +404,7 @@ static void create_counter(int counter, int cpu, pid_t pid) attr->sample_type |= PERF_SAMPLE_CALLCHAIN; if (raw_samples) { + attr->sample_type |= PERF_SAMPLE_TIME; attr->sample_type |= PERF_SAMPLE_RAW; attr->sample_type |= PERF_SAMPLE_CPU; } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index bbe4c444ef8f..d59bf8a86743 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -58,6 +58,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) struct dso *dso = NULL; struct thread *thread; u64 ip = event->ip.ip; + u64 timestamp = -1; u32 cpu = -1; u64 period = 1; void *more_data = event->ip.__more_data; @@ -65,6 +66,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) thread = threads__findnew(event->ip.pid, &threads, &last_match); + 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); @@ -127,7 +133,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) * field, although it should be the same than this perf * event pid */ - print_event(cpu, raw->data, raw->size, 0, thread->comm); + print_event(cpu, raw->data, raw->size, timestamp, thread->comm); } total += period; -- cgit v1.2.3