diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-15 11:26:35 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-15 11:26:35 -0800 |
commit | 83c2f912b43c3a7babbb6cb7ae2a5276c1ed2a3e (patch) | |
tree | eaa7f50dea154d9f19721db69c7adde64d48848f /tools/perf | |
parent | f0ed5b9a28536b8be2f578a9450cfa42ab31ccf8 (diff) | |
parent | 172d1b0b73256551f100fc00c69e356d047103f5 (diff) |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (39 commits)
perf tools: Fix compile error on x86_64 Ubuntu
perf report: Fix --stdio output alignment when --showcpuutilization used
perf annotate: Get rid of field_sep check
perf annotate: Fix usage string
perf kmem: Fix a memory leak
perf kmem: Add missing closedir() calls
perf top: Add error message for EMFILE
perf test: Change type of '-v' option to INCR
perf script: Add missing closedir() calls
tracing: Fix compile error when static ftrace is enabled
recordmcount: Fix handling of elf64 big-endian objects.
perf tools: Add const.h to MANIFEST to make perf-tar-src-pkg work again
perf tools: Add support for guest/host-only profiling
perf kvm: Do guest-only counting by default
perf top: Don't update total_period on process_sample
perf hists: Stop using 'self' for struct hist_entry
perf hists: Rename total_session to total_period
x86: Add counter when debug stack is used with interrupts enabled
x86: Allow NMIs to hit breakpoints in i386
x86: Keep current stack in NMI breakpoints
...
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/Documentation/perf-list.txt | 2 | ||||
-rw-r--r-- | tools/perf/MANIFEST | 1 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 7 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-kvm.c | 6 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-test.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 5 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 5 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 131 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 7 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 15 | ||||
-rw-r--r-- | tools/perf/util/trace-event-info.c | 1 | ||||
-rw-r--r-- | tools/perf/util/util.c | 15 | ||||
-rw-r--r-- | tools/perf/util/util.h | 4 |
15 files changed, 124 insertions, 84 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 7a527f7e9da..ddc22525228 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -21,6 +21,8 @@ EVENT MODIFIERS Events can optionally have a modifer by appending a colon and one or more modifiers. Modifiers allow the user to restrict when events are counted with 'u' for user-space, 'k' for kernel, 'h' for hypervisor. +Additional modifiers are 'G' for guest counting (in KVM guests) and 'H' +for host counting (not in KVM guests). The 'p' modifier can be used for specifying how precise the instruction address should be. The 'p' modifier is currently only implemented for diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index c12659d8cb2..1078c5fadd5 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST @@ -1,4 +1,5 @@ tools/perf +include/linux/const.h include/linux/perf_event.h include/linux/rbtree.h include/linux/list.h diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 214ba7f9f57..806e0a28663 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -235,7 +235,7 @@ out_delete: } static const char * const annotate_usage[] = { - "perf annotate [<options>] <command>", + "perf annotate [<options>]", NULL }; @@ -313,10 +313,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) annotate.sym_hist_filter = argv[0]; } - if (field_sep && *field_sep == '.') { - pr_err("'.' is the only non valid --field-separator argument\n"); - return -1; - } - return __cmd_annotate(&annotate); } diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index fe1ad8f2196..39104c0beea 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -108,7 +108,9 @@ static void setup_cpunode_map(void) continue; cpunode_map[cpu] = mem; } + closedir(dir2); } + closedir(dir1); } static void insert_alloc_stat(unsigned long call_site, unsigned long ptr, @@ -645,6 +647,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg) break; if (sort_dimension__add(tok, sort_list) < 0) { error("Unknown --sort key: '%s'", tok); + free(str); return -1; } } diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 032324a76b8..9fc6e0fa3dc 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -22,9 +22,6 @@ static const char *file_name; static char name_buffer[256]; -bool perf_host = 1; -bool perf_guest; - static const char * const kvm_usage[] = { "perf kvm [<options>] {top|record|report|diff|buildid-list}", NULL @@ -107,7 +104,8 @@ static int __cmd_buildid_list(int argc, const char **argv) int cmd_kvm(int argc, const char **argv, const char *prefix __used) { - perf_host = perf_guest = 0; + perf_host = 0; + perf_guest = 1; argc = parse_options(argc, argv, kvm_options, kvm_usage, PARSE_OPT_STOP_AT_NON_OPTION); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index fd1909afcfd..bb68ddf257b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1018,13 +1018,17 @@ static char *get_script_path(const char *script_root, const char *suffix) __script_root = get_script_root(&script_dirent, suffix); if (__script_root && !strcmp(script_root, __script_root)) { free(__script_root); + closedir(lang_dir); + closedir(scripts_dir); snprintf(script_path, MAXPATHLEN, "%s/%s", lang_path, script_dirent.d_name); return strdup(script_path); } free(__script_root); } + closedir(lang_dir); } + closedir(scripts_dir); return NULL; } diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 2b9a7f497a2..3854e869dce 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -1396,7 +1396,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __used) NULL, }; const struct option test_options[] = { - OPT_INTEGER('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_END() }; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 4f81eeb9987..8f80df89603 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -235,7 +235,6 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, if (he == NULL) return NULL; - evsel->hists.stats.total_period += sample->period; hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); return he; } @@ -889,6 +888,10 @@ try_again: ui__warning("The %s event is not supported.\n", event_name(counter)); goto out_err; + } else if (err == EMFILE) { + ui__warning("Too many events are opened.\n" + "Try again after reducing the number of events\n"); + goto out_err; } ui__warning("The sys_perf_event_open() syscall " diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index fa1837088ca..3f16e08a5c8 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -111,8 +111,11 @@ int perf_evlist__add_default(struct perf_evlist *evlist) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES, }; - struct perf_evsel *evsel = perf_evsel__new(&attr, 0); + struct perf_evsel *evsel; + + event_attr_init(&attr); + evsel = perf_evsel__new(&attr, 0); if (evsel == NULL) goto error; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index abef2703cd2..6f505d1abac 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -76,21 +76,21 @@ static void hists__calc_col_len(struct hists *hists, struct hist_entry *h) } } -static void hist_entry__add_cpumode_period(struct hist_entry *self, +static void hist_entry__add_cpumode_period(struct hist_entry *he, unsigned int cpumode, u64 period) { switch (cpumode) { case PERF_RECORD_MISC_KERNEL: - self->period_sys += period; + he->period_sys += period; break; case PERF_RECORD_MISC_USER: - self->period_us += period; + he->period_us += period; break; case PERF_RECORD_MISC_GUEST_KERNEL: - self->period_guest_sys += period; + he->period_guest_sys += period; break; case PERF_RECORD_MISC_GUEST_USER: - self->period_guest_us += period; + he->period_guest_us += period; break; default: break; @@ -165,18 +165,18 @@ void hists__decay_entries_threaded(struct hists *hists, static struct hist_entry *hist_entry__new(struct hist_entry *template) { size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0; - struct hist_entry *self = malloc(sizeof(*self) + callchain_size); + struct hist_entry *he = malloc(sizeof(*he) + callchain_size); - if (self != NULL) { - *self = *template; - self->nr_events = 1; - if (self->ms.map) - self->ms.map->referenced = true; + if (he != NULL) { + *he = *template; + he->nr_events = 1; + if (he->ms.map) + he->ms.map->referenced = true; if (symbol_conf.use_callchain) - callchain_init(self->callchain); + callchain_init(he->callchain); } - return self; + return he; } static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h) @@ -677,15 +677,16 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, return ret; } -static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, - u64 total_samples, int left_margin) +static size_t hist_entry_callchain__fprintf(struct hist_entry *he, + u64 total_samples, int left_margin, + FILE *fp) { struct rb_node *rb_node; struct callchain_node *chain; size_t ret = 0; u32 entries_printed = 0; - rb_node = rb_first(&self->sorted_chain); + rb_node = rb_first(&he->sorted_chain); while (rb_node) { double percent; @@ -730,35 +731,35 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows) } } -static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s, +static int hist_entry__pcnt_snprintf(struct hist_entry *he, char *s, size_t size, struct hists *pair_hists, bool show_displacement, long displacement, - bool color, u64 session_total) + bool color, u64 total_period) { u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; u64 nr_events; const char *sep = symbol_conf.field_sep; int ret; - if (symbol_conf.exclude_other && !self->parent) + if (symbol_conf.exclude_other && !he->parent) return 0; if (pair_hists) { - period = self->pair ? self->pair->period : 0; - nr_events = self->pair ? self->pair->nr_events : 0; + period = he->pair ? he->pair->period : 0; + nr_events = he->pair ? he->pair->nr_events : 0; total = pair_hists->stats.total_period; - period_sys = self->pair ? self->pair->period_sys : 0; - period_us = self->pair ? self->pair->period_us : 0; - period_guest_sys = self->pair ? self->pair->period_guest_sys : 0; - period_guest_us = self->pair ? self->pair->period_guest_us : 0; + period_sys = he->pair ? he->pair->period_sys : 0; + period_us = he->pair ? he->pair->period_us : 0; + period_guest_sys = he->pair ? he->pair->period_guest_sys : 0; + period_guest_us = he->pair ? he->pair->period_guest_us : 0; } else { - period = self->period; - nr_events = self->nr_events; - total = session_total; - period_sys = self->period_sys; - period_us = self->period_us; - period_guest_sys = self->period_guest_sys; - period_guest_us = self->period_guest_us; + period = he->period; + nr_events = he->nr_events; + total = total_period; + period_sys = he->period_sys; + period_us = he->period_us; + period_guest_sys = he->period_guest_sys; + period_guest_us = he->period_guest_us; } if (total) { @@ -812,8 +813,8 @@ static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s, if (total > 0) old_percent = (period * 100.0) / total; - if (session_total > 0) - new_percent = (self->period * 100.0) / session_total; + if (total_period > 0) + new_percent = (he->period * 100.0) / total_period; diff = new_percent - old_percent; @@ -862,9 +863,10 @@ int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size, return ret; } -int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists, - struct hists *pair_hists, bool show_displacement, - long displacement, FILE *fp, u64 session_total) +static int hist_entry__fprintf(struct hist_entry *he, size_t size, + struct hists *hists, struct hists *pair_hists, + bool show_displacement, long displacement, + u64 total_period, FILE *fp) { char bf[512]; int ret; @@ -874,14 +876,14 @@ int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists, ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists, show_displacement, displacement, - true, session_total); + true, total_period); hist_entry__snprintf(he, bf + ret, size - ret, hists); return fprintf(fp, "%s\n", bf); } -static size_t hist_entry__fprintf_callchain(struct hist_entry *self, - struct hists *hists, FILE *fp, - u64 session_total) +static size_t hist_entry__fprintf_callchain(struct hist_entry *he, + struct hists *hists, + u64 total_period, FILE *fp) { int left_margin = 0; @@ -889,11 +891,10 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self, struct sort_entry *se = list_first_entry(&hist_entry__sort_list, typeof(*se), list); left_margin = hists__col_len(hists, se->se_width_idx); - left_margin -= thread__comm_len(self->thread); + left_margin -= thread__comm_len(he->thread); } - return hist_entry_callchain__fprintf(fp, self, session_total, - left_margin); + return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); } size_t hists__fprintf(struct hists *hists, struct hists *pair, @@ -903,6 +904,7 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, struct sort_entry *se; struct rb_node *nd; size_t ret = 0; + u64 total_period; unsigned long position = 1; long displacement = 0; unsigned int width; @@ -917,20 +919,6 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, fprintf(fp, "# %s", pair ? "Baseline" : "Overhead"); - if (symbol_conf.show_nr_samples) { - if (sep) - fprintf(fp, "%cSamples", *sep); - else - fputs(" Samples ", fp); - } - - if (symbol_conf.show_total_period) { - if (sep) - ret += fprintf(fp, "%cPeriod", *sep); - else - ret += fprintf(fp, " Period "); - } - if (symbol_conf.show_cpu_utilization) { if (sep) { ret += fprintf(fp, "%csys", *sep); @@ -940,8 +928,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, ret += fprintf(fp, "%cguest us", *sep); } } else { - ret += fprintf(fp, " sys "); - ret += fprintf(fp, " us "); + ret += fprintf(fp, " sys "); + ret += fprintf(fp, " us "); if (perf_guest) { ret += fprintf(fp, " guest sys "); ret += fprintf(fp, " guest us "); @@ -949,6 +937,20 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, } } + if (symbol_conf.show_nr_samples) { + if (sep) + fprintf(fp, "%cSamples", *sep); + else + fputs(" Samples ", fp); + } + + if (symbol_conf.show_total_period) { + if (sep) + ret += fprintf(fp, "%cPeriod", *sep); + else + ret += fprintf(fp, " Period "); + } + if (pair) { if (sep) ret += fprintf(fp, "%cDelta", *sep); @@ -993,6 +995,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, goto print_entries; fprintf(fp, "# ........"); + if (symbol_conf.show_cpu_utilization) + fprintf(fp, " ....... ......."); if (symbol_conf.show_nr_samples) fprintf(fp, " .........."); if (symbol_conf.show_total_period) @@ -1025,6 +1029,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair, goto out; print_entries: + total_period = hists->stats.total_period; + for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); @@ -1040,11 +1046,10 @@ print_entries: ++position; } ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement, - displacement, fp, hists->stats.total_period); + displacement, total_period, fp); if (symbol_conf.use_callchain) - ret += hist_entry__fprintf_callchain(h, hists, fp, - hists->stats.total_period); + ret += hist_entry__fprintf_callchain(h, hists, total_period, fp); if (max_rows && ++nr_rows >= max_rows) goto out; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index ff6f9d56ea4..f55f0a8d1f8 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -66,11 +66,8 @@ struct hists { struct hist_entry *__hists__add_entry(struct hists *self, struct addr_location *al, struct symbol *parent, u64 period); -extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); -extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); -int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists, - struct hists *pair_hists, bool show_displacement, - long displacement, FILE *fp, u64 session_total); +int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); +int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, struct hists *hists); void hist_entry__free(struct hist_entry *); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 531c283fc0c..b029296d20d 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -735,8 +735,8 @@ static int parse_event_modifier(const char **strp, struct perf_event_attr *attr) { const char *str = *strp; - int exclude = 0; - int eu = 0, ek = 0, eh = 0, precise = 0; + int exclude = 0, exclude_GH = 0; + int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0; if (!*str) return 0; @@ -760,6 +760,14 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr) if (!exclude) exclude = eu = ek = eh = 1; eh = 0; + } else if (*str == 'G') { + if (!exclude_GH) + exclude_GH = eG = eH = 1; + eG = 0; + } else if (*str == 'H') { + if (!exclude_GH) + exclude_GH = eG = eH = 1; + eH = 0; } else if (*str == 'p') { precise++; } else @@ -776,6 +784,8 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr) attr->exclude_kernel = ek; attr->exclude_hv = eh; attr->precise_ip = precise; + attr->exclude_host = eH; + attr->exclude_guest = eG; return 0; } @@ -838,6 +848,7 @@ int parse_events(struct perf_evlist *evlist , const char *str, int unset __used) for (;;) { ostr = str; memset(&attr, 0, sizeof(attr)); + event_attr_init(&attr); ret = parse_event_symbols(evlist, &str, &attr); if (ret == EVT_FAILED) return -1; diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index ac6830d8292..fc22cf5c605 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -18,7 +18,6 @@ * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -#include <ctype.h> #include "util.h" #include <dirent.h> #include <mntent.h> diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 5b3ea49aa63..813141047fc 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -1,6 +1,21 @@ +#include "../perf.h" #include "util.h" #include <sys/mman.h> +/* + * XXX We need to find a better place for these things... + */ +bool perf_host = true; +bool perf_guest = true; + +void event_attr_init(struct perf_event_attr *attr) +{ + if (!perf_host) + attr->exclude_host = 1; + if (!perf_guest) + attr->exclude_guest = 1; +} + int mkdir_p(char *path, mode_t mode) { struct stat st; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 37be34dff79..b9c530cce79 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -242,6 +242,10 @@ int strtailcmp(const char *s1, const char *s2); unsigned long convert_unit(unsigned long value, char *unit); int readn(int fd, void *buf, size_t size); +struct perf_event_attr; + +void event_attr_init(struct perf_event_attr *attr); + #define _STR(x) #x #define STR(x) _STR(x) |