From c7f7fea30b7e52c9d4b9cef271110a98d59adcbc Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 22 Sep 2009 14:53:51 +0200 Subject: perf stat: Fix zero total printouts Before: 0 sched:sched_switch # nan M/sec After: 0 sched:sched_switch # 0.000 M/sec 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-stat.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 16af2d8..e5f6ece 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -338,14 +338,24 @@ static void nsec_printout(int counter, double avg) static void abs_printout(int counter, double avg) { + double total, ratio = 0.0; + fprintf(stderr, " %14.0f %-24s", avg, event_name(counter)); if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { - fprintf(stderr, " # %10.3f IPC ", - avg / avg_stats(&runtime_cycles_stats)); + total = avg_stats(&runtime_cycles_stats); + + if (total) + ratio = avg / total; + + fprintf(stderr, " # %10.3f IPC ", ratio); } else { - fprintf(stderr, " # %10.3f M/sec", - 1000.0 * avg / avg_stats(&runtime_nsecs_stats)); + total = avg_stats(&runtime_nsecs_stats); + + if (total) + ratio = 1000.0 * avg / total; + + fprintf(stderr, " # %10.3f M/sec", ratio); } } -- cgit v1.1 From a6f10a2f5d8c2738b3ac05974bdbea3b68a2aecd Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 22 Sep 2009 22:34:24 +1000 Subject: perf_event: Update PERF_EVENT_FORK header definition PERF_EVENT_FORK always outputs the time field, so update the header to reflect this. Signed-off-by: Anton Blanchard Cc: Arjan van de Ven Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Frederic Weisbecker LKML-Reference: <20090922123424.GD19453@kryten> Signed-off-by: Ingo Molnar --- include/linux/perf_counter.h | 2 +- include/linux/perf_event.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 368bd70..7b7fbf4 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h @@ -361,7 +361,7 @@ enum perf_event_type { * struct perf_event_header header; * u32 pid, ppid; * u32 tid, ptid; - * { u64 time; } && PERF_SAMPLE_TIME + * u64 time; * }; */ PERF_EVENT_FORK = 7, diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index acefaf7..3a9d36d 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -357,7 +357,7 @@ enum perf_event_type { * struct perf_event_header header; * u32 pid, ppid; * u32 tid, ptid; - * { u64 time; } && PERF_SAMPLE_TIME + * u64 time; * }; */ PERF_RECORD_FORK = 7, -- cgit v1.1 From 7d42896628202a551ad1107697cd215dc5fca099 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 23 Sep 2009 11:03:37 +0200 Subject: perf_event, x86: Fix 'perf sched record' crashing the machine Chris Malley reported that 'perf sched record' sometimes crashes his box with: [ 389.272175] BUG: unable to handle kernel paging request at ffffb300 [ 389.272294] IP: [] default_send_IPI_self+0x1d/0x50 [ 389.272366] *pde = 0073f067 *pte = 00000000 [ 389.274708] Call Trace: [ 389.274752] [] ? set_perf_event_pending+0x14/0x20 [ 389.274801] [] ? perf_output_unlock+0x121/0x1a0 [ 389.274848] [] ? perf_output_end+0x4a/0x70 [ 389.274893] [] ? __perf_event_overflow+0x240/0x2f0 [ 389.274942] [] ? atomic64_cmpxchg+0x1e/0x30 [ 389.274988] [] ? perf_swevent_ctx_event+0x1b4/0x1c0 [ 389.275035] [] ? perf_swevent_ctx_event+0x33/0x1c0 [ 389.275081] [] ? do_perf_sw_event+0xa7/0x160 [ 389.275127] [] ? perf_tp_event+0x82/0xa0 [ 389.275174] [] ? ftrace_profile_sched_stat_runtime+0xe6/0x120 [ 389.275224] [] ? ftrace_profile_sched_stat_runtime+0x0/0x120 [ 389.275273] [] ? update_curr+0x18a/0x230 [ 389.275318] [] ? put_prev_task_fair+0x155/0x160 [ 389.275366] [] ? sched_clock_cpu+0xd5/0x110 [ 389.275413] [] ? _spin_lock_irq+0x45/0x50 [ 389.275458] [] ? schedule+0x20e/0xb10 The problem is that the box has no lapic enabled: [ 0.042445] Local APIC not detected. Using dummy APIC emulation. The below seems like the best fix. We disabled all lapic bits, except the self-IPI-resend logic. Reported-by: Chris Malley Signed-off-by: Peter Zijlstra Cc: Cyrill Gorcunov Cc: Frederic Weisbecker LKML-Reference: <7863dc4c0909221409v7893bfd3o4b590d5951a233ba@mail.gmail.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index a3c7adb..b5801c3 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1790,6 +1790,9 @@ void smp_perf_pending_interrupt(struct pt_regs *regs) void set_perf_event_pending(void) { #ifdef CONFIG_X86_LOCAL_APIC + if (!x86_pmu.apic || !x86_pmu_initialized()) + return; + apic->send_IPI_self(LOCAL_PENDING_VECTOR); #endif } -- cgit v1.1 From 508c4d0874acf8584787bbab7e4a3798e2834c1a Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Wed, 23 Sep 2009 11:20:58 +0200 Subject: perf tools: Fix module symbol loading bug Avi Kivity reported 'perf annotate' failures with modules, the requested function was not annotated. If there are no modules currently loaded, or the last module scanned is not loaded, dso__load_modules() steps on the value from dso__load_vmlinux(), so we happily load the kallsyms symbols on top of what we've already loaded. Fix that such that the total count of symbols loaded is returned. Should module symbol load fail after parsing of vmlinux, is's a hard failure, so do not silently fall-back to kallsyms. Reported-by: Avi Kivity Signed-off-by: Mike Galbraith Cc: Arnaldo Carvalho de Melo Cc: rostedt@goodmis.org Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Masami Hiramatsu LKML-Reference: <1253697658.11461.36.camel@marge.simson.net> Signed-off-by: Ingo Molnar --- tools/perf/util/symbol.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fd3d9c8..559fb06 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -833,7 +833,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) struct mod_dso *mods = mod_dso__new_dso("modules"); struct module *pos; struct rb_node *next; - int err; + int err, count = 0; err = mod_dso__load_modules(mods); @@ -852,14 +852,16 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) break; next = rb_next(&pos->rb_node); + count += err; } if (err < 0) { mod_dso__delete_modules(mods); mod_dso__delete_self(mods); + return err; } - return err; + return count; } static inline void dso__fill_symbol_holes(struct dso *self) @@ -913,8 +915,15 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, if (vmlinux) { err = dso__load_vmlinux(self, vmlinux, filter, v); - if (err > 0 && use_modules) - err = dso__load_modules(self, filter, v); + if (err > 0 && use_modules) { + int syms = dso__load_modules(self, filter, v); + + if (syms < 0) { + fprintf(stderr, "dso__load_modules failed!\n"); + return syms; + } + err += syms; + } } if (err <= 0) -- cgit v1.1 From dd906a0fe8d78b925702cd3916a65f34dfdfc011 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 24 Sep 2009 10:07:08 +0200 Subject: perf tools: Handle relative paths while loading module symbols Inform util/module.c::mod_dso__load_module_paths() that relative paths do exist in some modules.dep, and make it fail noisily should it encounter a path that it doesn't understand, or a module it cannot open. Reported-by: Avi Kivity Signed-off-by: Mike Galbraith Cc: Arnaldo Carvalho de Melo Cc: rostedt@goodmis.org Cc: Mathieu Desnoyers Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Masami Hiramatsu LKML-Reference: <1253779628.10513.8.camel@marge.simson.net> Signed-off-by: Ingo Molnar --- tools/perf/util/module.c | 96 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c index 3d567fe..8f81622 100644 --- a/tools/perf/util/module.c +++ b/tools/perf/util/module.c @@ -4,6 +4,7 @@ #include "module.h" #include +#include #include #include #include @@ -409,35 +410,40 @@ out_failure: static int mod_dso__load_module_paths(struct mod_dso *self) { struct utsname uts; - int count = 0, len; + int count = 0, len, err = -1; char *line = NULL; FILE *file; - char *path; + char *dpath, *dir; size_t n; if (uname(&uts) < 0) - goto out_failure; + return err; len = strlen("/lib/modules/"); len += strlen(uts.release); len += strlen("/modules.dep"); - path = calloc(1, len); - if (path == NULL) - goto out_failure; + dpath = calloc(1, len); + if (dpath == NULL) + return err; - strcat(path, "/lib/modules/"); - strcat(path, uts.release); - strcat(path, "/modules.dep"); + strcat(dpath, "/lib/modules/"); + strcat(dpath, uts.release); + strcat(dpath, "/modules.dep"); - file = fopen(path, "r"); - free(path); + file = fopen(dpath, "r"); if (file == NULL) goto out_failure; + dir = dirname(dpath); + if (!dir) + goto out_failure; + strcat(dir, "/"); + while (!feof(file)) { - char *name, *tmp; struct module *module; + char *name, *path, *tmp; + FILE *modfile; int line_len; line_len = getline(&line, &n, file); @@ -445,17 +451,41 @@ static int mod_dso__load_module_paths(struct mod_dso *self) break; if (!line) - goto out_failure; + break; line[--line_len] = '\0'; /* \n */ - path = strtok(line, ":"); + path = strchr(line, ':'); + if (!path) + break; + *path = '\0'; + + path = strdup(line); if (!path) - goto out_failure; + break; + + if (!strstr(path, dir)) { + if (strncmp(path, "kernel/", 7)) + break; + + free(path); + path = calloc(1, strlen(dir) + strlen(line) + 1); + if (!path) + break; + strcat(path, dir); + strcat(path, line); + } + + modfile = fopen(path, "r"); + if (modfile == NULL) + break; + fclose(modfile); name = strdup(path); - name = strtok(name, "/"); + if (!name) + break; + name = strtok(name, "/"); tmp = name; while (tmp) { @@ -463,26 +493,25 @@ static int mod_dso__load_module_paths(struct mod_dso *self) if (tmp) name = tmp; } + name = strsep(&name, "."); + if (!name) + break; - /* Quirk: replace '-' with '_' in sound modules */ + /* Quirk: replace '-' with '_' in all modules */ for (len = strlen(name); len; len--) { if (*(name+len) == '-') *(name+len) = '_'; } module = module__new(name, path); - if (!module) { - fprintf(stderr, "load_module_paths: allocation error\n"); - goto out_failure; - } + if (!module) + break; mod_dso__insert_module(self, module); module->sections = sec_dso__new_dso("sections"); - if (!module->sections) { - fprintf(stderr, "load_module_paths: allocation error\n"); - goto out_failure; - } + if (!module->sections) + break; module->active = mod_dso__load_sections(module); @@ -490,13 +519,20 @@ static int mod_dso__load_module_paths(struct mod_dso *self) count++; } - free(line); - fclose(file); - - return count; + if (feof(file)) + err = count; + else + fprintf(stderr, "load_module_paths: modules.dep parsing failure!\n"); out_failure: - return -1; + if (dpath) + free(dpath); + if (file) + fclose(file); + if (line) + free(line); + + return err; } int mod_dso__load_modules(struct mod_dso *dso) -- cgit v1.1 From 67030036ebb370b0aa5561ae2fe31668ed1ccd1c Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Thu, 24 Sep 2009 15:00:22 +0400 Subject: perf tools: .gitignore += perf*.html I've tried building the docs in tools/perf/Documentation/ , and after that `git status` showed dozen of untracked htmls. Let's ignore them. Signed-off-by: Kirill Smelkov LKML-Reference: <1253790022-10300-1-git-send-email-kirr@mns.spb.ru> Signed-off-by: Ingo Molnar --- tools/perf/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index d69a759..0854f11 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore @@ -10,6 +10,7 @@ perf-stat perf-top perf*.1 perf*.xml +perf*.html common-cmds.h tags TAGS -- cgit v1.1 From a255a9981a8566a1efabec983b7811e937e662d2 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 24 Sep 2009 15:05:59 +0200 Subject: perf tools: Fix buffer allocation "perf top" cores dump on my dev machine, if run from a directory where vmlinux is present: *** glibc detected *** malloc(): memory corruption: 0x085670d0 *** Signed-off-by: Eric Dumazet Cc: LKML-Reference: <4ABB6EB7.7000002@gmail.com> Signed-off-by: Ingo Molnar --- tools/perf/util/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c index 8f81622..0d8c85d 100644 --- a/tools/perf/util/module.c +++ b/tools/perf/util/module.c @@ -423,7 +423,7 @@ static int mod_dso__load_module_paths(struct mod_dso *self) len += strlen(uts.release); len += strlen("/modules.dep"); - dpath = calloc(1, len); + dpath = calloc(1, len + 1); if (dpath == NULL) return err; -- cgit v1.1 From 725b13685c61168f71825b3fb67d96d2d7aa3b0f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 24 Sep 2009 15:39:09 +0200 Subject: perf tools: Dont use openat() openat() is still a young glibc facility, better to not use it in a non performance critical program (perf list) Many machines have older glibc (RHEL 4 Update 5 -> glibc-2.3.4-2.36 on my dev machine for example). Signed-off-by: Eric Dumazet Cc: Peter Zijlstra Cc: Ulrich Drepper LKML-Reference: <4ABB767D.6080004@gmail.com> Signed-off-by: Ingo Molnar --- tools/perf/util/parse-events.c | 49 +++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 13ab4b8..87c424d 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -165,33 +165,31 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) DIR *sys_dir, *evt_dir; struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; char id_buf[4]; - int sys_dir_fd, fd; + int fd; u64 id; char evt_path[MAXPATHLEN]; + char dir_path[MAXPATHLEN]; if (valid_debugfs_mount(debugfs_path)) return NULL; sys_dir = opendir(debugfs_path); if (!sys_dir) - goto cleanup; - sys_dir_fd = dirfd(sys_dir); + return NULL; for_each_subsystem(sys_dir, sys_dirent, sys_next) { - int dfd = openat(sys_dir_fd, sys_dirent.d_name, - O_RDONLY|O_DIRECTORY), evt_dir_fd; - if (dfd == -1) - continue; - evt_dir = fdopendir(dfd); - if (!evt_dir) { - close(dfd); + + snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, + sys_dirent.d_name); + evt_dir = opendir(dir_path); + if (!evt_dir) continue; - } - evt_dir_fd = dirfd(evt_dir); + for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { - snprintf(evt_path, MAXPATHLEN, "%s/id", + + snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dirent.d_name); - fd = openat(evt_dir_fd, evt_path, O_RDONLY); + fd = open(evt_path, O_RDONLY); if (fd < 0) continue; if (read(fd, id_buf, sizeof(id_buf)) < 0) { @@ -225,7 +223,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) closedir(evt_dir); } -cleanup: closedir(sys_dir); return NULL; } @@ -761,28 +758,24 @@ static void print_tracepoint_events(void) { DIR *sys_dir, *evt_dir; struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; - int sys_dir_fd; char evt_path[MAXPATHLEN]; + char dir_path[MAXPATHLEN]; if (valid_debugfs_mount(debugfs_path)) return; sys_dir = opendir(debugfs_path); if (!sys_dir) - goto cleanup; - sys_dir_fd = dirfd(sys_dir); + return; for_each_subsystem(sys_dir, sys_dirent, sys_next) { - int dfd = openat(sys_dir_fd, sys_dirent.d_name, - O_RDONLY|O_DIRECTORY), evt_dir_fd; - if (dfd == -1) - continue; - evt_dir = fdopendir(dfd); - if (!evt_dir) { - close(dfd); + + snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, + sys_dirent.d_name); + evt_dir = opendir(dir_path); + if (!evt_dir) continue; - } - evt_dir_fd = dirfd(evt_dir); + for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { snprintf(evt_path, MAXPATHLEN, "%s:%s", sys_dirent.d_name, evt_dirent.d_name); @@ -791,8 +784,6 @@ static void print_tracepoint_events(void) } closedir(evt_dir); } - -cleanup: closedir(sys_dir); } -- cgit v1.1