Patches contributed by Eötvös Lorand University
commit 05ca061eb9704ad9b0739f88046276792b75f2c1
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 14:21:16 2009 +0200
perf report: Print out the total number of events
So that the statistical quality of the profile can be estimated at a glance.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 15fe9dae792b..be392e0f77c6 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -721,6 +721,8 @@ static size_t output__fprintf(FILE *fp, uint64_t total_samples)
struct rb_node *nd;
size_t ret = 0;
+ fprintf(fp, "#\n");
+ fprintf(fp, "# (%Ld profiler events)\n", (__u64)total_samples);
fprintf(fp, "#\n");
fprintf(fp, "# Overhead");
commit bd74137ec9aaca3df3ff22b92455fddf7afaced1
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 14:13:04 2009 +0200
perf_counter tools: Print out symbol parsing errors only if --verbose
Also, add a suggestion to 'perf report', if the default sort order is
used.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 56c664d1b628..15fe9dae792b 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -26,7 +26,10 @@
static char const *input_name = "perf.data";
static char *vmlinux = NULL;
-static char *sort_order = "comm,dso";
+
+static char default_sort_order[] = "comm,dso";
+static char *sort_order = default_sort_order;
+
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -103,9 +106,10 @@ static struct dso *dsos__findnew(const char *name)
if (!dso)
goto out_delete_dso;
- nr = dso__load(dso, NULL);
+ nr = dso__load(dso, NULL, verbose);
if (nr < 0) {
- fprintf(stderr, "Failed to open: %s\n", name);
+ if (verbose)
+ fprintf(stderr, "Failed to open: %s\n", name);
goto out_delete_dso;
}
if (!nr && verbose) {
@@ -139,7 +143,7 @@ static int load_kernel(void)
if (!kernel_dso)
return -1;
- err = dso__load_kernel(kernel_dso, vmlinux, NULL);
+ err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose);
if (err) {
dso__delete(kernel_dso);
kernel_dso = NULL;
@@ -741,6 +745,12 @@ static size_t output__fprintf(FILE *fp, uint64_t total_samples)
ret += hist_entry__fprintf(fp, pos, total_samples);
}
+ if (!strcmp(sort_order, default_sort_order)) {
+ fprintf(fp, "#\n");
+ fprintf(fp, "# ( For more details, try: perf report --sort comm,dso,symbol )\n");
+ fprintf(fp, "#\n");
+ }
+
return ret;
}
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
index 3f7778ba00bc..548a8da4b15b 100644
--- a/Documentation/perf_counter/builtin-top.c
+++ b/Documentation/perf_counter/builtin-top.c
@@ -349,7 +349,7 @@ static int parse_symbols(void)
if (kernel_dso == NULL)
return -1;
- if (dso__load_kernel(kernel_dso, NULL, symbol_filter) != 0)
+ if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0)
goto out_delete_dso;
node = rb_first(&kernel_dso->syms);
diff --git a/Documentation/perf_counter/util/symbol.c b/Documentation/perf_counter/util/symbol.c
index 35ee6de1e513..15d5cf9abfac 100644
--- a/Documentation/perf_counter/util/symbol.c
+++ b/Documentation/perf_counter/util/symbol.c
@@ -124,7 +124,7 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
return ret;
}
-static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter)
+static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose)
{
struct rb_node *nd, *prevnd;
char *line = NULL;
@@ -370,7 +370,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
}
static int dso__load_sym(struct dso *self, int fd, const char *name,
- symbol_filter_t filter)
+ symbol_filter_t filter, int verbose)
{
Elf_Data *symstrs;
uint32_t nr_syms;
@@ -387,13 +387,15 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
- fprintf(stderr, "%s: cannot read %s ELF file.\n",
- __func__, name);
+ if (verbose)
+ fprintf(stderr, "%s: cannot read %s ELF file.\n",
+ __func__, name);
goto out_close;
}
if (gelf_getehdr(elf, &ehdr) == NULL) {
- fprintf(stderr, "%s: cannot get elf header.\n", __func__);
+ if (verbose)
+ fprintf(stderr, "%s: cannot get elf header.\n", __func__);
goto out_elf_end;
}
@@ -473,7 +475,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
return err;
}
-int dso__load(struct dso *self, symbol_filter_t filter)
+int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
{
int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
char *name = malloc(size);
@@ -505,7 +507,7 @@ int dso__load(struct dso *self, symbol_filter_t filter)
fd = open(name, O_RDONLY);
} while (fd < 0);
- ret = dso__load_sym(self, fd, name, filter);
+ ret = dso__load_sym(self, fd, name, filter, verbose);
close(fd);
/*
@@ -520,28 +522,29 @@ int dso__load(struct dso *self, symbol_filter_t filter)
}
static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
- symbol_filter_t filter)
+ symbol_filter_t filter, int verbose)
{
int err, fd = open(vmlinux, O_RDONLY);
if (fd < 0)
return -1;
- err = dso__load_sym(self, fd, vmlinux, filter);
+ err = dso__load_sym(self, fd, vmlinux, filter, verbose);
close(fd);
return err;
}
-int dso__load_kernel(struct dso *self, const char *vmlinux, symbol_filter_t filter)
+int dso__load_kernel(struct dso *self, const char *vmlinux,
+ symbol_filter_t filter, int verbose)
{
int err = -1;
if (vmlinux)
- err = dso__load_vmlinux(self, vmlinux, filter);
+ err = dso__load_vmlinux(self, vmlinux, filter, verbose);
if (err)
- err = dso__load_kallsyms(self, filter);
+ err = dso__load_kallsyms(self, filter, verbose);
return err;
}
diff --git a/Documentation/perf_counter/util/symbol.h b/Documentation/perf_counter/util/symbol.h
index b0299bc0cf50..8dd8522a0a0c 100644
--- a/Documentation/perf_counter/util/symbol.h
+++ b/Documentation/perf_counter/util/symbol.h
@@ -32,8 +32,8 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
struct symbol *dso__find_symbol(struct dso *self, uint64_t ip);
int dso__load_kernel(struct dso *self, const char *vmlinux,
- symbol_filter_t filter);
-int dso__load(struct dso *self, symbol_filter_t filter);
+ symbol_filter_t filter, int verbose);
+int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
size_t dso__fprintf(struct dso *self, FILE *fp);
commit af794b94ae8a16fb4a9da6ce640c122efb44e2a0
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 13:58:13 2009 +0200
perf_counter tools: Build with native optimization
Build the tools with -march=native by default.
No measurable difference in speed though, compared to the
default, on a Nehalem testbox.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile
index 005709b7b19a..414399cbc51a 100644
--- a/Documentation/perf_counter/Makefile
+++ b/Documentation/perf_counter/Makefile
@@ -159,7 +159,7 @@ uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
# CFLAGS and LDFLAGS are for the users to override from the command line.
-CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6
+CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6 -march=native
LDFLAGS = -lpthread -lrt -lelf
ALL_CFLAGS = $(CFLAGS)
ALL_LDFLAGS = $(LDFLAGS)
commit 64edbc562034f2ec3fce382cb208fab40586d005
Merge: 43bd1236234c 0f6ce3de4ef6
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 13:59:26 2009 +0200
Merge branch 'tracing/ftrace' into tracing/core
Merge reason: this mini-topic had outstanding problems that delayed
its merge, so it does not fast-forward.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
commit df97992c6e25ffc66c549c8bc59262dc627c6d17
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 13:41:22 2009 +0200
perf record/report: Fix PID/COMM handling
Fix two bugs causing lost comm mappings:
- initial PID is not 0 but getpid()
- when we are unable to handle an mmap event, dont assume the event
itself is broken - try to parse the stream. This way we wont lose
comm events.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c
index efa2eb498e9c..bf59df5bddf3 100644
--- a/Documentation/perf_counter/builtin-record.c
+++ b/Documentation/perf_counter/builtin-record.c
@@ -430,7 +430,7 @@ static int __cmd_record(int argc, const char **argv)
}
if (!system_wide) {
- open_counters(-1, target_pid != -1 ? target_pid : 0);
+ open_counters(-1, target_pid != -1 ? target_pid : getpid());
} else for (i = 0; i < nr_cpus; i++)
open_counters(i, target_pid);
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 86f23f0991f1..ff6f657476a9 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -852,7 +852,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
if (thread == NULL || map == NULL) {
dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n");
- return -1;
+ return 0;
}
thread__insert_map(thread, map);
commit 6e53cdf11dfc8d302ebb67e7112d1baf8d7c66d4
Author: Ingo Molnar <mingo@elte.hu>
Date: Thu Jun 4 08:53:05 2009 +0200
perf top: Reduce default filter threshold
On idle systems 'perf top' comes up empty by default, because the event
count filter is set to 100.
Reduce it to 5 instead.
Also add an option to limit the number of functions displayed.
Reported-by: Steven Rostedt <rostedt@goodmis.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
index 7c907e25d82b..3f7778ba00bc 100644
--- a/Documentation/perf_counter/builtin-top.c
+++ b/Documentation/perf_counter/builtin-top.c
@@ -64,9 +64,10 @@ static int default_interval = 100000;
static int event_count[MAX_COUNTERS];
static int fd[MAX_NR_CPUS][MAX_COUNTERS];
-static __u64 count_filter = 100;
+static __u64 count_filter = 5;
+static int print_entries = 15;
-static int target_pid = -1;
+static int target_pid = -1;
static int profile_cpu = -1;
static int nr_cpus = 0;
static unsigned int realtime_prio = 0;
@@ -254,7 +255,7 @@ static void print_sym_table(void)
struct symbol *sym = (struct symbol *)(syme + 1);
float pcnt;
- if (++printed > 18 || syme->snap_count < count_filter)
+ if (++printed > print_entries || syme->snap_count < count_filter)
continue;
pcnt = 100.0 - (100.0 * ((sum_kevents - syme->snap_count) /
@@ -650,7 +651,7 @@ static const struct option options[] = {
"number of seconds to delay between refreshes"),
OPT_BOOLEAN('D', "dump-symtab", &dump_symtab,
"dump the symbol table used for profiling"),
- OPT_INTEGER('f', "--count-filter", &count_filter,
+ OPT_INTEGER('f', "count-filter", &count_filter,
"only display functions with more events than this"),
OPT_BOOLEAN('g', "group", &group,
"put the counters into a counter group"),
@@ -662,8 +663,10 @@ static const struct option options[] = {
"track mmap events"),
OPT_BOOLEAN('U', "use-munmap", &use_munmap,
"track munmap events"),
- OPT_INTEGER('F', "--freq", &freq,
+ OPT_INTEGER('F', "freq", &freq,
"profile at this frequency"),
+ OPT_INTEGER('E', "entries", &print_entries,
+ "display this many functions"),
OPT_END()
};
commit d11444dfa78cdd887d8dfd2fab3883132aff2c2d
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed Jun 3 23:29:14 2009 +0200
perf report: Handle all known event types
We have munmap, throttle/unthrottle and period events as well,
process them - otherwise they are considered broke events and
we mis-parse the next few events.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 82b62529e659..6003cc3b188d 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -893,6 +893,15 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
case PERF_EVENT_COMM:
return process_comm_event(event, offset, head);
+ /*
+ * We dont process them right now but they are fine:
+ */
+ case PERF_EVENT_MUNMAP:
+ case PERF_EVENT_PERIOD:
+ case PERF_EVENT_THROTTLE:
+ case PERF_EVENT_UNTHROTTLE:
+ return 0;
+
default:
return -1;
}
commit 75051724f78677532618dd164a515baf106990e5
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed Jun 3 23:14:49 2009 +0200
perf report: Split out event processing helpers
- Introduce per event helper functions
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 333d31269e3f..82b62529e659 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -50,6 +50,7 @@ struct ip_event {
__u64 ip;
__u32 pid, tid;
};
+
struct mmap_event {
struct perf_event_header header;
__u32 pid, tid;
@@ -58,9 +59,10 @@ struct mmap_event {
__u64 pgoff;
char filename[PATH_MAX];
};
+
struct comm_event {
struct perf_event_header header;
- __u32 pid,tid;
+ __u32 pid, tid;
char comm[16];
};
@@ -760,114 +762,137 @@ static void register_idle_thread(void)
static unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
static int
-process_event(event_t *event, unsigned long offset, unsigned long head)
+process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
{
- if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
- char level;
- int show = 0;
- struct dso *dso = NULL;
- struct thread *thread = threads__findnew(event->ip.pid);
- uint64_t ip = event->ip.ip;
- struct map *map = NULL;
-
- dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
- (void *)(offset + head),
- (void *)(long)(event->header.size),
- event->header.misc,
- event->ip.pid,
- (void *)(long)ip);
-
- dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
-
- if (thread == NULL) {
- fprintf(stderr, "problem processing %d event, skipping it.\n",
- event->header.type);
- return -1;
- }
-
- if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
- show = SHOW_KERNEL;
- level = 'k';
+ char level;
+ int show = 0;
+ struct dso *dso = NULL;
+ struct thread *thread = threads__findnew(event->ip.pid);
+ uint64_t ip = event->ip.ip;
+ struct map *map = NULL;
+
+ dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
+ (void *)(offset + head),
+ (void *)(long)(event->header.size),
+ event->header.misc,
+ event->ip.pid,
+ (void *)(long)ip);
+
+ dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
+
+ if (thread == NULL) {
+ fprintf(stderr, "problem processing %d event, skipping it.\n",
+ event->header.type);
+ return -1;
+ }
- dso = kernel_dso;
+ if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
+ show = SHOW_KERNEL;
+ level = 'k';
- dprintf(" ...... dso: %s\n", dso->name);
+ dso = kernel_dso;
- } else if (event->header.misc & PERF_EVENT_MISC_USER) {
+ dprintf(" ...... dso: %s\n", dso->name);
- show = SHOW_USER;
- level = '.';
+ } else if (event->header.misc & PERF_EVENT_MISC_USER) {
- map = thread__find_map(thread, ip);
- if (map != NULL) {
- dso = map->dso;
- ip -= map->start + map->pgoff;
- } else {
- /*
- * If this is outside of all known maps,
- * and is a negative address, try to look it
- * up in the kernel dso, as it might be a
- * vsyscall (which executes in user-mode):
- */
- if ((long long)ip < 0)
- dso = kernel_dso;
- }
- dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
+ show = SHOW_USER;
+ level = '.';
+ map = thread__find_map(thread, ip);
+ if (map != NULL) {
+ dso = map->dso;
+ ip -= map->start + map->pgoff;
} else {
- show = SHOW_HV;
- level = 'H';
- dprintf(" ...... dso: [hypervisor]\n");
+ /*
+ * If this is outside of all known maps,
+ * and is a negative address, try to look it
+ * up in the kernel dso, as it might be a
+ * vsyscall (which executes in user-mode):
+ */
+ if ((long long)ip < 0)
+ dso = kernel_dso;
}
+ dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
- if (show & show_mask) {
- struct symbol *sym = dso__find_symbol(dso, ip);
+ } else {
+ show = SHOW_HV;
+ level = 'H';
+ dprintf(" ...... dso: [hypervisor]\n");
+ }
- if (hist_entry__add(thread, map, dso, sym, ip, level)) {
- fprintf(stderr,
- "problem incrementing symbol count, skipping event\n");
- return -1;
- }
- }
- total++;
- } else switch (event->header.type) {
- case PERF_EVENT_MMAP: {
- struct thread *thread = threads__findnew(event->mmap.pid);
- struct map *map = map__new(&event->mmap);
+ if (show & show_mask) {
+ struct symbol *sym = dso__find_symbol(dso, ip);
- dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
- (void *)(offset + head),
- (void *)(long)(event->header.size),
- (void *)(long)event->mmap.start,
- (void *)(long)event->mmap.len,
- (void *)(long)event->mmap.pgoff,
- event->mmap.filename);
-
- if (thread == NULL || map == NULL) {
- if (verbose)
- fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n");
+ if (hist_entry__add(thread, map, dso, sym, ip, level)) {
+ fprintf(stderr,
+ "problem incrementing symbol count, skipping event\n");
return -1;
}
- thread__insert_map(thread, map);
- total_mmap++;
- break;
}
- case PERF_EVENT_COMM: {
- struct thread *thread = threads__findnew(event->comm.pid);
+ total++;
- dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
- (void *)(offset + head),
- (void *)(long)(event->header.size),
- event->comm.comm, event->comm.pid);
+ return 0;
+}
- if (thread == NULL ||
- thread__set_comm(thread, event->comm.comm)) {
- fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n");
- return -1;
- }
- total_comm++;
- break;
+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);
+
+ dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
+ (void *)(offset + head),
+ (void *)(long)(event->header.size),
+ (void *)(long)event->mmap.start,
+ (void *)(long)event->mmap.len,
+ (void *)(long)event->mmap.pgoff,
+ event->mmap.filename);
+
+ if (thread == NULL || map == NULL) {
+ dprintf("problem processing PERF_EVENT_MMAP, skipping event.\n");
+ return -1;
+ }
+
+ thread__insert_map(thread, map);
+ total_mmap++;
+
+ return 0;
+}
+
+static int
+process_comm_event(event_t *event, unsigned long offset, unsigned long head)
+{
+ struct thread *thread = threads__findnew(event->comm.pid);
+
+ dprintf("%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)) {
+ dprintf("problem processing PERF_EVENT_COMM, skipping event.\n");
+ return -1;
}
+ total_comm++;
+
+ return 0;
+}
+
+static int
+process_event(event_t *event, unsigned long offset, unsigned long head)
+{
+ if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
+ return process_overflow_event(event, offset, head);
+
+ switch (event->header.type) {
+ case PERF_EVENT_MMAP:
+ return process_mmap_event(event, offset, head);
+
+ case PERF_EVENT_COMM:
+ return process_comm_event(event, offset, head);
+
default:
return -1;
}
@@ -877,13 +902,13 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
static int __cmd_report(void)
{
+ int ret, rc = EXIT_FAILURE;
unsigned long offset = 0;
unsigned long head = 0;
struct stat stat;
- char *buf;
event_t *event;
- int ret, rc = EXIT_FAILURE;
uint32_t size;
+ char *buf;
register_idle_thread();
commit d80d338d2fb611b65830db7ea56680624776030f
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed Jun 3 23:14:49 2009 +0200
perf report: Clean up event processing
- Split out event processig into process_events() helper.
- Untangle the cwd parameters - it's constant so can be a static.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 33b3b15fb014..333d31269e3f 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -147,7 +147,11 @@ static int load_kernel(void)
return err;
}
-static int strcommon(const char *pathname, const char *cwd, int cwdlen)
+static char __cwd[PATH_MAX];
+static char *cwd = __cwd;
+static int cwdlen;
+
+static int strcommon(const char *pathname)
{
int n = 0;
@@ -165,7 +169,7 @@ struct map {
struct dso *dso;
};
-static struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen)
+static struct map *map__new(struct mmap_event *event)
{
struct map *self = malloc(sizeof(*self));
@@ -174,7 +178,8 @@ static struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen)
char newfilename[PATH_MAX];
if (cwd) {
- int n = strcommon(filename, cwd, cwdlen);
+ int n = strcommon(filename);
+
if (n == cwdlen) {
snprintf(newfilename, sizeof(newfilename),
".%s", filename + n);
@@ -752,85 +757,11 @@ static void register_idle_thread(void)
}
}
+static unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
-static int __cmd_report(void)
+static int
+process_event(event_t *event, unsigned long offset, unsigned long head)
{
- unsigned long offset = 0;
- unsigned long head = 0;
- struct stat stat;
- char *buf;
- event_t *event;
- int ret, rc = EXIT_FAILURE;
- uint32_t size;
- unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
- char cwd[PATH_MAX], *cwdp = cwd;
- int cwdlen;
-
- register_idle_thread();
-
- input = open(input_name, O_RDONLY);
- if (input < 0) {
- perror("failed to open file");
- exit(-1);
- }
-
- ret = fstat(input, &stat);
- if (ret < 0) {
- perror("failed to stat file");
- exit(-1);
- }
-
- if (!stat.st_size) {
- fprintf(stderr, "zero-sized file, nothing to do!\n");
- exit(0);
- }
-
- if (load_kernel() < 0) {
- perror("failed to load kernel symbols");
- return EXIT_FAILURE;
- }
-
- if (!full_paths) {
- if (getcwd(cwd, sizeof(cwd)) == NULL) {
- perror("failed to get the current directory");
- return EXIT_FAILURE;
- }
- cwdlen = strlen(cwd);
- } else {
- cwdp = NULL;
- cwdlen = 0;
- }
-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 ret;
-
- ret = munmap(buf, page_size * mmap_window);
- assert(ret == 0);
-
- offset += shift;
- head -= shift;
- goto remap;
- }
-
- size = event->header.size;
- if (!size)
- goto broken_event;
-
if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
char level;
int show = 0;
@@ -851,7 +782,7 @@ static int __cmd_report(void)
if (thread == NULL) {
fprintf(stderr, "problem processing %d event, skipping it.\n",
event->header.type);
- goto broken_event;
+ return -1;
}
if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
@@ -895,14 +826,14 @@ static int __cmd_report(void)
if (hist_entry__add(thread, map, dso, sym, ip, level)) {
fprintf(stderr,
"problem incrementing symbol count, skipping event\n");
- goto broken_event;
+ return -1;
}
}
total++;
} else switch (event->header.type) {
case PERF_EVENT_MMAP: {
struct thread *thread = threads__findnew(event->mmap.pid);
- struct map *map = map__new(&event->mmap, cwdp, cwdlen);
+ struct map *map = map__new(&event->mmap);
dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
(void *)(offset + head),
@@ -915,7 +846,7 @@ static int __cmd_report(void)
if (thread == NULL || map == NULL) {
if (verbose)
fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n");
- goto broken_event;
+ return -1;
}
thread__insert_map(thread, map);
total_mmap++;
@@ -932,13 +863,93 @@ static int __cmd_report(void)
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n");
- goto broken_event;
+ return -1;
}
total_comm++;
break;
}
- default: {
-broken_event:
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __cmd_report(void)
+{
+ unsigned long offset = 0;
+ unsigned long head = 0;
+ struct stat stat;
+ char *buf;
+ event_t *event;
+ int ret, rc = EXIT_FAILURE;
+ uint32_t size;
+
+ register_idle_thread();
+
+ input = open(input_name, O_RDONLY);
+ if (input < 0) {
+ perror("failed to open file");
+ exit(-1);
+ }
+
+ ret = fstat(input, &stat);
+ if (ret < 0) {
+ perror("failed to stat file");
+ exit(-1);
+ }
+
+ if (!stat.st_size) {
+ fprintf(stderr, "zero-sized file, nothing to do!\n");
+ exit(0);
+ }
+
+ if (load_kernel() < 0) {
+ perror("failed to load kernel symbols");
+ return EXIT_FAILURE;
+ }
+
+ if (!full_paths) {
+ if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
+ perror("failed to get the current directory");
+ return EXIT_FAILURE;
+ }
+ cwdlen = strlen(cwd);
+ } else {
+ cwd = NULL;
+ cwdlen = 0;
+ }
+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 ret;
+
+ ret = munmap(buf, page_size * mmap_window);
+ assert(ret == 0);
+
+ offset += shift;
+ head -= shift;
+ goto remap;
+ }
+
+ size = event->header.size;
+
+ if (!size || process_event(event, offset, head) < 0) {
+
dprintf("%p [%p]: skipping unknown header type: %d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
@@ -956,7 +967,6 @@ static int __cmd_report(void)
size = 8;
}
- }
head += size;
commit 128f048f0f0d2a477ad2555e7acd2ad15a1b6061
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed Jun 3 22:19:36 2009 +0200
perf_counter: Fix throttling lock-up
Throttling logic is broken and we can lock up with too small
hw sampling intervals.
Make the throttling code more robust: disable counters even
if we already disabled them.
( Also clean up whitespace damage i noticed while reading
various pieces of code related to throttling. )
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 12cc05ed9f48..8f53f3a7da29 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -91,7 +91,7 @@ static u64 intel_pmu_raw_event(u64 event)
#define CORE_EVNTSEL_INV_MASK 0x00800000ULL
#define CORE_EVNTSEL_COUNTER_MASK 0xFF000000ULL
-#define CORE_EVNTSEL_MASK \
+#define CORE_EVNTSEL_MASK \
(CORE_EVNTSEL_EVENT_MASK | \
CORE_EVNTSEL_UNIT_MASK | \
CORE_EVNTSEL_EDGE_MASK | \
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index ab4455447f84..0bb03f15a5b6 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -2822,11 +2822,20 @@ int perf_counter_overflow(struct perf_counter *counter,
if (!throttle) {
counter->hw.interrupts++;
- } else if (counter->hw.interrupts != MAX_INTERRUPTS) {
- counter->hw.interrupts++;
- if (HZ*counter->hw.interrupts > (u64)sysctl_perf_counter_limit) {
- counter->hw.interrupts = MAX_INTERRUPTS;
- perf_log_throttle(counter, 0);
+ } else {
+ if (counter->hw.interrupts != MAX_INTERRUPTS) {
+ counter->hw.interrupts++;
+ if (HZ*counter->hw.interrupts > (u64)sysctl_perf_counter_limit) {
+ counter->hw.interrupts = MAX_INTERRUPTS;
+ perf_log_throttle(counter, 0);
+ ret = 1;
+ }
+ } else {
+ /*
+ * Keep re-disabling counters even though on the previous
+ * pass we disabled it - just in case we raced with a
+ * sched-in and the counter got enabled again:
+ */
ret = 1;
}
}