diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-09-19 10:59:01 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-09-19 10:59:01 -0400 |
commit | bea8f35421628266658c14ea990d18b0969c4c0b (patch) | |
tree | 46c5d4616a003011a1237ed8d31592a662cf9720 | |
parent | 26f45274afd938d82463816a12ec67448513294a (diff) | |
parent | 7ae92e744e3fb389afb1e24920ecda331d360c61 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
* Fix handling of unresolved samples when --symbols is used in 'report',
from Feng Tang.
* Add --symbols to 'script', similar to the one in 'report', from Feng Tang.
* Add union member access support to 'probe', from Hyeoncheol Lee.
* Make 'archive' work on Android, tweaking some of the utility parameters
used (tar, rm), from Irina Tirdea.
* Fixups to die() removal, from Namhyung Kim.
* Render fixes for the TUI, from Namhyung Kim.
* Don't enable annotation in non symbolic view, from Namhyung Kim.
* Fix pipe mode in 'report', from Namhyung Kim.
* Move related stats code from stat to util/, will be used by the 'stat'
kvm tool, from Xiao Guangrong.
* Add cpumask for uncore pmu, use it in 'stat', from Yan, Zheng.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
29 files changed, 318 insertions, 126 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 0a5571080e74..62ec3e6af7ea 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -2341,6 +2341,27 @@ int uncore_pmu_event_init(struct perf_event *event) | |||
2341 | return ret; | 2341 | return ret; |
2342 | } | 2342 | } |
2343 | 2343 | ||
2344 | static ssize_t uncore_get_attr_cpumask(struct device *dev, | ||
2345 | struct device_attribute *attr, char *buf) | ||
2346 | { | ||
2347 | int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &uncore_cpu_mask); | ||
2348 | |||
2349 | buf[n++] = '\n'; | ||
2350 | buf[n] = '\0'; | ||
2351 | return n; | ||
2352 | } | ||
2353 | |||
2354 | static DEVICE_ATTR(cpumask, S_IRUGO, uncore_get_attr_cpumask, NULL); | ||
2355 | |||
2356 | static struct attribute *uncore_pmu_attrs[] = { | ||
2357 | &dev_attr_cpumask.attr, | ||
2358 | NULL, | ||
2359 | }; | ||
2360 | |||
2361 | static struct attribute_group uncore_pmu_attr_group = { | ||
2362 | .attrs = uncore_pmu_attrs, | ||
2363 | }; | ||
2364 | |||
2344 | static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu) | 2365 | static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu) |
2345 | { | 2366 | { |
2346 | int ret; | 2367 | int ret; |
@@ -2378,8 +2399,8 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) | |||
2378 | free_percpu(type->pmus[i].box); | 2399 | free_percpu(type->pmus[i].box); |
2379 | kfree(type->pmus); | 2400 | kfree(type->pmus); |
2380 | type->pmus = NULL; | 2401 | type->pmus = NULL; |
2381 | kfree(type->attr_groups[1]); | 2402 | kfree(type->events_group); |
2382 | type->attr_groups[1] = NULL; | 2403 | type->events_group = NULL; |
2383 | } | 2404 | } |
2384 | 2405 | ||
2385 | static void __init uncore_types_exit(struct intel_uncore_type **types) | 2406 | static void __init uncore_types_exit(struct intel_uncore_type **types) |
@@ -2431,9 +2452,10 @@ static int __init uncore_type_init(struct intel_uncore_type *type) | |||
2431 | for (j = 0; j < i; j++) | 2452 | for (j = 0; j < i; j++) |
2432 | attrs[j] = &type->event_descs[j].attr.attr; | 2453 | attrs[j] = &type->event_descs[j].attr.attr; |
2433 | 2454 | ||
2434 | type->attr_groups[1] = events_group; | 2455 | type->events_group = events_group; |
2435 | } | 2456 | } |
2436 | 2457 | ||
2458 | type->pmu_group = &uncore_pmu_attr_group; | ||
2437 | type->pmus = pmus; | 2459 | type->pmus = pmus; |
2438 | return 0; | 2460 | return 0; |
2439 | fail: | 2461 | fail: |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 5b81c1856aac..e68a4550e952 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -369,10 +369,12 @@ struct intel_uncore_type { | |||
369 | struct intel_uncore_pmu *pmus; | 369 | struct intel_uncore_pmu *pmus; |
370 | struct intel_uncore_ops *ops; | 370 | struct intel_uncore_ops *ops; |
371 | struct uncore_event_desc *event_descs; | 371 | struct uncore_event_desc *event_descs; |
372 | const struct attribute_group *attr_groups[3]; | 372 | const struct attribute_group *attr_groups[4]; |
373 | }; | 373 | }; |
374 | 374 | ||
375 | #define format_group attr_groups[0] | 375 | #define pmu_group attr_groups[0] |
376 | #define format_group attr_groups[1] | ||
377 | #define events_group attr_groups[2] | ||
376 | 378 | ||
377 | struct intel_uncore_ops { | 379 | struct intel_uncore_ops { |
378 | void (*init_box)(struct intel_uncore_box *); | 380 | void (*init_box)(struct intel_uncore_box *); |
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 14131cb0522d..04d959fa0226 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile | |||
@@ -129,7 +129,7 @@ CFLAGS ?= -g -Wall | |||
129 | 129 | ||
130 | # Append required CFLAGS | 130 | # Append required CFLAGS |
131 | override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) | 131 | override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) |
132 | override CFLAGS += $(udis86-flags) | 132 | override CFLAGS += $(udis86-flags) -D_GNU_SOURCE |
133 | 133 | ||
134 | ifeq ($(VERBOSE),1) | 134 | ifeq ($(VERBOSE),1) |
135 | Q = | 135 | Q = |
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 2c54cdd8ae1b..77ebeb8266f4 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -24,7 +24,6 @@ | |||
24 | * Frederic Weisbecker gave his permission to relicense the code to | 24 | * Frederic Weisbecker gave his permission to relicense the code to |
25 | * the Lesser General Public License. | 25 | * the Lesser General Public License. |
26 | */ | 26 | */ |
27 | #define _GNU_SOURCE | ||
28 | #include <stdio.h> | 27 | #include <stdio.h> |
29 | #include <stdlib.h> | 28 | #include <stdlib.h> |
30 | #include <string.h> | 29 | #include <string.h> |
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 209774bcee2e..5077f8e2ef72 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -406,6 +406,7 @@ LIB_OBJS += $(OUTPUT)util/target.o | |||
406 | LIB_OBJS += $(OUTPUT)util/rblist.o | 406 | LIB_OBJS += $(OUTPUT)util/rblist.o |
407 | LIB_OBJS += $(OUTPUT)util/intlist.o | 407 | LIB_OBJS += $(OUTPUT)util/intlist.o |
408 | LIB_OBJS += $(OUTPUT)util/vdso.o | 408 | LIB_OBJS += $(OUTPUT)util/vdso.o |
409 | LIB_OBJS += $(OUTPUT)util/stat.o | ||
409 | 410 | ||
410 | LIB_OBJS += $(OUTPUT)ui/helpline.o | 411 | LIB_OBJS += $(OUTPUT)ui/helpline.o |
411 | LIB_OBJS += $(OUTPUT)ui/hist.o | 412 | LIB_OBJS += $(OUTPUT)ui/hist.o |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 97b2e6300f4c..1da243dfbc3e 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -93,7 +93,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, | |||
93 | struct annotation *notes; | 93 | struct annotation *notes; |
94 | err = -ENOMEM; | 94 | err = -ENOMEM; |
95 | bx = he->branch_info; | 95 | bx = he->branch_info; |
96 | if (bx->from.sym && use_browser > 0) { | 96 | if (bx->from.sym && use_browser == 1 && sort__has_sym) { |
97 | notes = symbol__annotation(bx->from.sym); | 97 | notes = symbol__annotation(bx->from.sym); |
98 | if (!notes->src | 98 | if (!notes->src |
99 | && symbol__alloc_hist(bx->from.sym) < 0) | 99 | && symbol__alloc_hist(bx->from.sym) < 0) |
@@ -107,7 +107,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, | |||
107 | goto out; | 107 | goto out; |
108 | } | 108 | } |
109 | 109 | ||
110 | if (bx->to.sym && use_browser > 0) { | 110 | if (bx->to.sym && use_browser == 1 && sort__has_sym) { |
111 | notes = symbol__annotation(bx->to.sym); | 111 | notes = symbol__annotation(bx->to.sym); |
112 | if (!notes->src | 112 | if (!notes->src |
113 | && symbol__alloc_hist(bx->to.sym) < 0) | 113 | && symbol__alloc_hist(bx->to.sym) < 0) |
@@ -162,7 +162,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, | |||
162 | * so we don't allocated the extra space needed because the stdio | 162 | * so we don't allocated the extra space needed because the stdio |
163 | * code will not use it. | 163 | * code will not use it. |
164 | */ | 164 | */ |
165 | if (he->ms.sym != NULL && use_browser > 0) { | 165 | if (he->ms.sym != NULL && use_browser == 1 && sort__has_sym) { |
166 | struct annotation *notes = symbol__annotation(he->ms.sym); | 166 | struct annotation *notes = symbol__annotation(he->ms.sym); |
167 | 167 | ||
168 | assert(evsel != NULL); | 168 | assert(evsel != NULL); |
@@ -689,15 +689,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
689 | 689 | ||
690 | if (strcmp(report.input_name, "-") != 0) | 690 | if (strcmp(report.input_name, "-") != 0) |
691 | setup_browser(true); | 691 | setup_browser(true); |
692 | else | 692 | else { |
693 | use_browser = 0; | 693 | use_browser = 0; |
694 | perf_hpp__init(false, false); | ||
695 | } | ||
696 | |||
697 | setup_sorting(report_usage, options); | ||
694 | 698 | ||
695 | /* | 699 | /* |
696 | * Only in the newt browser we are doing integrated annotation, | 700 | * Only in the newt browser we are doing integrated annotation, |
697 | * so don't allocate extra space that won't be used in the stdio | 701 | * so don't allocate extra space that won't be used in the stdio |
698 | * implementation. | 702 | * implementation. |
699 | */ | 703 | */ |
700 | if (use_browser > 0) { | 704 | if (use_browser == 1 && sort__has_sym) { |
701 | symbol_conf.priv_size = sizeof(struct annotation); | 705 | symbol_conf.priv_size = sizeof(struct annotation); |
702 | report.annotate_init = symbol__annotate_init; | 706 | report.annotate_init = symbol__annotate_init; |
703 | /* | 707 | /* |
@@ -720,8 +724,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
720 | if (symbol__init() < 0) | 724 | if (symbol__init() < 0) |
721 | goto error; | 725 | goto error; |
722 | 726 | ||
723 | setup_sorting(report_usage, options); | ||
724 | |||
725 | if (parent_pattern != default_parent_pattern) { | 727 | if (parent_pattern != default_parent_pattern) { |
726 | if (sort_dimension__add("parent") < 0) | 728 | if (sort_dimension__add("parent") < 0) |
727 | goto error; | 729 | goto error; |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index af305f57bd22..9b9e32eaa805 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -438,8 +438,8 @@ static int self_open_counters(void) | |||
438 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | 438 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); |
439 | 439 | ||
440 | if (fd < 0) | 440 | if (fd < 0) |
441 | pr_debug("Error: sys_perf_event_open() syscall returned" | 441 | pr_err("Error: sys_perf_event_open() syscall returned " |
442 | "with %d (%s)\n", fd, strerror(errno)); | 442 | "with %d (%s)\n", fd, strerror(errno)); |
443 | return fd; | 443 | return fd; |
444 | } | 444 | } |
445 | 445 | ||
@@ -700,7 +700,7 @@ static int replay_switch_event(struct perf_sched *sched, | |||
700 | delta = 0; | 700 | delta = 0; |
701 | 701 | ||
702 | if (delta < 0) { | 702 | if (delta < 0) { |
703 | pr_debug("hm, delta: %" PRIu64 " < 0 ?\n", delta); | 703 | pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); |
704 | return -1; | 704 | return -1; |
705 | } | 705 | } |
706 | 706 | ||
@@ -990,7 +990,7 @@ static int latency_runtime_event(struct perf_sched *sched, | |||
990 | return -1; | 990 | return -1; |
991 | atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); | 991 | atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); |
992 | if (!atoms) { | 992 | if (!atoms) { |
993 | pr_debug("in-event: Internal tree error"); | 993 | pr_err("in-event: Internal tree error"); |
994 | return -1; | 994 | return -1; |
995 | } | 995 | } |
996 | if (add_sched_out_event(atoms, 'R', timestamp)) | 996 | if (add_sched_out_event(atoms, 'R', timestamp)) |
@@ -1024,7 +1024,7 @@ static int latency_wakeup_event(struct perf_sched *sched, | |||
1024 | return -1; | 1024 | return -1; |
1025 | atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); | 1025 | atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); |
1026 | if (!atoms) { | 1026 | if (!atoms) { |
1027 | pr_debug("wakeup-event: Internal tree error"); | 1027 | pr_err("wakeup-event: Internal tree error"); |
1028 | return -1; | 1028 | return -1; |
1029 | } | 1029 | } |
1030 | if (add_sched_out_event(atoms, 'S', timestamp)) | 1030 | if (add_sched_out_event(atoms, 'S', timestamp)) |
@@ -1079,7 +1079,7 @@ static int latency_migrate_task_event(struct perf_sched *sched, | |||
1079 | register_pid(sched, migrant->pid, migrant->comm); | 1079 | register_pid(sched, migrant->pid, migrant->comm); |
1080 | atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); | 1080 | atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); |
1081 | if (!atoms) { | 1081 | if (!atoms) { |
1082 | pr_debug("migration-event: Internal tree error"); | 1082 | pr_err("migration-event: Internal tree error"); |
1083 | return -1; | 1083 | return -1; |
1084 | } | 1084 | } |
1085 | if (add_sched_out_event(atoms, 'R', timestamp)) | 1085 | if (add_sched_out_event(atoms, 'R', timestamp)) |
@@ -1286,7 +1286,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, | |||
1286 | delta = 0; | 1286 | delta = 0; |
1287 | 1287 | ||
1288 | if (delta < 0) { | 1288 | if (delta < 0) { |
1289 | pr_debug("hm, delta: %" PRIu64 " < 0 ?\n", delta); | 1289 | pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); |
1290 | return -1; | 1290 | return -1; |
1291 | } | 1291 | } |
1292 | 1292 | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 6d98a83d5a60..1be843aa1546 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "util/util.h" | 14 | #include "util/util.h" |
15 | #include "util/evlist.h" | 15 | #include "util/evlist.h" |
16 | #include "util/evsel.h" | 16 | #include "util/evsel.h" |
17 | #include "util/sort.h" | ||
17 | #include <linux/bitmap.h> | 18 | #include <linux/bitmap.h> |
18 | 19 | ||
19 | static char const *script_name; | 20 | static char const *script_name; |
@@ -1031,6 +1032,61 @@ static int list_available_scripts(const struct option *opt __maybe_unused, | |||
1031 | exit(0); | 1032 | exit(0); |
1032 | } | 1033 | } |
1033 | 1034 | ||
1035 | /* | ||
1036 | * Return -1 if none is found, otherwise the actual scripts number. | ||
1037 | * | ||
1038 | * Currently the only user of this function is the script browser, which | ||
1039 | * will list all statically runnable scripts, select one, execute it and | ||
1040 | * show the output in a perf browser. | ||
1041 | */ | ||
1042 | int find_scripts(char **scripts_array, char **scripts_path_array) | ||
1043 | { | ||
1044 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; | ||
1045 | char scripts_path[MAXPATHLEN]; | ||
1046 | DIR *scripts_dir, *lang_dir; | ||
1047 | char lang_path[MAXPATHLEN]; | ||
1048 | char *temp; | ||
1049 | int i = 0; | ||
1050 | |||
1051 | snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); | ||
1052 | |||
1053 | scripts_dir = opendir(scripts_path); | ||
1054 | if (!scripts_dir) | ||
1055 | return -1; | ||
1056 | |||
1057 | for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { | ||
1058 | snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, | ||
1059 | lang_dirent.d_name); | ||
1060 | #ifdef NO_LIBPERL | ||
1061 | if (strstr(lang_path, "perl")) | ||
1062 | continue; | ||
1063 | #endif | ||
1064 | #ifdef NO_LIBPYTHON | ||
1065 | if (strstr(lang_path, "python")) | ||
1066 | continue; | ||
1067 | #endif | ||
1068 | |||
1069 | lang_dir = opendir(lang_path); | ||
1070 | if (!lang_dir) | ||
1071 | continue; | ||
1072 | |||
1073 | for_each_script(lang_path, lang_dir, script_dirent, script_next) { | ||
1074 | /* Skip those real time scripts: xxxtop.p[yl] */ | ||
1075 | if (strstr(script_dirent.d_name, "top.")) | ||
1076 | continue; | ||
1077 | sprintf(scripts_path_array[i], "%s/%s", lang_path, | ||
1078 | script_dirent.d_name); | ||
1079 | temp = strchr(script_dirent.d_name, '.'); | ||
1080 | snprintf(scripts_array[i], | ||
1081 | (temp - script_dirent.d_name) + 1, | ||
1082 | "%s", script_dirent.d_name); | ||
1083 | i++; | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | return i; | ||
1088 | } | ||
1089 | |||
1034 | static char *get_script_path(const char *script_root, const char *suffix) | 1090 | static char *get_script_path(const char *script_root, const char *suffix) |
1035 | { | 1091 | { |
1036 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; | 1092 | struct dirent *script_next, *lang_next, script_dirent, lang_dirent; |
@@ -1143,6 +1199,8 @@ static const struct option options[] = { | |||
1143 | parse_output_fields), | 1199 | parse_output_fields), |
1144 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 1200 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
1145 | "system-wide collection from all CPUs"), | 1201 | "system-wide collection from all CPUs"), |
1202 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", | ||
1203 | "only consider these symbols"), | ||
1146 | OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), | 1204 | OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), |
1147 | OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", | 1205 | OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", |
1148 | "only display events for these comms"), | 1206 | "only display events for these comms"), |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index dab347d7b010..e0f65fe65944 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -51,13 +51,13 @@ | |||
51 | #include "util/evsel.h" | 51 | #include "util/evsel.h" |
52 | #include "util/debug.h" | 52 | #include "util/debug.h" |
53 | #include "util/color.h" | 53 | #include "util/color.h" |
54 | #include "util/stat.h" | ||
54 | #include "util/header.h" | 55 | #include "util/header.h" |
55 | #include "util/cpumap.h" | 56 | #include "util/cpumap.h" |
56 | #include "util/thread.h" | 57 | #include "util/thread.h" |
57 | #include "util/thread_map.h" | 58 | #include "util/thread_map.h" |
58 | 59 | ||
59 | #include <sys/prctl.h> | 60 | #include <sys/prctl.h> |
60 | #include <math.h> | ||
61 | #include <locale.h> | 61 | #include <locale.h> |
62 | 62 | ||
63 | #define DEFAULT_SEPARATOR " " | 63 | #define DEFAULT_SEPARATOR " " |
@@ -199,11 +199,6 @@ static int output_fd; | |||
199 | 199 | ||
200 | static volatile int done = 0; | 200 | static volatile int done = 0; |
201 | 201 | ||
202 | struct stats | ||
203 | { | ||
204 | double n, mean, M2; | ||
205 | }; | ||
206 | |||
207 | struct perf_stat { | 202 | struct perf_stat { |
208 | struct stats res_stats[3]; | 203 | struct stats res_stats[3]; |
209 | }; | 204 | }; |
@@ -220,48 +215,14 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) | |||
220 | evsel->priv = NULL; | 215 | evsel->priv = NULL; |
221 | } | 216 | } |
222 | 217 | ||
223 | static void update_stats(struct stats *stats, u64 val) | 218 | static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) |
224 | { | 219 | { |
225 | double delta; | 220 | return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; |
226 | |||
227 | stats->n++; | ||
228 | delta = val - stats->mean; | ||
229 | stats->mean += delta / stats->n; | ||
230 | stats->M2 += delta*(val - stats->mean); | ||
231 | } | 221 | } |
232 | 222 | ||
233 | static double avg_stats(struct stats *stats) | 223 | static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) |
234 | { | ||
235 | return stats->mean; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance | ||
240 | * | ||
241 | * (\Sum n_i^2) - ((\Sum n_i)^2)/n | ||
242 | * s^2 = ------------------------------- | ||
243 | * n - 1 | ||
244 | * | ||
245 | * http://en.wikipedia.org/wiki/Stddev | ||
246 | * | ||
247 | * The std dev of the mean is related to the std dev by: | ||
248 | * | ||
249 | * s | ||
250 | * s_mean = ------- | ||
251 | * sqrt(n) | ||
252 | * | ||
253 | */ | ||
254 | static double stddev_stats(struct stats *stats) | ||
255 | { | 224 | { |
256 | double variance, variance_mean; | 225 | return perf_evsel__cpus(evsel)->nr; |
257 | |||
258 | if (!stats->n) | ||
259 | return 0.0; | ||
260 | |||
261 | variance = stats->M2 / (stats->n - 1); | ||
262 | variance_mean = variance / stats->n; | ||
263 | |||
264 | return sqrt(variance_mean); | ||
265 | } | 226 | } |
266 | 227 | ||
267 | static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; | 228 | static struct stats runtime_nsecs_stats[MAX_NR_CPUS]; |
@@ -295,7 +256,7 @@ retry: | |||
295 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; | 256 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; |
296 | 257 | ||
297 | if (perf_target__has_cpu(&target)) { | 258 | if (perf_target__has_cpu(&target)) { |
298 | ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus); | 259 | ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); |
299 | if (ret) | 260 | if (ret) |
300 | goto check_ret; | 261 | goto check_ret; |
301 | return 0; | 262 | return 0; |
@@ -376,7 +337,7 @@ static int read_counter_aggr(struct perf_evsel *counter) | |||
376 | u64 *count = counter->counts->aggr.values; | 337 | u64 *count = counter->counts->aggr.values; |
377 | int i; | 338 | int i; |
378 | 339 | ||
379 | if (__perf_evsel__read(counter, evsel_list->cpus->nr, | 340 | if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter), |
380 | evsel_list->threads->nr, scale) < 0) | 341 | evsel_list->threads->nr, scale) < 0) |
381 | return -1; | 342 | return -1; |
382 | 343 | ||
@@ -405,7 +366,7 @@ static int read_counter(struct perf_evsel *counter) | |||
405 | u64 *count; | 366 | u64 *count; |
406 | int cpu; | 367 | int cpu; |
407 | 368 | ||
408 | for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { | 369 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { |
409 | if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) | 370 | if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) |
410 | return -1; | 371 | return -1; |
411 | 372 | ||
@@ -544,12 +505,12 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) | |||
544 | if (no_aggr) { | 505 | if (no_aggr) { |
545 | list_for_each_entry(counter, &evsel_list->entries, node) { | 506 | list_for_each_entry(counter, &evsel_list->entries, node) { |
546 | read_counter(counter); | 507 | read_counter(counter); |
547 | perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1); | 508 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); |
548 | } | 509 | } |
549 | } else { | 510 | } else { |
550 | list_for_each_entry(counter, &evsel_list->entries, node) { | 511 | list_for_each_entry(counter, &evsel_list->entries, node) { |
551 | read_counter_aggr(counter); | 512 | read_counter_aggr(counter); |
552 | perf_evsel__close_fd(counter, evsel_list->cpus->nr, | 513 | perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), |
553 | evsel_list->threads->nr); | 514 | evsel_list->threads->nr); |
554 | } | 515 | } |
555 | } | 516 | } |
@@ -559,10 +520,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) | |||
559 | 520 | ||
560 | static void print_noise_pct(double total, double avg) | 521 | static void print_noise_pct(double total, double avg) |
561 | { | 522 | { |
562 | double pct = 0.0; | 523 | double pct = rel_stddev_stats(total, avg); |
563 | |||
564 | if (avg) | ||
565 | pct = 100.0*total/avg; | ||
566 | 524 | ||
567 | if (csv_output) | 525 | if (csv_output) |
568 | fprintf(output, "%s%.2f%%", csv_sep, pct); | 526 | fprintf(output, "%s%.2f%%", csv_sep, pct); |
@@ -590,7 +548,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg) | |||
590 | if (no_aggr) | 548 | if (no_aggr) |
591 | sprintf(cpustr, "CPU%*d%s", | 549 | sprintf(cpustr, "CPU%*d%s", |
592 | csv_output ? 0 : -4, | 550 | csv_output ? 0 : -4, |
593 | evsel_list->cpus->map[cpu], csv_sep); | 551 | perf_evsel__cpus(evsel)->map[cpu], csv_sep); |
594 | 552 | ||
595 | fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel)); | 553 | fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel)); |
596 | 554 | ||
@@ -802,7 +760,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) | |||
802 | if (no_aggr) | 760 | if (no_aggr) |
803 | sprintf(cpustr, "CPU%*d%s", | 761 | sprintf(cpustr, "CPU%*d%s", |
804 | csv_output ? 0 : -4, | 762 | csv_output ? 0 : -4, |
805 | evsel_list->cpus->map[cpu], csv_sep); | 763 | perf_evsel__cpus(evsel)->map[cpu], csv_sep); |
806 | else | 764 | else |
807 | cpu = 0; | 765 | cpu = 0; |
808 | 766 | ||
@@ -963,14 +921,14 @@ static void print_counter(struct perf_evsel *counter) | |||
963 | u64 ena, run, val; | 921 | u64 ena, run, val; |
964 | int cpu; | 922 | int cpu; |
965 | 923 | ||
966 | for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) { | 924 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { |
967 | val = counter->counts->cpu[cpu].val; | 925 | val = counter->counts->cpu[cpu].val; |
968 | ena = counter->counts->cpu[cpu].ena; | 926 | ena = counter->counts->cpu[cpu].ena; |
969 | run = counter->counts->cpu[cpu].run; | 927 | run = counter->counts->cpu[cpu].run; |
970 | if (run == 0 || ena == 0) { | 928 | if (run == 0 || ena == 0) { |
971 | fprintf(output, "CPU%*d%s%*s%s%*s", | 929 | fprintf(output, "CPU%*d%s%*s%s%*s", |
972 | csv_output ? 0 : -4, | 930 | csv_output ? 0 : -4, |
973 | evsel_list->cpus->map[cpu], csv_sep, | 931 | perf_evsel__cpus(counter)->map[cpu], csv_sep, |
974 | csv_output ? 0 : 18, | 932 | csv_output ? 0 : 18, |
975 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, | 933 | counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, |
976 | csv_sep, | 934 | csv_sep, |
@@ -1269,7 +1227,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1269 | 1227 | ||
1270 | list_for_each_entry(pos, &evsel_list->entries, node) { | 1228 | list_for_each_entry(pos, &evsel_list->entries, node) { |
1271 | if (perf_evsel__alloc_stat_priv(pos) < 0 || | 1229 | if (perf_evsel__alloc_stat_priv(pos) < 0 || |
1272 | perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0) | 1230 | perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0) |
1273 | goto out_free_fd; | 1231 | goto out_free_fd; |
1274 | } | 1232 | } |
1275 | 1233 | ||
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index d33143efefce..4aed1553db56 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c | |||
@@ -1026,15 +1026,15 @@ static int __test__rdpmc(void) | |||
1026 | 1026 | ||
1027 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | 1027 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); |
1028 | if (fd < 0) { | 1028 | if (fd < 0) { |
1029 | pr_debug("Error: sys_perf_event_open() syscall returned " | 1029 | pr_err("Error: sys_perf_event_open() syscall returned " |
1030 | "with %d (%s)\n", fd, strerror(errno)); | 1030 | "with %d (%s)\n", fd, strerror(errno)); |
1031 | return -1; | 1031 | return -1; |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); | 1034 | addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); |
1035 | if (addr == (void *)(-1)) { | 1035 | if (addr == (void *)(-1)) { |
1036 | pr_debug("Error: mmap() syscall returned with (%s)\n", | 1036 | pr_err("Error: mmap() syscall returned with (%s)\n", |
1037 | strerror(errno)); | 1037 | strerror(errno)); |
1038 | goto out_close; | 1038 | goto out_close; |
1039 | } | 1039 | } |
1040 | 1040 | ||
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index b382bd551aac..3ea74ed1b26b 100644 --- a/tools/perf/builtin.h +++ b/tools/perf/builtin.h | |||
@@ -36,4 +36,5 @@ extern int cmd_kvm(int argc, const char **argv, const char *prefix); | |||
36 | extern int cmd_test(int argc, const char **argv, const char *prefix); | 36 | extern int cmd_test(int argc, const char **argv, const char *prefix); |
37 | extern int cmd_inject(int argc, const char **argv, const char *prefix); | 37 | extern int cmd_inject(int argc, const char **argv, const char *prefix); |
38 | 38 | ||
39 | extern int find_scripts(char **scripts_array, char **scripts_path_array); | ||
39 | #endif | 40 | #endif |
diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh index 95b6f8b6177a..e91930620269 100644 --- a/tools/perf/perf-archive.sh +++ b/tools/perf/perf-archive.sh | |||
@@ -24,7 +24,7 @@ NOBUILDID=0000000000000000000000000000000000000000 | |||
24 | perf buildid-list -i $PERF_DATA --with-hits | grep -v "^$NOBUILDID " > $BUILDIDS | 24 | perf buildid-list -i $PERF_DATA --with-hits | grep -v "^$NOBUILDID " > $BUILDIDS |
25 | if [ ! -s $BUILDIDS ] ; then | 25 | if [ ! -s $BUILDIDS ] ; then |
26 | echo "perf archive: no build-ids found" | 26 | echo "perf archive: no build-ids found" |
27 | rm -f $BUILDIDS | 27 | rm $BUILDIDS || true |
28 | exit 1 | 28 | exit 1 |
29 | fi | 29 | fi |
30 | 30 | ||
@@ -39,8 +39,8 @@ while read build_id ; do | |||
39 | echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST | 39 | echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST |
40 | done | 40 | done |
41 | 41 | ||
42 | tar cfj $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST | 42 | tar cjf $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST |
43 | rm -f $MANIFEST $BUILDIDS | 43 | rm $MANIFEST $BUILDIDS || true |
44 | echo -e "Now please run:\n" | 44 | echo -e "Now please run:\n" |
45 | echo -e "$ tar xvf $PERF_DATA.tar.bz2 -C ~/.debug\n" | 45 | echo -e "$ tar xvf $PERF_DATA.tar.bz2 -C ~/.debug\n" |
46 | echo "wherever you need to run 'perf report' on." | 46 | echo "wherever you need to run 'perf report' on." |
diff --git a/tools/perf/scripts/python/bin/event_analyzing_sample-record b/tools/perf/scripts/python/bin/event_analyzing_sample-record new file mode 100644 index 000000000000..5ce652dabd02 --- /dev/null +++ b/tools/perf/scripts/python/bin/event_analyzing_sample-record | |||
@@ -0,0 +1,8 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # | ||
4 | # event_analyzing_sample.py can cover all type of perf samples including | ||
5 | # the tracepoints, so no special record requirements, just record what | ||
6 | # you want to analyze. | ||
7 | # | ||
8 | perf record $@ | ||
diff --git a/tools/perf/scripts/python/bin/event_analyzing_sample-report b/tools/perf/scripts/python/bin/event_analyzing_sample-report new file mode 100644 index 000000000000..0941fc94e158 --- /dev/null +++ b/tools/perf/scripts/python/bin/event_analyzing_sample-report | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/bash | ||
2 | # description: analyze all perf samples | ||
3 | perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/event_analyzing_sample.py | ||
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 5a5739bbe6ac..a21f40bebbac 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -571,7 +571,7 @@ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ | |||
571 | { \ | 571 | { \ |
572 | double percent = 100.0 * he->_field / hpp->total_period; \ | 572 | double percent = 100.0 * he->_field / hpp->total_period; \ |
573 | *(double *)hpp->ptr = percent; \ | 573 | *(double *)hpp->ptr = percent; \ |
574 | return scnprintf(hpp->buf, hpp->size, "%5.2f%%", percent); \ | 574 | return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \ |
575 | } | 575 | } |
576 | 576 | ||
577 | HPP__COLOR_FN(overhead, period) | 577 | HPP__COLOR_FN(overhead, period) |
@@ -605,7 +605,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
605 | char s[256]; | 605 | char s[256]; |
606 | double percent; | 606 | double percent; |
607 | int i, printed = 0; | 607 | int i, printed = 0; |
608 | int width = browser->b.width - 1; | 608 | int width = browser->b.width; |
609 | char folded_sign = ' '; | 609 | char folded_sign = ' '; |
610 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); | 610 | bool current_entry = ui_browser__is_current_entry(&browser->b, row); |
611 | off_t row_offset = entry->row_offset; | 611 | off_t row_offset = entry->row_offset; |
@@ -627,7 +627,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
627 | .total_period = browser->hists->stats.total_period, | 627 | .total_period = browser->hists->stats.total_period, |
628 | }; | 628 | }; |
629 | 629 | ||
630 | ui_browser__gotorc(&browser->b, row, 1); | 630 | ui_browser__gotorc(&browser->b, row, 0); |
631 | 631 | ||
632 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { | 632 | for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { |
633 | if (!perf_hpp__format[i].cond) | 633 | if (!perf_hpp__format[i].cond) |
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 55acba6e0df4..7ff99ec1d95e 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c | |||
@@ -56,7 +56,7 @@ static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ | |||
56 | markup = perf_gtk__get_percent_color(percent); \ | 56 | markup = perf_gtk__get_percent_color(percent); \ |
57 | if (markup) \ | 57 | if (markup) \ |
58 | ret += scnprintf(hpp->buf, hpp->size, "%s", markup); \ | 58 | ret += scnprintf(hpp->buf, hpp->size, "%s", markup); \ |
59 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%5.2f%%", percent); \ | 59 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent); \ |
60 | if (markup) \ | 60 | if (markup) \ |
61 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); \ | 61 | ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); \ |
62 | \ | 62 | \ |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 407e855cccb8..e3f8cd46e7d7 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -33,13 +33,13 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) | |||
33 | percent = 0.0; | 33 | percent = 0.0; |
34 | } | 34 | } |
35 | 35 | ||
36 | return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%%", percent); | 36 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); |
37 | } | 37 | } |
38 | 38 | ||
39 | static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) | 39 | static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) |
40 | { | 40 | { |
41 | double percent = 100.0 * he->period / hpp->total_period; | 41 | double percent = 100.0 * he->period / hpp->total_period; |
42 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%%"; | 42 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; |
43 | 43 | ||
44 | if (hpp->ptr) { | 44 | if (hpp->ptr) { |
45 | struct hists *old_hists = hpp->ptr; | 45 | struct hists *old_hists = hpp->ptr; |
@@ -57,52 +57,52 @@ static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) | |||
57 | 57 | ||
58 | static int hpp__header_overhead_sys(struct perf_hpp *hpp) | 58 | static int hpp__header_overhead_sys(struct perf_hpp *hpp) |
59 | { | 59 | { |
60 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6s"; | 60 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; |
61 | 61 | ||
62 | return scnprintf(hpp->buf, hpp->size, fmt, "sys"); | 62 | return scnprintf(hpp->buf, hpp->size, fmt, "sys"); |
63 | } | 63 | } |
64 | 64 | ||
65 | static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) | 65 | static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) |
66 | { | 66 | { |
67 | return 6; | 67 | return 7; |
68 | } | 68 | } |
69 | 69 | ||
70 | static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | 70 | static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) |
71 | { | 71 | { |
72 | double percent = 100.0 * he->period_sys / hpp->total_period; | 72 | double percent = 100.0 * he->period_sys / hpp->total_period; |
73 | return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent); | 73 | return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); |
74 | } | 74 | } |
75 | 75 | ||
76 | static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | 76 | static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) |
77 | { | 77 | { |
78 | double percent = 100.0 * he->period_sys / hpp->total_period; | 78 | double percent = 100.0 * he->period_sys / hpp->total_period; |
79 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%5.2f%%"; | 79 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; |
80 | 80 | ||
81 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 81 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
82 | } | 82 | } |
83 | 83 | ||
84 | static int hpp__header_overhead_us(struct perf_hpp *hpp) | 84 | static int hpp__header_overhead_us(struct perf_hpp *hpp) |
85 | { | 85 | { |
86 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6s"; | 86 | const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; |
87 | 87 | ||
88 | return scnprintf(hpp->buf, hpp->size, fmt, "user"); | 88 | return scnprintf(hpp->buf, hpp->size, fmt, "user"); |
89 | } | 89 | } |
90 | 90 | ||
91 | static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) | 91 | static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused) |
92 | { | 92 | { |
93 | return 6; | 93 | return 7; |
94 | } | 94 | } |
95 | 95 | ||
96 | static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | 96 | static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) |
97 | { | 97 | { |
98 | double percent = 100.0 * he->period_us / hpp->total_period; | 98 | double percent = 100.0 * he->period_us / hpp->total_period; |
99 | return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent); | 99 | return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); |
100 | } | 100 | } |
101 | 101 | ||
102 | static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | 102 | static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) |
103 | { | 103 | { |
104 | double percent = 100.0 * he->period_us / hpp->total_period; | 104 | double percent = 100.0 * he->period_us / hpp->total_period; |
105 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%5.2f%%"; | 105 | const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; |
106 | 106 | ||
107 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 107 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
108 | } | 108 | } |
@@ -121,14 +121,14 @@ static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, | |||
121 | struct hist_entry *he) | 121 | struct hist_entry *he) |
122 | { | 122 | { |
123 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; | 123 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; |
124 | return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent); | 124 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, | 127 | static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, |
128 | struct hist_entry *he) | 128 | struct hist_entry *he) |
129 | { | 129 | { |
130 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; | 130 | double percent = 100.0 * he->period_guest_sys / hpp->total_period; |
131 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%% "; | 131 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; |
132 | 132 | ||
133 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 133 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
134 | } | 134 | } |
@@ -147,14 +147,14 @@ static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, | |||
147 | struct hist_entry *he) | 147 | struct hist_entry *he) |
148 | { | 148 | { |
149 | double percent = 100.0 * he->period_guest_us / hpp->total_period; | 149 | double percent = 100.0 * he->period_guest_us / hpp->total_period; |
150 | return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent); | 150 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); |
151 | } | 151 | } |
152 | 152 | ||
153 | static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, | 153 | static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, |
154 | struct hist_entry *he) | 154 | struct hist_entry *he) |
155 | { | 155 | { |
156 | double percent = 100.0 * he->period_guest_us / hpp->total_period; | 156 | double percent = 100.0 * he->period_guest_us / hpp->total_period; |
157 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %5.2f%% "; | 157 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; |
158 | 158 | ||
159 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 159 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
160 | } | 160 | } |
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index adc72f09914d..2b32ffa9ebdb 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
@@ -38,24 +38,19 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) | |||
38 | return cpus; | 38 | return cpus; |
39 | } | 39 | } |
40 | 40 | ||
41 | static struct cpu_map *cpu_map__read_all_cpu_map(void) | 41 | struct cpu_map *cpu_map__read(FILE *file) |
42 | { | 42 | { |
43 | struct cpu_map *cpus = NULL; | 43 | struct cpu_map *cpus = NULL; |
44 | FILE *onlnf; | ||
45 | int nr_cpus = 0; | 44 | int nr_cpus = 0; |
46 | int *tmp_cpus = NULL, *tmp; | 45 | int *tmp_cpus = NULL, *tmp; |
47 | int max_entries = 0; | 46 | int max_entries = 0; |
48 | int n, cpu, prev; | 47 | int n, cpu, prev; |
49 | char sep; | 48 | char sep; |
50 | 49 | ||
51 | onlnf = fopen("/sys/devices/system/cpu/online", "r"); | ||
52 | if (!onlnf) | ||
53 | return cpu_map__default_new(); | ||
54 | |||
55 | sep = 0; | 50 | sep = 0; |
56 | prev = -1; | 51 | prev = -1; |
57 | for (;;) { | 52 | for (;;) { |
58 | n = fscanf(onlnf, "%u%c", &cpu, &sep); | 53 | n = fscanf(file, "%u%c", &cpu, &sep); |
59 | if (n <= 0) | 54 | if (n <= 0) |
60 | break; | 55 | break; |
61 | if (prev >= 0) { | 56 | if (prev >= 0) { |
@@ -95,6 +90,19 @@ static struct cpu_map *cpu_map__read_all_cpu_map(void) | |||
95 | cpus = cpu_map__default_new(); | 90 | cpus = cpu_map__default_new(); |
96 | out_free_tmp: | 91 | out_free_tmp: |
97 | free(tmp_cpus); | 92 | free(tmp_cpus); |
93 | return cpus; | ||
94 | } | ||
95 | |||
96 | static struct cpu_map *cpu_map__read_all_cpu_map(void) | ||
97 | { | ||
98 | struct cpu_map *cpus = NULL; | ||
99 | FILE *onlnf; | ||
100 | |||
101 | onlnf = fopen("/sys/devices/system/cpu/online", "r"); | ||
102 | if (!onlnf) | ||
103 | return cpu_map__default_new(); | ||
104 | |||
105 | cpus = cpu_map__read(onlnf); | ||
98 | fclose(onlnf); | 106 | fclose(onlnf); |
99 | return cpus; | 107 | return cpus; |
100 | } | 108 | } |
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index c41518573c6a..17b5264f6436 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h | |||
@@ -11,7 +11,7 @@ struct cpu_map { | |||
11 | struct cpu_map *cpu_map__new(const char *cpu_list); | 11 | struct cpu_map *cpu_map__new(const char *cpu_list); |
12 | struct cpu_map *cpu_map__dummy_new(void); | 12 | struct cpu_map *cpu_map__dummy_new(void); |
13 | void cpu_map__delete(struct cpu_map *map); | 13 | void cpu_map__delete(struct cpu_map *map); |
14 | 14 | struct cpu_map *cpu_map__read(FILE *file); | |
15 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); | 15 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); |
16 | 16 | ||
17 | #endif /* __PERF_CPUMAP_H */ | 17 | #endif /* __PERF_CPUMAP_H */ |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 8202f5ca0483..6715b1938725 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -904,8 +904,9 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
904 | al->sym = map__find_symbol(al->map, al->addr, filter); | 904 | al->sym = map__find_symbol(al->map, al->addr, filter); |
905 | } | 905 | } |
906 | 906 | ||
907 | if (symbol_conf.sym_list && al->sym && | 907 | if (symbol_conf.sym_list && |
908 | !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) | 908 | (!al->sym || !strlist__has_entry(symbol_conf.sym_list, |
909 | al->sym->name))) | ||
909 | goto out_filtered; | 910 | goto out_filtered; |
910 | 911 | ||
911 | return 0; | 912 | return 0; |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index dc40fe32210b..93876bad2e52 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -66,6 +66,7 @@ struct perf_evsel { | |||
66 | void *func; | 66 | void *func; |
67 | void *data; | 67 | void *data; |
68 | } handler; | 68 | } handler; |
69 | struct cpu_map *cpus; | ||
69 | unsigned int sample_size; | 70 | unsigned int sample_size; |
70 | bool supported; | 71 | bool supported; |
71 | /* parse modifier helper */ | 72 | /* parse modifier helper */ |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 44afcf40f796..bf5d033ee1b4 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -239,8 +239,11 @@ const char *event_type(int type) | |||
239 | return "unknown"; | 239 | return "unknown"; |
240 | } | 240 | } |
241 | 241 | ||
242 | static int add_event(struct list_head **_list, int *idx, | 242 | |
243 | struct perf_event_attr *attr, char *name) | 243 | |
244 | static int __add_event(struct list_head **_list, int *idx, | ||
245 | struct perf_event_attr *attr, | ||
246 | char *name, struct cpu_map *cpus) | ||
244 | { | 247 | { |
245 | struct perf_evsel *evsel; | 248 | struct perf_evsel *evsel; |
246 | struct list_head *list = *_list; | 249 | struct list_head *list = *_list; |
@@ -260,6 +263,7 @@ static int add_event(struct list_head **_list, int *idx, | |||
260 | return -ENOMEM; | 263 | return -ENOMEM; |
261 | } | 264 | } |
262 | 265 | ||
266 | evsel->cpus = cpus; | ||
263 | if (name) | 267 | if (name) |
264 | evsel->name = strdup(name); | 268 | evsel->name = strdup(name); |
265 | list_add_tail(&evsel->node, list); | 269 | list_add_tail(&evsel->node, list); |
@@ -267,6 +271,12 @@ static int add_event(struct list_head **_list, int *idx, | |||
267 | return 0; | 271 | return 0; |
268 | } | 272 | } |
269 | 273 | ||
274 | static int add_event(struct list_head **_list, int *idx, | ||
275 | struct perf_event_attr *attr, char *name) | ||
276 | { | ||
277 | return __add_event(_list, idx, attr, name, NULL); | ||
278 | } | ||
279 | |||
270 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) | 280 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) |
271 | { | 281 | { |
272 | int i, j; | 282 | int i, j; |
@@ -607,8 +617,8 @@ int parse_events_add_pmu(struct list_head **list, int *idx, | |||
607 | if (perf_pmu__config(pmu, &attr, head_config)) | 617 | if (perf_pmu__config(pmu, &attr, head_config)) |
608 | return -EINVAL; | 618 | return -EINVAL; |
609 | 619 | ||
610 | return add_event(list, idx, &attr, | 620 | return __add_event(list, idx, &attr, pmu_event_name(head_config), |
611 | pmu_event_name(head_config)); | 621 | pmu->cpus); |
612 | } | 622 | } |
613 | 623 | ||
614 | int parse_events__modifier_group(struct list_head *list, | 624 | int parse_events__modifier_group(struct list_head *list, |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 6631d828db3d..8a2229da594f 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "util.h" | 9 | #include "util.h" |
10 | #include "pmu.h" | 10 | #include "pmu.h" |
11 | #include "parse-events.h" | 11 | #include "parse-events.h" |
12 | #include "cpumap.h" | ||
12 | 13 | ||
13 | #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" | 14 | #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" |
14 | 15 | ||
@@ -253,6 +254,33 @@ static void pmu_read_sysfs(void) | |||
253 | closedir(dir); | 254 | closedir(dir); |
254 | } | 255 | } |
255 | 256 | ||
257 | static struct cpu_map *pmu_cpumask(char *name) | ||
258 | { | ||
259 | struct stat st; | ||
260 | char path[PATH_MAX]; | ||
261 | const char *sysfs; | ||
262 | FILE *file; | ||
263 | struct cpu_map *cpus; | ||
264 | |||
265 | sysfs = sysfs_find_mountpoint(); | ||
266 | if (!sysfs) | ||
267 | return NULL; | ||
268 | |||
269 | snprintf(path, PATH_MAX, | ||
270 | "%s/bus/event_source/devices/%s/cpumask", sysfs, name); | ||
271 | |||
272 | if (stat(path, &st) < 0) | ||
273 | return NULL; | ||
274 | |||
275 | file = fopen(path, "r"); | ||
276 | if (!file) | ||
277 | return NULL; | ||
278 | |||
279 | cpus = cpu_map__read(file); | ||
280 | fclose(file); | ||
281 | return cpus; | ||
282 | } | ||
283 | |||
256 | static struct perf_pmu *pmu_lookup(char *name) | 284 | static struct perf_pmu *pmu_lookup(char *name) |
257 | { | 285 | { |
258 | struct perf_pmu *pmu; | 286 | struct perf_pmu *pmu; |
@@ -275,6 +303,8 @@ static struct perf_pmu *pmu_lookup(char *name) | |||
275 | if (!pmu) | 303 | if (!pmu) |
276 | return NULL; | 304 | return NULL; |
277 | 305 | ||
306 | pmu->cpus = pmu_cpumask(name); | ||
307 | |||
278 | pmu_aliases(name, &aliases); | 308 | pmu_aliases(name, &aliases); |
279 | 309 | ||
280 | INIT_LIST_HEAD(&pmu->format); | 310 | INIT_LIST_HEAD(&pmu->format); |
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 47f68d3cc5d1..53c7794fc4be 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h | |||
@@ -28,6 +28,7 @@ struct perf_pmu__alias { | |||
28 | struct perf_pmu { | 28 | struct perf_pmu { |
29 | char *name; | 29 | char *name; |
30 | __u32 type; | 30 | __u32 type; |
31 | struct cpu_map *cpus; | ||
31 | struct list_head format; | 32 | struct list_head format; |
32 | struct list_head aliases; | 33 | struct list_head aliases; |
33 | struct list_head list; | 34 | struct list_head list; |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 526ba56e720b..1daf5c14e751 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -525,8 +525,10 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
525 | return -ENOENT; | 525 | return -ENOENT; |
526 | } | 526 | } |
527 | /* Verify it is a data structure */ | 527 | /* Verify it is a data structure */ |
528 | if (dwarf_tag(&type) != DW_TAG_structure_type) { | 528 | tag = dwarf_tag(&type); |
529 | pr_warning("%s is not a data structure.\n", varname); | 529 | if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { |
530 | pr_warning("%s is not a data structure nor an union.\n", | ||
531 | varname); | ||
530 | return -EINVAL; | 532 | return -EINVAL; |
531 | } | 533 | } |
532 | 534 | ||
@@ -539,8 +541,9 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
539 | *ref_ptr = ref; | 541 | *ref_ptr = ref; |
540 | } else { | 542 | } else { |
541 | /* Verify it is a data structure */ | 543 | /* Verify it is a data structure */ |
542 | if (tag != DW_TAG_structure_type) { | 544 | if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { |
543 | pr_warning("%s is not a data structure.\n", varname); | 545 | pr_warning("%s is not a data structure nor an union.\n", |
546 | varname); | ||
544 | return -EINVAL; | 547 | return -EINVAL; |
545 | } | 548 | } |
546 | if (field->name[0] == '[') { | 549 | if (field->name[0] == '[') { |
@@ -567,10 +570,15 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
567 | } | 570 | } |
568 | 571 | ||
569 | /* Get the offset of the field */ | 572 | /* Get the offset of the field */ |
570 | ret = die_get_data_member_location(die_mem, &offs); | 573 | if (tag == DW_TAG_union_type) { |
571 | if (ret < 0) { | 574 | offs = 0; |
572 | pr_warning("Failed to get the offset of %s.\n", field->name); | 575 | } else { |
573 | return ret; | 576 | ret = die_get_data_member_location(die_mem, &offs); |
577 | if (ret < 0) { | ||
578 | pr_warning("Failed to get the offset of %s.\n", | ||
579 | field->name); | ||
580 | return ret; | ||
581 | } | ||
574 | } | 582 | } |
575 | ref->offset += (long)offs; | 583 | ref->offset += (long)offs; |
576 | 584 | ||
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 0981bc7a2917..b5b1b9211960 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -8,6 +8,7 @@ const char default_sort_order[] = "comm,dso,symbol"; | |||
8 | const char *sort_order = default_sort_order; | 8 | const char *sort_order = default_sort_order; |
9 | int sort__need_collapse = 0; | 9 | int sort__need_collapse = 0; |
10 | int sort__has_parent = 0; | 10 | int sort__has_parent = 0; |
11 | int sort__has_sym = 0; | ||
11 | int sort__branch_mode = -1; /* -1 = means not set */ | 12 | int sort__branch_mode = -1; /* -1 = means not set */ |
12 | 13 | ||
13 | enum sort_type sort__first_dimension; | 14 | enum sort_type sort__first_dimension; |
@@ -511,6 +512,10 @@ int sort_dimension__add(const char *tok) | |||
511 | return -EINVAL; | 512 | return -EINVAL; |
512 | } | 513 | } |
513 | sort__has_parent = 1; | 514 | sort__has_parent = 1; |
515 | } else if (sd->entry == &sort_sym || | ||
516 | sd->entry == &sort_sym_from || | ||
517 | sd->entry == &sort_sym_to) { | ||
518 | sort__has_sym = 1; | ||
514 | } | 519 | } |
515 | 520 | ||
516 | if (sd->taken) | 521 | if (sd->taken) |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index e459c981b039..12d634792de5 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -31,6 +31,7 @@ extern const char *parent_pattern; | |||
31 | extern const char default_sort_order[]; | 31 | extern const char default_sort_order[]; |
32 | extern int sort__need_collapse; | 32 | extern int sort__need_collapse; |
33 | extern int sort__has_parent; | 33 | extern int sort__has_parent; |
34 | extern int sort__has_sym; | ||
34 | extern int sort__branch_mode; | 35 | extern int sort__branch_mode; |
35 | extern struct sort_entry sort_comm; | 36 | extern struct sort_entry sort_comm; |
36 | extern struct sort_entry sort_dso; | 37 | extern struct sort_entry sort_dso; |
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c new file mode 100644 index 000000000000..23742126f47c --- /dev/null +++ b/tools/perf/util/stat.c | |||
@@ -0,0 +1,57 @@ | |||
1 | #include <math.h> | ||
2 | |||
3 | #include "stat.h" | ||
4 | |||
5 | void update_stats(struct stats *stats, u64 val) | ||
6 | { | ||
7 | double delta; | ||
8 | |||
9 | stats->n++; | ||
10 | delta = val - stats->mean; | ||
11 | stats->mean += delta / stats->n; | ||
12 | stats->M2 += delta*(val - stats->mean); | ||
13 | } | ||
14 | |||
15 | double avg_stats(struct stats *stats) | ||
16 | { | ||
17 | return stats->mean; | ||
18 | } | ||
19 | |||
20 | /* | ||
21 | * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance | ||
22 | * | ||
23 | * (\Sum n_i^2) - ((\Sum n_i)^2)/n | ||
24 | * s^2 = ------------------------------- | ||
25 | * n - 1 | ||
26 | * | ||
27 | * http://en.wikipedia.org/wiki/Stddev | ||
28 | * | ||
29 | * The std dev of the mean is related to the std dev by: | ||
30 | * | ||
31 | * s | ||
32 | * s_mean = ------- | ||
33 | * sqrt(n) | ||
34 | * | ||
35 | */ | ||
36 | double stddev_stats(struct stats *stats) | ||
37 | { | ||
38 | double variance, variance_mean; | ||
39 | |||
40 | if (!stats->n) | ||
41 | return 0.0; | ||
42 | |||
43 | variance = stats->M2 / (stats->n - 1); | ||
44 | variance_mean = variance / stats->n; | ||
45 | |||
46 | return sqrt(variance_mean); | ||
47 | } | ||
48 | |||
49 | double rel_stddev_stats(double stddev, double avg) | ||
50 | { | ||
51 | double pct = 0.0; | ||
52 | |||
53 | if (avg) | ||
54 | pct = 100.0 * stddev/avg; | ||
55 | |||
56 | return pct; | ||
57 | } | ||
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h new file mode 100644 index 000000000000..588367c3c767 --- /dev/null +++ b/tools/perf/util/stat.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef __PERF_STATS_H | ||
2 | #define __PERF_STATS_H | ||
3 | |||
4 | #include "types.h" | ||
5 | |||
6 | struct stats | ||
7 | { | ||
8 | double n, mean, M2; | ||
9 | }; | ||
10 | |||
11 | void update_stats(struct stats *stats, u64 val); | ||
12 | double avg_stats(struct stats *stats); | ||
13 | double stddev_stats(struct stats *stats); | ||
14 | double rel_stddev_stats(double stddev, double avg); | ||
15 | |||
16 | #endif | ||