From 13d1e536b14ec2d404319a25e681a3287ca084ad Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sun, 21 Jun 2015 12:41:16 +0900 Subject: perf top: Move toggling event logic into hists browser Current 'f' key action to enable/disable events won't work if there're more than one event since perf_evsel_menu__run() doesn't return the key. So move it to the hists browser loop so that it can be processed as like other key action, and it's more natural to handle it there IMHO. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Jiri Olsa Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1434858076-6533-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 24 +++--------------------- tools/perf/ui/browsers/hists.c | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 23 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 619a8696fda7..ecf319728f25 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -586,27 +586,9 @@ static void *display_thread_tui(void *arg) hists->uid_filter_str = top->record_opts.target.uid_str; } - while (true) { - int key = perf_evlist__tui_browse_hists(top->evlist, help, &hbt, - top->min_percent, - &top->session->header.env); - - if (key != 'f') - break; - - perf_evlist__toggle_enable(top->evlist); - /* - * No need to refresh, resort/decay histogram entries - * if we are not collecting samples: - */ - if (top->evlist->enabled) { - hbt.refresh = top->delay_secs; - help = "Press 'f' to disable the events or 'h' to see other hotkeys"; - } else { - help = "Press 'f' again to re-enable the events"; - hbt.refresh = 0; - } - } + perf_evlist__tui_browse_hists(top->evlist, help, &hbt, + top->min_percent, + &top->session->header.env); done = 1; return NULL; diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index c42adb600091..7629bef2fd79 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1902,8 +1902,23 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, case CTRL('c'): goto out_free_stack; case 'f': - if (!is_report_browser(hbt)) - goto out_free_stack; + if (!is_report_browser(hbt)) { + struct perf_top *top = hbt->arg; + + perf_evlist__toggle_enable(top->evlist); + /* + * No need to refresh, resort/decay histogram + * entries if we are not collecting samples: + */ + if (top->evlist->enabled) { + helpline = "Press 'f' to disable the events or 'h' to see other hotkeys"; + hbt->refresh = delay_secs; + } else { + helpline = "Press 'f' again to re-enable the events"; + hbt->refresh = 0; + } + continue; + } /* Fall thru */ default: helpline = "Press '?' for help on key bindings"; -- cgit v1.2.3 From 502819c5f35ef44eb7151fb85cd883c5b76b506d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jun 2015 14:50:50 +0200 Subject: perf tests: Add testing for Makefile.perf Currently we test only builds through top level Makefile, but seems like there's a bunch of users using Makefile.perf directly. Changing the make suite to be run for Makefile.perf as well. It takes now considerable amount of time, but hopefully we catch more issues. Also fixing the output indentation for make_kernelsrc and make_kernelsrc_tools tests. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Lukas Wunner Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1434977452-32520-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 65280d28662e..bfe1962da0df 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -1,5 +1,16 @@ +ifndef MK +ifeq ($(MAKECMDGOALS),) +# no target specified, trigger the whole suite +all: + @echo "Testing Makefile"; $(MAKE) -sf tests/make MK=Makefile + @echo "Testing Makefile.perf"; $(MAKE) -sf tests/make MK=Makefile.perf +else +# run only specific test over 'Makefile' +%: + @echo "Testing Makefile"; $(MAKE) -sf tests/make MK=Makefile $@ +endif +else PERF := . -MK := Makefile include config/Makefile.arch @@ -57,7 +68,12 @@ make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 # $(run) contains all available tests run := make_pure +# Targets 'clean all' can be run together only through top level +# Makefile because we detect clean target in Makefile.perf and +# disable features detection +ifeq ($(MK),Makefile) run += make_clean_all +endif run += make_python_perf_so run += make_debug run += make_no_libperl @@ -226,13 +242,13 @@ tarpkg: ( eval $$cmd ) >> $@ 2>&1 make_kernelsrc: - @echo " - make -C tools/perf" + @echo "- make -C tools/perf" $(call clean); \ (make -C ../.. tools/perf) > $@ 2>&1 && \ test -x perf && rm -f $@ || (cat $@ ; false) make_kernelsrc_tools: - @echo " - make -C /tools perf" + @echo "- make -C /tools perf" $(call clean); \ (make -C ../../tools perf) > $@ 2>&1 && \ test -x perf && rm -f $@ || (cat $@ ; false) @@ -244,3 +260,4 @@ out: $(run_O) @echo OK .PHONY: all $(run) $(run_O) tarpkg clean +endif # ifndef MK -- cgit v1.2.3 From eb30d2c5077b30f9f8e00eb2e5fadba18b148538 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jun 2015 14:50:51 +0200 Subject: perf tests: Add test for make install with prefix Lukas Wunner reported issue (and fix[1]) with 'make install prefix=...'. Adding automated test for this, so it wouldn't happen again. [1]: 75e84ab906ef ("perf tools: Fix build breakage if prefix= is specified") Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Lukas Wunner Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1434977452-32520-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tools') diff --git a/tools/perf/tests/make b/tools/perf/tests/make index bfe1962da0df..729112f4cfaa 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -58,6 +58,7 @@ make_install_man := install-man make_install_html := install-html make_install_info := install-info make_install_pdf := install-pdf +make_install_prefix := install prefix=/tmp/krava make_static := LDFLAGS=-static # all the NO_* variable combined @@ -99,6 +100,7 @@ run += make_util_map_o run += make_util_pmu_bison_o run += make_install run += make_install_bin +run += make_install_prefix # FIXME 'install-*' commented out till they're fixed # run += make_install_doc # run += make_install_man @@ -173,6 +175,12 @@ test_make_install_O := $(call test_dest_files,$(installed_files_all)) test_make_install_bin := $(call test_dest_files,$(installed_files_bin)) test_make_install_bin_O := $(call test_dest_files,$(installed_files_bin)) +# We prefix all installed files for make_install_prefix +# with '/tmp/krava' to match installed/prefix-ed files. +installed_files_all_prefix := $(addprefix /tmp/krava/,$(installed_files_all)) +test_make_install_prefix := $(call test_dest_files,$(installed_files_all_prefix)) +test_make_install_prefix_O := $(call test_dest_files,$(installed_files_all_prefix)) + # FIXME nothing gets installed test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1 test_make_install_man_O := $(test_make_install_man) -- cgit v1.2.3 From 8e55735150934f9ab2ce8a8005626e5693a6b61d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jun 2015 14:50:52 +0200 Subject: perf build: Fix single target build dependency check Currently if we build a single target like: $ touch util/map.c && make util/map.o It will not rebuild util/map.o if it already exists and util/map.c is modified. The reason is that the top-level 'Makefile' processes util/map.o as an implicit rule and if util/map.o exists make considers the 'util/map.o' target as done and will not nest into Makefile.perf. Adding FORCE for '%', because that's what we want to nest into Makefile.perf for any target. Adding Makefile into phony targets, because make tries to rebuild it and it's also resolved as '%' target. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Lukas Wunner Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1434977452-32520-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/Makefile b/tools/perf/Makefile index d31a7bbd7cee..480546d5f13b 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -83,8 +83,8 @@ build-test: # # All other targets get passed through: # -%: +%: FORCE $(print_msg) $(make) -.PHONY: tags TAGS +.PHONY: tags TAGS FORCE Makefile -- cgit v1.2.3 From c5de47f2e803c7e6ffc0a34b174d4d009c8bd8e1 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Wed, 10 Jun 2015 00:25:07 -0700 Subject: perf pmu: Use __weak definition from Jiri Olsa pointed out, that the defines the attribute '__weak'. We might as well use that. Signed-off-by: Sukadev Bhattiprolu Acked-by: Jiri Olsa Cc: Andi Kleen Cc: Madhavan Srinivasan Cc: Michael Ellerman Cc: Namhyung Kim Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1433921123-25327-4-git-send-email-sukadev@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 0fcc624eb767..c6b16b1db6d0 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -436,7 +437,7 @@ static struct cpu_map *pmu_cpumask(const char *name) return cpus; } -struct perf_event_attr *__attribute__((weak)) +struct perf_event_attr * __weak perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) { return NULL; -- cgit v1.2.3 From 70c646e0e47b51c8fa431f9ec1962f7d6e512860 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Wed, 10 Jun 2015 00:25:08 -0700 Subject: perf pmu: Split perf_pmu__new_alias() Separate the event parsing code in perf_pmu__new_alias() out into a separate function __perf_pmu__new_alias() so that code can be called indepdently. This is based on an earlier patch from Andi Kleen. Signed-off-by: Sukadev Bhattiprolu Acked-by: Jiri Olsa Cc: Andi Kleen Cc: Madhavan Srinivasan Cc: Michael Ellerman Cc: Namhyung Kim Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1433921123-25327-5-git-send-email-sukadev@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index c6b16b1db6d0..7bcb8c315615 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -206,17 +206,12 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, return 0; } -static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) +static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, + char *desc __maybe_unused, char *val) { struct perf_pmu_alias *alias; - char buf[256]; int ret; - ret = fread(buf, 1, sizeof(buf), file); - if (ret == 0) - return -EINVAL; - buf[ret] = 0; - alias = malloc(sizeof(*alias)); if (!alias) return -ENOMEM; @@ -226,26 +221,43 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI alias->unit[0] = '\0'; alias->per_pkg = false; - ret = parse_events_terms(&alias->terms, buf); + ret = parse_events_terms(&alias->terms, val); if (ret) { + pr_err("Cannot parse alias %s: %d\n", val, ret); free(alias); return ret; } alias->name = strdup(name); - /* - * load unit name and scale if available - */ - perf_pmu__parse_unit(alias, dir, name); - perf_pmu__parse_scale(alias, dir, name); - perf_pmu__parse_per_pkg(alias, dir, name); - perf_pmu__parse_snapshot(alias, dir, name); + if (dir) { + /* + * load unit name and scale if available + */ + perf_pmu__parse_unit(alias, dir, name); + perf_pmu__parse_scale(alias, dir, name); + perf_pmu__parse_per_pkg(alias, dir, name); + perf_pmu__parse_snapshot(alias, dir, name); + } list_add_tail(&alias->list, list); return 0; } +static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) +{ + char buf[256]; + int ret; + + ret = fread(buf, 1, sizeof(buf), file); + if (ret == 0) + return -EINVAL; + + buf[ret] = 0; + + return __perf_pmu__new_alias(list, dir, name, NULL, buf); +} + static inline bool pmu_alias_info_file(char *name) { size_t len; -- cgit v1.2.3 From 5b021ddf81b0bcd17d88186b605f53a2ca452d3a Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 10 Jun 2015 00:25:11 -0700 Subject: perf tools: Allow events with dot The Intel events use a dot to separate event name and unit mask. Allow dot in names in the scanner, and remove special handling of dot as EOF. Also remove the hack in jevents to replace dot with underscore. This way dotted events can be specified directly by the user. I'm not fully sure this change to the scanner is correct (what was the dot special case good for?), but I haven't found anything that breaks with it so far at least. Signed-off-by: Andi Kleen Acked-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Madhavan Srinivasan Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1433921123-25327-8-git-send-email-sukadev@linux.vnet.ibm.com Signed-off-by: Sukadev Bhattiprolu Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.l | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 09e738fe9ea2..13cef3c65565 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -119,8 +119,8 @@ event [^,{}/]+ num_dec [0-9]+ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ -name [a-zA-Z_*?][a-zA-Z0-9_*?]* -name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* +name [a-zA-Z_*?][a-zA-Z0-9_*?.]* +name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]* /* If you add a modifier you need to update check_modifier() */ modifier_event [ukhpGHSDI]+ modifier_bp [rwx]{1,3} @@ -165,7 +165,6 @@ modifier_bp [rwx]{1,3} return PE_EVENT_NAME; } -. | <> { BEGIN(INITIAL); REWIND(0); -- cgit v1.2.3 From 5531e16227cc18bc13b028a052a609a233b49c07 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 23 Jun 2015 10:52:48 +0300 Subject: perf session: Print a newline when dumping PERF_RECORD_FINISHED_ROUND With 'perf report -D' the PERF_RECORD_FINISHED_ROUND event was printed without a newline, resulting in: 0x91a18 [0x8]: PERF_RECORD_FINISHED_ROUNDAggregated stats Other events print their details, but PERF_RECORD_FINISHED_ROUND doesn't have any so just add a print for a newline. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1435045969-15999-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index aa482c10469d..aac1c4cee1e8 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -686,6 +686,8 @@ static int process_finished_round(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct ordered_events *oe) { + if (dump_trace) + fprintf(stdout, "\n"); return ordered_events__flush(oe, OE_FLUSH__ROUND); } -- cgit v1.2.3 From fe692ac86adbbbbf9745909aafe0c87fd7fc6368 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 23 Jun 2015 10:52:49 +0300 Subject: perf tools: Print a newline before dumping Aggregated stats When dumping events with 'perf report -D' the event print always starts with a newline (see dump_event()). Do the same with the "Aggregated stats" print so that it is not jammed up against the last event print. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1435045969-15999-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index aac1c4cee1e8..b5549b58bb2b 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1728,7 +1728,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) if (perf_header__has_feat(&session->header, HEADER_AUXTRACE)) msg = " (excludes AUX area (e.g. instruction trace) decoded / synthesized events)"; - ret = fprintf(fp, "Aggregated stats:%s\n", msg); + ret = fprintf(fp, "\nAggregated stats:%s\n", msg); ret += events_stats__fprintf(&session->evlist->stats, fp); return ret; -- cgit v1.2.3 From 7c31bb8c95ed269062ff7c7cc4a28b84a2b0f3a6 Mon Sep 17 00:00:00 2001 From: He Kuang Date: Thu, 18 Jun 2015 02:49:10 +0000 Subject: perf probe: Fix failure to probe events on arm Fix failure to probe events on arm, the problem was introduced by commit 5a51fcd1f30c ("perf probe: Skip kernel symbols which is out of .text"). For some architectures, the '_etext' label is not in the .text section (in the .notes section for arm/arm64). Labels out of the .text section are not loaded as symbols and we get a zero value when looking up its addresses, which causes all events to be wrongly skipped. This patch skips checking the text address range when failing to get the address of '_etext' and thus fixes the problem. The problem can be reproduced on arm as follows: # perf probe --add='generic_perform_write' generic_perform_write+0 is out of .text, skip it. Probe point 'generic_perform_write' not found. Error: Failed to add events. After this patch: # perf probe --add='generic_perform_write' Added new event: probe:generic_perform_write (on generic_perform_write) You can now use it in all perf tools, such as: perf record -e probe:generic_perform_write -aR sleep 1 Signed-off-by: He Kuang Acked-by: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1434595750-129791-1-git-send-email-hekuang@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 076527b639bd..381f23a443c7 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -249,8 +249,12 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) static bool kprobe_blacklist__listed(unsigned long address); static bool kprobe_warn_out_range(const char *symbol, unsigned long address) { + u64 etext_addr; + /* Get the address of _etext for checking non-probable text symbol */ - if (kernel_get_symbol_address_by_name("_etext", false) < address) + etext_addr = kernel_get_symbol_address_by_name("_etext", false); + + if (etext_addr != 0 && etext_addr < address) pr_warning("%s is out of .text, skip it.\n", symbol); else if (kprobe_blacklist__listed(address)) pr_warning("%s is blacklisted function, skip it.\n", symbol); -- cgit v1.2.3 From e13798c77bdfed1da497f5e076b105b2be17b44f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 23 Jun 2015 00:36:02 +0200 Subject: perf thread_map: Don't access the array entries directly Instead provide a method to set the array entries, and another to access the contents. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435012588-9007-2-git-send-email-jolsa@kernel.org [ Split providing the set/get accessors from transforming the entries structs ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/openat-syscall-tp-fields.c | 2 +- tools/perf/util/auxtrace.c | 4 ++-- tools/perf/util/event.c | 6 +++--- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 2 +- tools/perf/util/thread_map.c | 24 +++++++++++++----------- tools/perf/util/thread_map.h | 10 ++++++++++ 8 files changed, 34 insertions(+), 22 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index de5d277d1ad7..2bf2ca771ca5 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -2325,7 +2325,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) */ if (trace->filter_pids.nr > 0) err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries); - else if (evlist->threads->map[0] == -1) + else if (thread_map__pid(evlist->threads, 0) == -1) err = perf_evlist__set_filter_pid(evlist, getpid()); if (err < 0) { @@ -2343,7 +2343,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (forks) perf_evlist__start_workload(evlist); - trace->multiple_threads = evlist->threads->map[0] == -1 || + trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 || evlist->threads->nr > 1 || perf_evlist__first(evlist)->attr.inherit; again: diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 6245221479d7..01a19626c846 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -45,7 +45,7 @@ int test__syscall_openat_tp_fields(void) perf_evsel__config(evsel, &opts); - evlist->threads->map[0] = getpid(); + thread_map__set_pid(evlist->threads, 0, getpid()); err = perf_evlist__open(evlist); if (err < 0) { diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index df66966cfde7..3dab006b4a03 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -119,12 +119,12 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, if (per_cpu) { mp->cpu = evlist->cpus->map[idx]; if (evlist->threads) - mp->tid = evlist->threads->map[0]; + mp->tid = thread_map__pid(evlist->threads, 0); else mp->tid = -1; } else { mp->cpu = -1; - mp->tid = evlist->threads->map[idx]; + mp->tid = thread_map__pid(evlist->threads, idx); } } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index d7d986d8f23e..67a977e5d0ab 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -504,7 +504,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, for (thread = 0; thread < threads->nr; ++thread) { if (__event__synthesize_thread(comm_event, mmap_event, fork_event, - threads->map[thread], 0, + thread_map__pid(threads, thread), 0, process, tool, machine, mmap_data, proc_map_timeout)) { err = -1; @@ -515,12 +515,12 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, * comm.pid is set to thread group id by * perf_event__synthesize_comm */ - if ((int) comm_event->comm.pid != threads->map[thread]) { + if ((int) comm_event->comm.pid != thread_map__pid(threads, thread)) { bool need_leader = true; /* is thread group leader in thread_map? */ for (j = 0; j < threads->nr; ++j) { - if ((int) comm_event->comm.pid == threads->map[j]) { + if ((int) comm_event->comm.pid == thread_map__pid(threads, j)) { need_leader = false; break; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 8366511b45f8..d29df901be3e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -548,7 +548,7 @@ static void perf_evlist__set_sid_idx(struct perf_evlist *evlist, else sid->cpu = -1; if (!evsel->system_wide && evlist->threads && thread >= 0) - sid->tid = evlist->threads->map[thread]; + sid->tid = thread_map__pid(evlist->threads, thread); else sid->tid = -1; } @@ -1475,7 +1475,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar __func__, __LINE__); goto out_close_pipes; } - evlist->threads->map[0] = evlist->workload.pid; + thread_map__set_pid(evlist->threads, 0, evlist->workload.pid); } close(child_ready_pipe[1]); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 33449decf7bd..1b56047af96b 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1167,7 +1167,7 @@ retry_sample_id: int group_fd; if (!evsel->cgrp && !evsel->system_wide) - pid = threads->map[thread]; + pid = thread_map__pid(threads, thread); group_fd = get_group_fd(evsel, cpu, thread); retry_open: diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index f4822bd03709..8c3c3a0751bd 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -45,7 +45,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) threads = thread_map__alloc(items); if (threads != NULL) { for (i = 0; i < items; i++) - threads->map[i] = atoi(namelist[i]->d_name); + thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); threads->nr = items; } @@ -61,8 +61,8 @@ struct thread_map *thread_map__new_by_tid(pid_t tid) struct thread_map *threads = thread_map__alloc(1); if (threads != NULL) { - threads->map[0] = tid; - threads->nr = 1; + thread_map__set_pid(threads, 0, tid); + threads->nr = 1; } return threads; @@ -123,8 +123,10 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) threads = tmp; } - for (i = 0; i < items; i++) - threads->map[threads->nr + i] = atoi(namelist[i]->d_name); + for (i = 0; i < items; i++) { + thread_map__set_pid(threads, threads->nr + i, + atoi(namelist[i]->d_name)); + } for (i = 0; i < items; i++) zfree(&namelist[i]); @@ -201,7 +203,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) threads = nt; for (i = 0; i < items; i++) { - threads->map[j++] = atoi(namelist[i]->d_name); + thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name)); zfree(&namelist[i]); } threads->nr = total_tasks; @@ -227,8 +229,8 @@ struct thread_map *thread_map__new_dummy(void) struct thread_map *threads = thread_map__alloc(1); if (threads != NULL) { - threads->map[0] = -1; - threads->nr = 1; + thread_map__set_pid(threads, 0, -1); + threads->nr = 1; } return threads; } @@ -267,8 +269,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) goto out_free_threads; threads = nt; - threads->map[ntasks - 1] = tid; - threads->nr = ntasks; + thread_map__set_pid(threads, ntasks - 1, tid); + threads->nr = ntasks; } out: return threads; @@ -301,7 +303,7 @@ size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) size_t printed = fprintf(fp, "%d thread%s: ", threads->nr, threads->nr > 1 ? "s" : ""); for (i = 0; i < threads->nr; ++i) - printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]); + printed += fprintf(fp, "%s%d", i ? ", " : "", thread_map__pid(threads, i)); return printed + fprintf(fp, "\n"); } diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 95313f43cc0f..e22570390470 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -27,4 +27,14 @@ static inline int thread_map__nr(struct thread_map *threads) return threads ? threads->nr : 1; } +static inline pid_t thread_map__pid(struct thread_map *map, int thread) +{ + return map->map[thread]; +} + +static inline void +thread_map__set_pid(struct thread_map *map, int thread, pid_t pid) +{ + map->map[thread] = pid; +} #endif /* __PERF_THREAD_MAP_H */ -- cgit v1.2.3 From 38e89d2b1771649c006720903c06d8b8bedd4d83 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 23 Jun 2015 00:36:02 +0200 Subject: perf thread_map: Change map entries into a struct We need to store command names with the pid. Changing map entries to be a struct holding pid. Process name is coming in shortly. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435012588-9007-2-git-send-email-jolsa@kernel.org [ Split providing the set/get accessors from transforming the entries structs ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index e22570390470..b9f40679f589 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -4,9 +4,13 @@ #include #include +struct thread_map_data { + pid_t pid; +}; + struct thread_map { int nr; - pid_t map[]; + struct thread_map_data map[]; }; struct thread_map *thread_map__new_dummy(void); @@ -29,12 +33,12 @@ static inline int thread_map__nr(struct thread_map *threads) static inline pid_t thread_map__pid(struct thread_map *map, int thread) { - return map->map[thread]; + return map->map[thread].pid; } static inline void thread_map__set_pid(struct thread_map *map, int thread, pid_t pid) { - map->map[thread] = pid; + map->map[thread].pid = pid; } #endif /* __PERF_THREAD_MAP_H */ -- cgit v1.2.3 From 83b2ea257eb1d43e52f76d756722aeb899a2852c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 29 May 2015 16:33:38 +0300 Subject: perf tools: Allow auxtrace data alignment Allow auxtrace data to be a multiple of something other than page size. That is needed for BTS where the buffer contains 24-byte records. Signed-off-by: Adrian Hunter Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1432906425-9911-11-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/auxtrace.c | 7 +++++++ tools/perf/util/auxtrace.h | 1 + 2 files changed, 8 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 3dab006b4a03..7e7405c9b936 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -1182,6 +1182,13 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm, data2 = NULL; } + if (itr->alignment) { + unsigned int unwanted = len1 % itr->alignment; + + len1 -= unwanted; + size -= unwanted; + } + /* padding must be written by fn() e.g. record__process_auxtrace() */ padding = size & 7; if (padding) diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index a171abbe7301..471aecbc4d68 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -303,6 +303,7 @@ struct auxtrace_record { const char *str); u64 (*reference)(struct auxtrace_record *itr); int (*read_finish)(struct auxtrace_record *itr, int idx); + unsigned int alignment; }; #ifdef HAVE_AUXTRACE_SUPPORT -- cgit v1.2.3 From 2b42b09b88c831ba4da2d669581dde371c38c2af Mon Sep 17 00:00:00 2001 From: Srikar Dronamraju Date: Wed, 24 Jun 2015 16:40:04 +0530 Subject: perf bench numa: Fix to show proper convergence stats With commit: e1e455f4f4d3 (perf tools: Work around lack of sched_getcpu in glibc < 2.6), perf_bench numa mem with -c or -m option is not able to correctly calculate convergence. With the above commit, sched_getcpu always seems to return -1. The intention of commit e1e455f was to add a sched_getcpu in glibc < 2.6. Hence keep the sched_getcpu definition under an ifdef. This regression happened occurred between v4.0 and v4.1 Signed-off-by: Srikar Dronamraju Acked-by: Ingo Molnar Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Vinson Lee Fixes: e1e455f4f4d3 ("perf tools: Work around lack of sched_getcpu in glibc < 2.6") Link: http://lkml.kernel.org/r/20150624111004.GA5220@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cloexec.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c index 85b523885f9d..2babddaa2481 100644 --- a/tools/perf/util/cloexec.c +++ b/tools/perf/util/cloexec.c @@ -7,11 +7,15 @@ static unsigned long flag = PERF_FLAG_FD_CLOEXEC; +#ifdef __GLIBC_PREREQ +#if !__GLIBC_PREREQ(2, 6) int __weak sched_getcpu(void) { errno = ENOSYS; return -1; } +#endif +#endif static int perf_flag_probe(void) { -- cgit v1.2.3 From 060664f3b9dff37860e48b5158e8429b2467e526 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 25 Jun 2015 14:48:49 -0300 Subject: perf tools: Future-proof thread_map allocation size calculation Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/20150625174840.GH3253@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 8c3c3a0751bd..920136dd8c2e 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -22,7 +22,7 @@ static int filter(const struct dirent *dir) static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) { - size_t size = sizeof(*map) + sizeof(pid_t) * nr; + size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; return realloc(map, size); } -- cgit v1.2.3 From 4cc97614812e96c135e369f3d723fcda07d33437 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 25 Jun 2015 17:12:32 +0200 Subject: perf header: Delete an unnecessary check before the calling free_event_desc() The free_event_desc() function tests whether its argument is NULL and then returns immediately. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Cc: Julia Lawall Cc: Peter Zijlstra Cc: kernel-janitors@vger.kernel.org Link: http://lkml.kernel.org/r/558C2ABA.3000603@users.sourceforge.net Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 21a77e7a171e..03ace57a800c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1063,8 +1063,7 @@ out: free(buf); return events; error: - if (events) - free_event_desc(events); + free_event_desc(events); events = NULL; goto out; } -- cgit v1.2.3 From f30a79b012e5d9b3887f6a59293d9ef3ca0e2c3e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 23 Jun 2015 00:36:04 +0200 Subject: perf tools: Add reference counting for cpu_map object Adding refference counting for cpu_map object, so it could be easily shared among other objects. Using cpu_map__put instead cpu_map__delete and making cpu_map__delete static. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435012588-9007-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/util/cpumap.c | 26 ++++++++++++++++++++++++-- tools/perf/util/cpumap.h | 6 +++++- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/evsel.c | 1 + tools/perf/util/parse-events.c | 5 ++++- tools/perf/util/python.c | 2 +- tools/perf/util/record.c | 4 ++-- tools/perf/util/session.c | 2 +- tools/perf/util/svghelper.c | 2 +- 13 files changed, 45 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 22f8a00446e1..6b3250f54240 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -545,7 +545,7 @@ out_err: if (evlist) { perf_evlist__delete(evlist); } else { - cpu_map__delete(cpus); + cpu_map__put(cpus); thread_map__delete(threads); } machines__destroy_kernel_maps(&machines); diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 5b171d1e338b..a330235cefc0 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -144,7 +144,7 @@ out_err: perf_evlist__disable(evlist); perf_evlist__delete(evlist); } else { - cpu_map__delete(cpus); + cpu_map__put(cpus); thread_map__delete(threads); } diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 5855cf471210..5a9ef5833452 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -140,7 +140,7 @@ out_delete_evlist: cpus = NULL; threads = NULL; out_free_cpus: - cpu_map__delete(cpus); + cpu_map__put(cpus); out_free_threads: thread_map__delete(threads); return err; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 0d31403ea593..1b06122beb76 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -560,7 +560,7 @@ out: perf_evlist__disable(evlist); perf_evlist__delete(evlist); } else { - cpu_map__delete(cpus); + cpu_map__put(cpus); thread_map__delete(threads); } diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index c4e55b71010c..3667e2123e5b 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -5,6 +5,7 @@ #include #include #include +#include "asm/bug.h" static struct cpu_map *cpu_map__default_new(void) { @@ -22,6 +23,7 @@ static struct cpu_map *cpu_map__default_new(void) cpus->map[i] = i; cpus->nr = nr_cpus; + atomic_set(&cpus->refcnt, 1); } return cpus; @@ -35,6 +37,7 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) if (cpus != NULL) { cpus->nr = nr_cpus; memcpy(cpus->map, tmp_cpus, payload_size); + atomic_set(&cpus->refcnt, 1); } return cpus; @@ -194,14 +197,32 @@ struct cpu_map *cpu_map__dummy_new(void) if (cpus != NULL) { cpus->nr = 1; cpus->map[0] = -1; + atomic_set(&cpus->refcnt, 1); } return cpus; } -void cpu_map__delete(struct cpu_map *map) +static void cpu_map__delete(struct cpu_map *map) { - free(map); + if (map) { + WARN_ONCE(atomic_read(&map->refcnt) != 0, + "cpu_map refcnt unbalanced\n"); + free(map); + } +} + +struct cpu_map *cpu_map__get(struct cpu_map *map) +{ + if (map) + atomic_inc(&map->refcnt); + return map; +} + +void cpu_map__put(struct cpu_map *map) +{ + if (map && atomic_dec_and_test(&map->refcnt)) + cpu_map__delete(map); } int cpu_map__get_socket(struct cpu_map *map, int idx) @@ -263,6 +284,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, /* ensure we process id in increasing order */ qsort(c->map, c->nr, sizeof(int), cmp_ids); + atomic_set(&cpus->refcnt, 1); *res = c; return 0; } diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 61a654849002..0af9cecb4c51 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -3,18 +3,19 @@ #include #include +#include #include "perf.h" #include "util/debug.h" struct cpu_map { + atomic_t refcnt; int nr; int map[]; }; struct cpu_map *cpu_map__new(const char *cpu_list); struct cpu_map *cpu_map__dummy_new(void); -void cpu_map__delete(struct cpu_map *map); struct cpu_map *cpu_map__read(FILE *file); size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); int cpu_map__get_socket(struct cpu_map *map, int idx); @@ -22,6 +23,9 @@ int cpu_map__get_core(struct cpu_map *map, int idx); int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); +struct cpu_map *cpu_map__get(struct cpu_map *map); +void cpu_map__put(struct cpu_map *map); + static inline int cpu_map__socket(struct cpu_map *sock, int s) { if (!sock || s > sock->nr || s < 0) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d29df901be3e..59498f7b3e9b 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -114,7 +114,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) { perf_evlist__munmap(evlist); perf_evlist__close(evlist); - cpu_map__delete(evlist->cpus); + cpu_map__put(evlist->cpus); thread_map__delete(evlist->threads); evlist->cpus = NULL; evlist->threads = NULL; @@ -1353,7 +1353,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) out: return err; out_free_cpus: - cpu_map__delete(evlist->cpus); + cpu_map__put(evlist->cpus); evlist->cpus = NULL; goto out; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1b56047af96b..31b0afb68825 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -885,6 +885,7 @@ void perf_evsel__exit(struct perf_evsel *evsel) perf_evsel__free_fd(evsel); perf_evsel__free_id(evsel); close_cgroup(evsel->cgrp); + cpu_map__put(evsel->cpus); zfree(&evsel->group_name); zfree(&evsel->name); perf_evsel__object.fini(evsel); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 2a4d1ec02846..09f8d2357108 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -17,6 +17,7 @@ #include "parse-events-flex.h" #include "pmu.h" #include "thread_map.h" +#include "cpumap.h" #include "asm/bug.h" #define MAX_NAME_LEN 100 @@ -285,7 +286,9 @@ __add_event(struct list_head *list, int *idx, if (!evsel) return NULL; - evsel->cpus = cpus; + if (cpus) + evsel->cpus = cpu_map__get(cpus); + if (name) evsel->name = strdup(name); list_add_tail(&evsel->node, list); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index d906d0ad5d40..b106d56df240 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -384,7 +384,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) { - cpu_map__delete(pcpus->cpus); + cpu_map__put(pcpus->cpus); pcpus->ob_type->tp_free((PyObject*)pcpus); } diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index d457c523a33d..1f7becbe5e18 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c @@ -64,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn) if (!cpus) return false; cpu = cpus->map[0]; - cpu_map__delete(cpus); + cpu_map__put(cpus); do { ret = perf_do_probe_api(fn, cpu, try[i++]); @@ -226,7 +226,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) struct cpu_map *cpus = cpu_map__new(NULL); cpu = cpus ? cpus->map[0] : 0; - cpu_map__delete(cpus); + cpu_map__put(cpus); } else { cpu = evlist->cpus->map[0]; } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b5549b58bb2b..ed9dc2555ec7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1895,7 +1895,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, err = 0; out_delete_map: - cpu_map__delete(map); + cpu_map__put(map); return err; } diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 283d3e73e2f2..eec6c1149f44 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -748,7 +748,7 @@ static int str_to_bitmap(char *s, cpumask_t *b) set_bit(c, cpumask_bits(b)); } - cpu_map__delete(m); + cpu_map__put(m); return ret; } -- cgit v1.2.3 From 186fbb7432f4a740b4fbaf4145375442210110bb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 23 Jun 2015 00:36:05 +0200 Subject: perf tools: Add reference counting for thread_map object Adding reference counting for thread_map object, so it could be easily shared among other objects. Using thread_map__put instead thread_map__delete and making thread_map__delete static. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435012588-9007-5-git-send-email-jolsa@kernel.org [ Adjustments to move it ahead of the "comm" patches ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/code-reading.c | 2 +- tools/perf/tests/keep-tracking.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/tests/mmap-thread-lookup.c | 2 +- tools/perf/tests/openat-syscall-all-cpus.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/tests/switch-tracking.c | 2 +- tools/perf/util/evlist.c | 4 ++-- tools/perf/util/python.c | 2 +- tools/perf/util/thread_map.c | 30 ++++++++++++++++++++++++++++-- tools/perf/util/thread_map.h | 7 +++++-- 11 files changed, 43 insertions(+), 14 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6b3250f54240..39c784a100a9 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -546,7 +546,7 @@ out_err: perf_evlist__delete(evlist); } else { cpu_map__put(cpus); - thread_map__delete(threads); + thread_map__put(threads); } machines__destroy_kernel_maps(&machines); machine__delete_threads(machine); diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index a330235cefc0..4d4b9837b630 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -145,7 +145,7 @@ out_err: perf_evlist__delete(evlist); } else { cpu_map__put(cpus); - thread_map__delete(threads); + thread_map__put(threads); } return err; diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 5a9ef5833452..666b67a4df9d 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -142,6 +142,6 @@ out_delete_evlist: out_free_cpus: cpu_map__put(cpus); out_free_threads: - thread_map__delete(threads); + thread_map__put(threads); return err; } diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index 7f48efa7e295..145050e2e544 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c @@ -143,7 +143,7 @@ static int synth_process(struct machine *machine) perf_event__process, machine, 0, 500); - thread_map__delete(map); + thread_map__put(map); return err; } diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 9a7a116e09b8..b8d552b13950 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -111,6 +111,6 @@ out_close_fd: out_evsel_delete: perf_evsel__delete(evsel); out_thread_map_delete: - thread_map__delete(threads); + thread_map__put(threads); return err; } diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index 9f9491bb8e48..bdfa1f446681 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -56,6 +56,6 @@ out_close_fd: out_evsel_delete: perf_evsel__delete(evsel); out_thread_map_delete: - thread_map__delete(threads); + thread_map__put(threads); return err; } diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 1b06122beb76..e698742d4fec 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -561,7 +561,7 @@ out: perf_evlist__delete(evlist); } else { cpu_map__put(cpus); - thread_map__delete(threads); + thread_map__put(threads); } return err; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 59498f7b3e9b..a8d18a3d2164 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -115,7 +115,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) perf_evlist__munmap(evlist); perf_evlist__close(evlist); cpu_map__put(evlist->cpus); - thread_map__delete(evlist->threads); + thread_map__put(evlist->threads); evlist->cpus = NULL; evlist->threads = NULL; perf_evlist__purge(evlist); @@ -1120,7 +1120,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) return 0; out_delete_threads: - thread_map__delete(evlist->threads); + thread_map__put(evlist->threads); evlist->threads = NULL; return -1; } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index b106d56df240..626422eda727 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -453,7 +453,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) { - thread_map__delete(pthreads->threads); + thread_map__put(pthreads->threads); pthreads->ob_type->tp_free((PyObject*)pthreads); } diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 920136dd8c2e..368cc58c6892 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -8,6 +8,7 @@ #include #include "strlist.h" #include +#include "asm/bug.h" #include "thread_map.h" #include "util.h" @@ -47,6 +48,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) for (i = 0; i < items; i++) thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); threads->nr = items; + atomic_set(&threads->refcnt, 1); } for (i=0; inr = 1; + atomic_set(&threads->refcnt, 1); } return threads; @@ -84,6 +87,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) goto out_free_threads; threads->nr = 0; + atomic_set(&threads->refcnt, 1); while (!readdir_r(proc, &dirent, &next) && next) { char *end; @@ -212,6 +216,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) out: strlist__delete(slist); + if (threads) + atomic_set(&threads->refcnt, 1); return threads; out_free_namelist: @@ -231,6 +237,7 @@ struct thread_map *thread_map__new_dummy(void) if (threads != NULL) { thread_map__set_pid(threads, 0, -1); threads->nr = 1; + atomic_set(&threads->refcnt, 1); } return threads; } @@ -273,6 +280,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) threads->nr = ntasks; } out: + if (threads) + atomic_set(&threads->refcnt, 1); return threads; out_free_threads: @@ -292,9 +301,26 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid, return thread_map__new_by_tid_str(tid); } -void thread_map__delete(struct thread_map *threads) +static void thread_map__delete(struct thread_map *threads) { - free(threads); + if (threads) { + WARN_ONCE(atomic_read(&threads->refcnt) != 0, + "thread map refcnt unbalanced\n"); + free(threads); + } +} + +struct thread_map *thread_map__get(struct thread_map *map) +{ + if (map) + atomic_inc(&map->refcnt); + return map; +} + +void thread_map__put(struct thread_map *map) +{ + if (map && atomic_dec_and_test(&map->refcnt)) + thread_map__delete(map); } size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index b9f40679f589..6b0cd2dc006b 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -3,12 +3,14 @@ #include #include +#include struct thread_map_data { pid_t pid; }; struct thread_map { + atomic_t refcnt; int nr; struct thread_map_data map[]; }; @@ -19,11 +21,12 @@ struct thread_map *thread_map__new_by_tid(pid_t tid); struct thread_map *thread_map__new_by_uid(uid_t uid); struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); +struct thread_map *thread_map__get(struct thread_map *map); +void thread_map__put(struct thread_map *map); + struct thread_map *thread_map__new_str(const char *pid, const char *tid, uid_t uid); -void thread_map__delete(struct thread_map *threads); - size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); static inline int thread_map__nr(struct thread_map *threads) -- cgit v1.2.3 From b7f0c203586b91419ff9aa9b1115e261082ff5b4 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 23 Jun 2015 00:36:06 +0200 Subject: perf evlist: Propagate cpu maps to evsels in an evlist Propagate evlist's cpu_map object through all the evsel objects, while keeping already configured evsel->cpus. It'll be handy to access evsel's cpus directly in following patches. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435012588-9007-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index a8d18a3d2164..214affaf1cf6 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1101,6 +1101,29 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false); } +static int perf_evlist__propagate_maps(struct perf_evlist *evlist, + struct target *target) +{ + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) { + /* + * We already have cpus for evsel (via PMU sysfs) so + * keep it, if there's no target cpu list defined. + */ + if (evsel->cpus && target->cpu_list) + cpu_map__put(evsel->cpus); + + if (!evsel->cpus || target->cpu_list) + evsel->cpus = cpu_map__get(evlist->cpus); + + if (!evsel->cpus) + return -ENOMEM; + } + + return 0; +} + int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) { evlist->threads = thread_map__new_str(target->pid, target->tid, @@ -1117,7 +1140,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) if (evlist->cpus == NULL) goto out_delete_threads; - return 0; + return perf_evlist__propagate_maps(evlist, target); out_delete_threads: thread_map__put(evlist->threads); -- cgit v1.2.3 From 578e91ec04d03aca89e300151addb3e3ed5b06ea Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 23 Jun 2015 00:36:07 +0200 Subject: perf evlist: Propagate thread maps through the evlist Propagate evlist's thread_map object through all the evsel objects. It'll be handy to access evsel's threads directly in following patches. The reason is there's no link from evsel to evlist which hold threads map now and evlist is not always available. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435012588-9007-7-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 4 +++- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 214affaf1cf6..6cfdee68e763 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1117,7 +1117,9 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist, if (!evsel->cpus || target->cpu_list) evsel->cpus = cpu_map__get(evlist->cpus); - if (!evsel->cpus) + evsel->threads = thread_map__get(evlist->threads); + + if (!evsel->cpus || !evsel->threads) return -ENOMEM; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 31b0afb68825..1b2f480a3e82 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -886,6 +886,7 @@ void perf_evsel__exit(struct perf_evsel *evsel) perf_evsel__free_id(evsel); close_cgroup(evsel->cgrp); cpu_map__put(evsel->cpus); + thread_map__put(evsel->threads); zfree(&evsel->group_name); zfree(&evsel->name); perf_evsel__object.fini(evsel); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index bb0579e8a10a..9e16a5c4eb01 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -82,6 +82,7 @@ struct perf_evsel { struct cgroup_sel *cgrp; void *handler; struct cpu_map *cpus; + struct thread_map *threads; unsigned int sample_size; int id_pos; int is_pos; -- cgit v1.2.3 From a22e99cd74a31dee4b5241bd60a256c629c808da Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 23 Jun 2015 00:36:08 +0200 Subject: perf tools: Make perf_evsel__(nr_)cpus generic Because we now propagate all evlist's cpu_maps and thread_map objects through all evsels, the perf_evsel__(nr_)cpus no longer need to be specific to stat object and check evlist and target objects. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435012588-9007-8-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 10 ---------- tools/perf/util/evsel.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index fcf99bdeb19e..3e1636cae76b 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -141,16 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) -{ - return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; -} - -static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) -{ - return perf_evsel__cpus(evsel)->nr; -} - static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) { int i; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 9e16a5c4eb01..4dbf32d94dfb 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -8,6 +8,7 @@ #include #include "xyarray.h" #include "symbol.h" +#include "cpumap.h" struct perf_counts_values { union { @@ -114,6 +115,16 @@ struct thread_map; struct perf_evlist; struct record_opts; +static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) +{ + return evsel->cpus; +} + +static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) +{ + return perf_evsel__cpus(evsel)->nr; +} + void perf_counts_values__scale(struct perf_counts_values *count, bool scale, s8 *pscaled); -- cgit v1.2.3 From d0cc439b30be638c3a606767e9469c300d397433 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 25 Jun 2015 19:32:33 -0300 Subject: perf trace: Validate syscall list passed via -e argument The 'trace' tool was accepting any names passed and just looking if syscalls returned via the raw_syscalls:* tracepoints were in that list, leading to it accepting perf events and then never finding any, as those are not valid syscall names, confusing users. Fix it by checking each entry in the list using audit_name_to_syscall, telling the user which entries are invalid and suggesting where to look for valid syscall names. E.g: [root@zoo ~]# trace -e open,foo,bar,close,baz Error: Invalid syscall bar, baz, foo Hint: try 'perf list syscalls:sys_enter_*' Hint: and: 'man syscalls' [root@zoo ~]# Reported-by: Flavio Leitner Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/n/tip-4g1i3m1z6fzsrznn2umi02wa@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2bf2ca771ca5..39ad4d0ca884 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1617,6 +1617,34 @@ static int trace__read_syscall_info(struct trace *trace, int id) return syscall__set_arg_fmts(sc); } +static int trace__validate_ev_qualifier(struct trace *trace) +{ + int err = 0; + struct str_node *pos; + + strlist__for_each(pos, trace->ev_qualifier) { + const char *sc = pos->s; + + if (audit_name_to_syscall(sc, trace->audit.machine) < 0) { + if (err == 0) { + fputs("Error:\tInvalid syscall ", trace->output); + err = -EINVAL; + } else { + fputs(", ", trace->output); + } + + fputs(sc, trace->output); + } + } + + if (err < 0) { + fputs("\nHint:\ttry 'perf list syscalls:sys_enter_*'" + "\nHint:\tand: 'man syscalls'\n", trace->output); + } + + return err; +} + /* * args is to be interpreted as a series of longs but we need to handle * 8-byte unaligned accesses. args points to raw_data within the event @@ -2862,6 +2890,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) err = -ENOMEM; goto out_close; } + + err = trace__validate_ev_qualifier(&trace); + if (err) + goto out_close; } err = target__validate(&trace.opts.target); -- cgit v1.2.3 From 62eea464380633b88902da35bf9cbd8515289703 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:06 +0200 Subject: perf thread_map: Introduce thread_map__reset function We need to reset newly allocated 'struct thread_map_data' entries, because we will introduce new comm memeber, which will get set later or not at all. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-2-git-send-email-jolsa@kernel.org [ Use sizeof(map->map[0]) to be independent of the array entry type ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread_map.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 368cc58c6892..ed76c179cf4e 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -21,11 +21,26 @@ static int filter(const struct dirent *dir) return 1; } +static void thread_map__reset(struct thread_map *map, int start, int nr) +{ + size_t size = (nr - start) * sizeof(map->map[0]); + + memset(&map->map[start], 0, size); +} + static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) { size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; + int start = map ? map->nr : 0; - return realloc(map, size); + map = realloc(map, size); + /* + * We only realloc to add more items, let's reset new items. + */ + if (map) + thread_map__reset(map, start, nr); + + return map; } #define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr) -- cgit v1.2.3 From 792402fd5c0a5a5300868e9dfc8ee569f3a39169 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:07 +0200 Subject: perf thrad_map: Add comm string into array Adding support to hold comm name together with pids in 'struct thread_map'. It will be useful for --per-thread option to display task pid together with task name. Adding thread_map__read_comms function that reads/set comm string for the 'struct thread_map'. Getting the task name from /proc/$pid/comm. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python-ext-sources | 1 + tools/perf/util/thread_map.c | 59 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/thread_map.h | 8 ++++++ 3 files changed, 68 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 5925fec90562..e23ded40c79e 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -20,3 +20,4 @@ util/stat.c util/strlist.c util/trace-event.c ../../lib/rbtree.c +util/string.c diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index ed76c179cf4e..da7646d767fe 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c @@ -8,9 +8,11 @@ #include #include "strlist.h" #include +#include #include "asm/bug.h" #include "thread_map.h" #include "util.h" +#include "debug.h" /* Skip "." and ".." directories */ static int filter(const struct dirent *dir) @@ -319,8 +321,12 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid, static void thread_map__delete(struct thread_map *threads) { if (threads) { + int i; + WARN_ONCE(atomic_read(&threads->refcnt) != 0, "thread map refcnt unbalanced\n"); + for (i = 0; i < threads->nr; i++) + free(thread_map__comm(threads, i)); free(threads); } } @@ -348,3 +354,56 @@ size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) return printed + fprintf(fp, "\n"); } + +static int get_comm(char **comm, pid_t pid) +{ + char *path; + size_t size; + int err; + + if (asprintf(&path, "%s/%d/comm", procfs__mountpoint(), pid) == -1) + return -ENOMEM; + + err = filename__read_str(path, comm, &size); + if (!err) { + /* + * We're reading 16 bytes, while filename__read_str + * allocates data per BUFSIZ bytes, so we can safely + * mark the end of the string. + */ + (*comm)[size] = 0; + rtrim(*comm); + } + + free(path); + return err; +} + +static void comm_init(struct thread_map *map, int i) +{ + pid_t pid = thread_map__pid(map, i); + char *comm = NULL; + + /* dummy pid comm initialization */ + if (pid == -1) { + map->map[i].comm = strdup("dummy"); + return; + } + + /* + * The comm name is like extra bonus ;-), + * so just warn if we fail for any reason. + */ + if (get_comm(&comm, pid)) + pr_warning("Couldn't resolve comm name for pid %d\n", pid); + + map->map[i].comm = comm; +} + +void thread_map__read_comms(struct thread_map *threads) +{ + int i; + + for (i = 0; i < threads->nr; ++i) + comm_init(threads, i); +} diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index 6b0cd2dc006b..af679d8a50f8 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h @@ -7,6 +7,7 @@ struct thread_map_data { pid_t pid; + char *comm; }; struct thread_map { @@ -44,4 +45,11 @@ thread_map__set_pid(struct thread_map *map, int thread, pid_t pid) { map->map[thread].pid = pid; } + +static inline char *thread_map__comm(struct thread_map *map, int thread) +{ + return map->map[thread].comm; +} + +void thread_map__read_comms(struct thread_map *threads); #endif /* __PERF_THREAD_MAP_H */ -- cgit v1.2.3 From 134aa44f6bff6b967efb85255ee9e8982cb8e486 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:08 +0200 Subject: perf tests: Add thread_map object tests Adding thread_map object tests for comm name values. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++++ tools/perf/tests/tests.h | 1 + tools/perf/tests/thread-map.c | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 tools/perf/tests/thread-map.c (limited to 'tools') diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index ee41e705b2eb..d20d6e6ab65b 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -31,6 +31,7 @@ perf-y += code-reading.o perf-y += sample-parsing.o perf-y += parse-no-sample-id-all.o perf-y += kmod-path.o +perf-y += thread-map.o perf-$(CONFIG_X86) += perf-time-to-tsc.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 87b9961646e4..c1dde733c3a6 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -170,6 +170,10 @@ static struct test { .desc = "Test kmod_path__parse function", .func = test__kmod_path__parse, }, + { + .desc = "Test thread map", + .func = test__thread_map, + }, { .func = NULL, }, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 8e5038b48ba8..ebb47d96bc0b 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -61,6 +61,7 @@ int test__switch_tracking(void); int test__fdarray__filter(void); int test__fdarray__add(void); int test__kmod_path__parse(void); +int test__thread_map(void); #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) #ifdef HAVE_DWARF_UNWIND_SUPPORT diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c new file mode 100644 index 000000000000..5acf000939ea --- /dev/null +++ b/tools/perf/tests/thread-map.c @@ -0,0 +1,38 @@ +#include +#include +#include "tests.h" +#include "thread_map.h" +#include "debug.h" + +int test__thread_map(void) +{ + struct thread_map *map; + + /* test map on current pid */ + map = thread_map__new_by_pid(getpid()); + TEST_ASSERT_VAL("failed to alloc map", map); + + thread_map__read_comms(map); + + TEST_ASSERT_VAL("wrong nr", map->nr == 1); + TEST_ASSERT_VAL("wrong pid", + thread_map__pid(map, 0) == getpid()); + TEST_ASSERT_VAL("wrong comm", + thread_map__comm(map, 0) && + !strcmp(thread_map__comm(map, 0), "perf")); + thread_map__put(map); + + /* test dummy pid */ + map = thread_map__new_dummy(); + TEST_ASSERT_VAL("failed to alloc map", map); + + thread_map__read_comms(map); + + TEST_ASSERT_VAL("wrong nr", map->nr == 1); + TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == -1); + TEST_ASSERT_VAL("wrong comm", + thread_map__comm(map, 0) && + !strcmp(thread_map__comm(map, 0), "dummy")); + thread_map__put(map); + return 0; +} -- cgit v1.2.3 From 1ac77e1ce8654ec94ada0c508d58ba80a4647fba Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:09 +0200 Subject: perf stat: Introduce perf_counts function Introducing perf_counts function, that returns 'struct perf_counts_values' pointer for given cpu. Also moving perf_counts* structures into stat.h. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 14 +++++++------- tools/perf/tests/openat-syscall-all-cpus.c | 4 ++-- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/util/evsel.c | 6 +++--- tools/perf/util/evsel.h | 18 +----------------- tools/perf/util/stat.h | 23 +++++++++++++++++++++++ 6 files changed, 37 insertions(+), 30 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 3e1636cae76b..49b90374232c 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -316,7 +316,7 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, if (!evsel->snapshot) perf_evsel__compute_deltas(evsel, cpu, count); perf_counts_values__scale(count, scale, NULL); - evsel->counts->cpu[cpu] = *count; + *perf_counts(evsel->counts, cpu) = *count; if (aggr_mode == AGGR_NONE) perf_stat__update_shadow_stats(evsel, count->values, cpu); break; @@ -805,9 +805,9 @@ static void print_aggr(char *prefix) s2 = aggr_get_id(evsel_list->cpus, cpu2); if (s2 != id) continue; - val += counter->counts->cpu[cpu].val; - ena += counter->counts->cpu[cpu].ena; - run += counter->counts->cpu[cpu].run; + val += perf_counts(counter->counts, cpu)->val; + ena += perf_counts(counter->counts, cpu)->ena; + run += perf_counts(counter->counts, cpu)->run; nr++; } if (prefix) @@ -915,9 +915,9 @@ static void print_counter(struct perf_evsel *counter, char *prefix) int cpu; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - val = counter->counts->cpu[cpu].val; - ena = counter->counts->cpu[cpu].ena; - run = counter->counts->cpu[cpu].run; + val = perf_counts(counter->counts, cpu)->val; + ena = perf_counts(counter->counts, cpu)->ena; + run = perf_counts(counter->counts, cpu)->run; if (prefix) fprintf(output, "%s", prefix); diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index b8d552b13950..e8d944fe1bd0 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -98,9 +98,9 @@ int test__openat_syscall_event_on_all_cpus(void) } expected = nr_openat_calls + cpu; - if (evsel->counts->cpu[cpu].val != expected) { + if (perf_counts(evsel->counts, cpu)->val != expected) { pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", - expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); + expected, cpus->map[cpu], perf_counts(evsel->counts, cpu)->val); err = -1; } } diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index bdfa1f446681..e86fc477a74f 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -44,7 +44,7 @@ int test__openat_syscall_event(void) goto out_close_fd; } - if (evsel->counts->cpu[0].val != nr_openat_calls) { + if (perf_counts(evsel->counts, 0)->val != nr_openat_calls) { pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n", nr_openat_calls, evsel->counts->cpu[0].val); goto out_close_fd; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1b2f480a3e82..8401b042b9d4 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -910,8 +910,8 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, tmp = evsel->prev_raw_counts->aggr; evsel->prev_raw_counts->aggr = *count; } else { - tmp = evsel->prev_raw_counts->cpu[cpu]; - evsel->prev_raw_counts->cpu[cpu] = *count; + tmp = *perf_counts(evsel->prev_raw_counts, cpu); + *perf_counts(evsel->prev_raw_counts, cpu) = *count; } count->val = count->val - tmp.val; @@ -972,7 +972,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, perf_evsel__compute_deltas(evsel, cpu, &count); perf_counts_values__scale(&count, scale, NULL); - evsel->counts->cpu[cpu] = count; + *perf_counts(evsel->counts, cpu) = count; return 0; } diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 4dbf32d94dfb..b420f8f5fc5d 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -9,23 +9,7 @@ #include "xyarray.h" #include "symbol.h" #include "cpumap.h" - -struct perf_counts_values { - union { - struct { - u64 val; - u64 ena; - u64 run; - }; - u64 values[3]; - }; -}; - -struct perf_counts { - s8 scaled; - struct perf_counts_values aggr; - struct perf_counts_values cpu[]; -}; +#include "stat.h" struct perf_evsel; diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 093dc3cb28dd..5e43348836a6 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -31,6 +31,29 @@ enum aggr_mode { AGGR_CORE, }; +struct perf_counts_values { + union { + struct { + u64 val; + u64 ena; + u64 run; + }; + u64 values[3]; + }; +}; + +struct perf_counts { + s8 scaled; + struct perf_counts_values aggr; + struct perf_counts_values cpu[]; +}; + +static inline struct perf_counts_values* +perf_counts(struct perf_counts *counts, int cpu) +{ + return &counts->cpu[cpu]; +} + void update_stats(struct stats *stats, u64 val); double avg_stats(struct stats *stats); double stddev_stats(struct stats *stats); -- cgit v1.2.3 From a8e02324dfe6bcafc15d02b790f33321ec4facb0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:10 +0200 Subject: perf stat: Use xyarray for cpu evsel counts Switching single dimensional array of 'struct perf_counts_values' with xyarray object, so we could store thread dimension counts. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 2 +- tools/perf/tests/openat-syscall.c | 2 +- tools/perf/util/stat.c | 31 ++++++++++++++++++++++--------- tools/perf/util/stat.h | 7 ++++--- 4 files changed, 28 insertions(+), 14 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 49b90374232c..055ce83dd6f2 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -218,7 +218,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist) evlist__for_each(evlist, evsel) { perf_evsel__reset_stat_priv(evsel); - perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel)); + perf_evsel__reset_counts(evsel); } perf_stat__reset_shadow_stats(); diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index e86fc477a74f..bd882f09ebbc 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -46,7 +46,7 @@ int test__openat_syscall_event(void) if (perf_counts(evsel->counts, 0)->val != nr_openat_calls) { pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n", - nr_openat_calls, evsel->counts->cpu[0].val); + nr_openat_calls, perf_counts(evsel->counts, 0)->val); goto out_close_fd; } diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 4014b709f956..453480aa7650 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -97,26 +97,39 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) struct perf_counts *perf_counts__new(int ncpus) { - int size = sizeof(struct perf_counts) + - ncpus * sizeof(struct perf_counts_values); + struct perf_counts *counts = zalloc(sizeof(*counts)); - return zalloc(size); + if (counts) { + struct xyarray *cpu; + + cpu = xyarray__new(ncpus, 1, sizeof(struct perf_counts_values)); + if (!cpu) { + free(counts); + return NULL; + } + + counts->cpu = cpu; + } + + return counts; } void perf_counts__delete(struct perf_counts *counts) { - free(counts); + if (counts) { + xyarray__delete(counts->cpu); + free(counts); + } } -static void perf_counts__reset(struct perf_counts *counts, int ncpus) +static void perf_counts__reset(struct perf_counts *counts) { - memset(counts, 0, (sizeof(*counts) + - (ncpus * sizeof(struct perf_counts_values)))); + xyarray__reset(counts->cpu); } -void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus) +void perf_evsel__reset_counts(struct perf_evsel *evsel) { - perf_counts__reset(evsel->counts, ncpus); + perf_counts__reset(evsel->counts); } int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 5e43348836a6..6d07612545e0 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -3,6 +3,7 @@ #include #include +#include "xyarray.h" struct stats { @@ -45,13 +46,13 @@ struct perf_counts_values { struct perf_counts { s8 scaled; struct perf_counts_values aggr; - struct perf_counts_values cpu[]; + struct xyarray *cpu; }; static inline struct perf_counts_values* perf_counts(struct perf_counts *counts, int cpu) { - return &counts->cpu[cpu]; + return xyarray__entry(counts->cpu, cpu, 0); } void update_stats(struct stats *stats, u64 val); @@ -88,7 +89,7 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel, struct perf_counts *perf_counts__new(int ncpus); void perf_counts__delete(struct perf_counts *counts); -void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus); +void perf_evsel__reset_counts(struct perf_evsel *evsel); int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); void perf_evsel__free_counts(struct perf_evsel *evsel); #endif -- cgit v1.2.3 From a6fa003855d38d53d90c1a8a5827102e62702334 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:11 +0200 Subject: perf stat: Make stats work over the thread dimension Now that we have space for thread dimension counts, let's store it. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-7-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 32 +++++++++++++++++------------- tools/perf/tests/openat-syscall-all-cpus.c | 6 +++--- tools/perf/tests/openat-syscall.c | 4 ++-- tools/perf/util/evsel.c | 12 +++++------ tools/perf/util/evsel.h | 2 +- tools/perf/util/stat.c | 8 ++++---- tools/perf/util/stat.h | 8 ++++---- 7 files changed, 38 insertions(+), 34 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 055ce83dd6f2..983bcbbe8e0a 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -166,11 +166,12 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) zfree(&evsel->priv); } -static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) +static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, + int ncpus, int nthreads) { struct perf_counts *counts; - counts = perf_counts__new(perf_evsel__nr_cpus(evsel)); + counts = perf_counts__new(ncpus, nthreads); if (counts) evsel->prev_raw_counts = counts; @@ -197,11 +198,14 @@ static void perf_evlist__free_stats(struct perf_evlist *evlist) static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) { struct perf_evsel *evsel; + int nthreads = thread_map__nr(evsel_list->threads); evlist__for_each(evlist, evsel) { + int ncpus = perf_evsel__nr_cpus(evsel); + if (perf_evsel__alloc_stat_priv(evsel) < 0 || - perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 || - (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0)) + perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 || + (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0)) goto out_free; } @@ -294,7 +298,7 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) return 0; } -static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, +static int read_cb(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count) { struct perf_counts_values *aggr = &evsel->counts->aggr; @@ -314,9 +318,9 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused, case AGGR_SOCKET: case AGGR_NONE: if (!evsel->snapshot) - perf_evsel__compute_deltas(evsel, cpu, count); + perf_evsel__compute_deltas(evsel, cpu, thread, count); perf_counts_values__scale(count, scale, NULL); - *perf_counts(evsel->counts, cpu) = *count; + *perf_counts(evsel->counts, cpu, thread) = *count; if (aggr_mode == AGGR_NONE) perf_stat__update_shadow_stats(evsel, count->values, cpu); break; @@ -352,7 +356,7 @@ static int read_counter_aggr(struct perf_evsel *counter) return -1; if (!counter->snapshot) - perf_evsel__compute_deltas(counter, -1, aggr); + perf_evsel__compute_deltas(counter, -1, -1, aggr); perf_counts_values__scale(aggr, scale, &counter->counts->scaled); for (i = 0; i < 3; i++) @@ -805,9 +809,9 @@ static void print_aggr(char *prefix) s2 = aggr_get_id(evsel_list->cpus, cpu2); if (s2 != id) continue; - val += perf_counts(counter->counts, cpu)->val; - ena += perf_counts(counter->counts, cpu)->ena; - run += perf_counts(counter->counts, cpu)->run; + val += perf_counts(counter->counts, cpu, 0)->val; + ena += perf_counts(counter->counts, cpu, 0)->ena; + run += perf_counts(counter->counts, cpu, 0)->run; nr++; } if (prefix) @@ -915,9 +919,9 @@ static void print_counter(struct perf_evsel *counter, char *prefix) int cpu; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - val = perf_counts(counter->counts, cpu)->val; - ena = perf_counts(counter->counts, cpu)->ena; - run = perf_counts(counter->counts, cpu)->run; + val = perf_counts(counter->counts, cpu, 0)->val; + ena = perf_counts(counter->counts, cpu, 0)->ena; + run = perf_counts(counter->counts, cpu, 0)->run; if (prefix) fprintf(output, "%s", prefix); diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index e8d944fe1bd0..a572f87e9c8d 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c @@ -78,7 +78,7 @@ int test__openat_syscall_event_on_all_cpus(void) * we use the auto allocation it will allocate just for 1 cpu, * as we start by cpu 0. */ - if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) { + if (perf_evsel__alloc_counts(evsel, cpus->nr, 1) < 0) { pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr); goto out_close_fd; } @@ -98,9 +98,9 @@ int test__openat_syscall_event_on_all_cpus(void) } expected = nr_openat_calls + cpu; - if (perf_counts(evsel->counts, cpu)->val != expected) { + if (perf_counts(evsel->counts, cpu, 0)->val != expected) { pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", - expected, cpus->map[cpu], perf_counts(evsel->counts, cpu)->val); + expected, cpus->map[cpu], perf_counts(evsel->counts, cpu, 0)->val); err = -1; } } diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index bd882f09ebbc..c9a37bc6b33a 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c @@ -44,9 +44,9 @@ int test__openat_syscall_event(void) goto out_close_fd; } - if (perf_counts(evsel->counts, 0)->val != nr_openat_calls) { + if (perf_counts(evsel->counts, 0, 0)->val != nr_openat_calls) { pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n", - nr_openat_calls, perf_counts(evsel->counts, 0)->val); + nr_openat_calls, perf_counts(evsel->counts, 0, 0)->val); goto out_close_fd; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8401b042b9d4..cd6ce7066f85 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -898,7 +898,7 @@ void perf_evsel__delete(struct perf_evsel *evsel) free(evsel); } -void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, +void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count) { struct perf_counts_values tmp; @@ -910,8 +910,8 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, tmp = evsel->prev_raw_counts->aggr; evsel->prev_raw_counts->aggr = *count; } else { - tmp = *perf_counts(evsel->prev_raw_counts, cpu); - *perf_counts(evsel->prev_raw_counts, cpu) = *count; + tmp = *perf_counts(evsel->prev_raw_counts, cpu, thread); + *perf_counts(evsel->prev_raw_counts, cpu, thread) = *count; } count->val = count->val - tmp.val; @@ -964,15 +964,15 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, if (FD(evsel, cpu, thread) < 0) return -EINVAL; - if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0) + if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0) return -ENOMEM; if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) return -errno; - perf_evsel__compute_deltas(evsel, cpu, &count); + perf_evsel__compute_deltas(evsel, cpu, thread, &count); perf_counts_values__scale(&count, scale, NULL); - *perf_counts(evsel->counts, cpu) = count; + *perf_counts(evsel->counts, cpu, thread) = count; return 0; } diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index b420f8f5fc5d..020f7e13634a 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -112,7 +112,7 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) void perf_counts_values__scale(struct perf_counts_values *count, bool scale, s8 *pscaled); -void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, +void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count); int perf_evsel__object_config(size_t object_size, diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 453480aa7650..7bcc19b62dd1 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -95,14 +95,14 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } -struct perf_counts *perf_counts__new(int ncpus) +struct perf_counts *perf_counts__new(int ncpus, int nthreads) { struct perf_counts *counts = zalloc(sizeof(*counts)); if (counts) { struct xyarray *cpu; - cpu = xyarray__new(ncpus, 1, sizeof(struct perf_counts_values)); + cpu = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values)); if (!cpu) { free(counts); return NULL; @@ -132,9 +132,9 @@ void perf_evsel__reset_counts(struct perf_evsel *evsel) perf_counts__reset(evsel->counts); } -int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) +int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads) { - evsel->counts = perf_counts__new(ncpus); + evsel->counts = perf_counts__new(ncpus, nthreads); return evsel->counts != NULL ? 0 : -ENOMEM; } diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 6d07612545e0..e0b8dc50fbb6 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -50,9 +50,9 @@ struct perf_counts { }; static inline struct perf_counts_values* -perf_counts(struct perf_counts *counts, int cpu) +perf_counts(struct perf_counts *counts, int cpu, int thread) { - return xyarray__entry(counts->cpu, cpu, 0); + return xyarray__entry(counts->cpu, cpu, thread); } void update_stats(struct stats *stats, u64 val); @@ -86,10 +86,10 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel, double avg, int cpu, enum aggr_mode aggr); -struct perf_counts *perf_counts__new(int ncpus); +struct perf_counts *perf_counts__new(int ncpus, int nthreads); void perf_counts__delete(struct perf_counts *counts); void perf_evsel__reset_counts(struct perf_evsel *evsel); -int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); +int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__free_counts(struct perf_evsel *evsel); #endif -- cgit v1.2.3 From 57b289159ab4fe1f7b2b531464cf67f65e48dd00 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:12 +0200 Subject: perf stat: Rename struct perf_counts::cpu member to values Renaming 'struct xyarray *cpu' pointer to more fitting/generic values, because now we store both cpu and thread values. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-8-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat.c | 12 ++++++------ tools/perf/util/stat.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 7bcc19b62dd1..197a2db5f2c4 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -100,15 +100,15 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads) struct perf_counts *counts = zalloc(sizeof(*counts)); if (counts) { - struct xyarray *cpu; + struct xyarray *values; - cpu = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values)); - if (!cpu) { + values = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values)); + if (!values) { free(counts); return NULL; } - counts->cpu = cpu; + counts->values = values; } return counts; @@ -117,14 +117,14 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads) void perf_counts__delete(struct perf_counts *counts) { if (counts) { - xyarray__delete(counts->cpu); + xyarray__delete(counts->values); free(counts); } } static void perf_counts__reset(struct perf_counts *counts) { - xyarray__reset(counts->cpu); + xyarray__reset(counts->values); } void perf_evsel__reset_counts(struct perf_evsel *evsel) diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index e0b8dc50fbb6..295d1e29d3d6 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -46,13 +46,13 @@ struct perf_counts_values { struct perf_counts { s8 scaled; struct perf_counts_values aggr; - struct xyarray *cpu; + struct xyarray *values; }; static inline struct perf_counts_values* perf_counts(struct perf_counts *counts, int cpu, int thread) { - return xyarray__entry(counts->cpu, cpu, thread); + return xyarray__entry(counts->values, cpu, thread); } void update_stats(struct stats *stats, u64 val); -- cgit v1.2.3 From 254ecbc7474dfa08155c5595e90cd4a0fa9d14ce Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:13 +0200 Subject: perf stat: Introduce perf_evlist__reset_stats To fit in with the rest of the helpers (alloc and free). Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-9-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 983bcbbe8e0a..188cd98a4ab3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -216,7 +216,7 @@ out_free: return -1; } -static void perf_stat__reset_stats(struct perf_evlist *evlist) +static void perf_evlist__reset_stats(struct perf_evlist *evlist) { struct perf_evsel *evsel; @@ -224,7 +224,11 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist) perf_evsel__reset_stat_priv(evsel); perf_evsel__reset_counts(evsel); } +} +static void perf_stat__reset_stats(void) +{ + perf_evlist__reset_stats(evsel_list); perf_stat__reset_shadow_stats(); } @@ -1473,7 +1477,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) status = run_perf_stat(argc, argv); if (forever && status != -1) { print_stat(argc, argv); - perf_stat__reset_stats(evsel_list); + perf_stat__reset_stats(); } } -- cgit v1.2.3 From 9689edfabc1547155a7cdd1304fd294107054291 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:14 +0200 Subject: perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object Moving perf_evsel__(alloc|free|reset)_stat_priv into stat object, so it could be used outside stat command in following patches. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-10-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 25 ------------------------- tools/perf/util/stat.c | 25 +++++++++++++++++++++++++ tools/perf/util/stat.h | 4 ++++ 3 files changed, 29 insertions(+), 25 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 188cd98a4ab3..8a7fd0c60ab1 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -141,31 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) -{ - int i; - struct perf_stat *ps = evsel->priv; - - for (i = 0; i < 3; i++) - init_stats(&ps->res_stats[i]); - - perf_stat_evsel_id_init(evsel); -} - -static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) -{ - evsel->priv = zalloc(sizeof(struct perf_stat)); - if (evsel->priv == NULL) - return -ENOMEM; - perf_evsel__reset_stat_priv(evsel); - return 0; -} - -static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) -{ - zfree(&evsel->priv); -} - static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, int ncpus, int nthreads) { diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 197a2db5f2c4..b8c329f41f13 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -143,3 +143,28 @@ void perf_evsel__free_counts(struct perf_evsel *evsel) perf_counts__delete(evsel->counts); evsel->counts = NULL; } + +void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) +{ + int i; + struct perf_stat *ps = evsel->priv; + + for (i = 0; i < 3; i++) + init_stats(&ps->res_stats[i]); + + perf_stat_evsel_id_init(evsel); +} + +int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) +{ + evsel->priv = zalloc(sizeof(struct perf_stat)); + if (evsel->priv == NULL) + return -ENOMEM; + perf_evsel__reset_stat_priv(evsel); + return 0; +} + +void perf_evsel__free_stat_priv(struct perf_evsel *evsel) +{ + zfree(&evsel->priv); +} diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 295d1e29d3d6..c441cb312565 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -92,4 +92,8 @@ void perf_counts__delete(struct perf_counts *counts); void perf_evsel__reset_counts(struct perf_evsel *evsel); int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__free_counts(struct perf_evsel *evsel); + +void perf_evsel__reset_stat_priv(struct perf_evsel *evsel); +int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel); +void perf_evsel__free_stat_priv(struct perf_evsel *evsel); #endif -- cgit v1.2.3 From a939512d10a5583a32ae85c1bff6c4ae63a8a517 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:15 +0200 Subject: perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into stat object Moving perf_evsel__(alloc|free)_prev_raw_counts into stat object, so it could be used in following patches. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-11-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 18 ------------------ tools/perf/util/stat.c | 18 ++++++++++++++++++ tools/perf/util/stat.h | 4 ++++ 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8a7fd0c60ab1..0ccba5c6b61d 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -141,24 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, - int ncpus, int nthreads) -{ - struct perf_counts *counts; - - counts = perf_counts__new(ncpus, nthreads); - if (counts) - evsel->prev_raw_counts = counts; - - return counts ? 0 : -ENOMEM; -} - -static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) -{ - perf_counts__delete(evsel->prev_raw_counts); - evsel->prev_raw_counts = NULL; -} - static void perf_evlist__free_stats(struct perf_evlist *evlist) { struct perf_evsel *evsel; diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index b8c329f41f13..6221c3898397 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -168,3 +168,21 @@ void perf_evsel__free_stat_priv(struct perf_evsel *evsel) { zfree(&evsel->priv); } + +int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, + int ncpus, int nthreads) +{ + struct perf_counts *counts; + + counts = perf_counts__new(ncpus, nthreads); + if (counts) + evsel->prev_raw_counts = counts; + + return counts ? 0 : -ENOMEM; +} + +void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) +{ + perf_counts__delete(evsel->prev_raw_counts); + evsel->prev_raw_counts = NULL; +} diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index c441cb312565..454b26875aef 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -96,4 +96,8 @@ void perf_evsel__free_counts(struct perf_evsel *evsel); void perf_evsel__reset_stat_priv(struct perf_evsel *evsel); int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel); void perf_evsel__free_stat_priv(struct perf_evsel *evsel); + +int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, + int ncpus, int nthreads); +void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel); #endif -- cgit v1.2.3 From 24e34f68e21a47a582b3cc2eccdb835b80b1830a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:16 +0200 Subject: perf stat: Move perf_evlist__(alloc|free|reset)_stats into stat object Moving perf_evlist__(alloc|free|reset)_stats into stat object, so it could be used in following patches. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-12-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 42 ------------------------------------------ tools/perf/util/evlist.h | 1 - tools/perf/util/stat.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/stat.h | 6 ++++++ 4 files changed, 50 insertions(+), 43 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 0ccba5c6b61d..3e385f9f12ee 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -141,48 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, } } -static void perf_evlist__free_stats(struct perf_evlist *evlist) -{ - struct perf_evsel *evsel; - - evlist__for_each(evlist, evsel) { - perf_evsel__free_stat_priv(evsel); - perf_evsel__free_counts(evsel); - perf_evsel__free_prev_raw_counts(evsel); - } -} - -static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) -{ - struct perf_evsel *evsel; - int nthreads = thread_map__nr(evsel_list->threads); - - evlist__for_each(evlist, evsel) { - int ncpus = perf_evsel__nr_cpus(evsel); - - if (perf_evsel__alloc_stat_priv(evsel) < 0 || - perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 || - (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0)) - goto out_free; - } - - return 0; - -out_free: - perf_evlist__free_stats(evlist); - return -1; -} - -static void perf_evlist__reset_stats(struct perf_evlist *evlist) -{ - struct perf_evsel *evsel; - - evlist__for_each(evlist, evsel) { - perf_evsel__reset_stat_priv(evsel); - perf_evsel__reset_counts(evsel); - } -} - static void perf_stat__reset_stats(void) { perf_evlist__reset_stats(evsel_list); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a8489b9d2812..037633c1da9d 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -289,5 +289,4 @@ void perf_evlist__to_front(struct perf_evlist *evlist, void perf_evlist__set_tracking_event(struct perf_evlist *evlist, struct perf_evsel *tracking_evsel); - #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 6221c3898397..818cb022fcb6 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -1,6 +1,8 @@ #include #include "stat.h" +#include "evlist.h" #include "evsel.h" +#include "thread_map.h" void update_stats(struct stats *stats, u64 val) { @@ -186,3 +188,45 @@ void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) perf_counts__delete(evsel->prev_raw_counts); evsel->prev_raw_counts = NULL; } + +int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) +{ + struct perf_evsel *evsel; + int nthreads = thread_map__nr(evlist->threads); + + evlist__for_each(evlist, evsel) { + int ncpus = perf_evsel__nr_cpus(evsel); + + if (perf_evsel__alloc_stat_priv(evsel) < 0 || + perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 || + (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0)) + goto out_free; + } + + return 0; + +out_free: + perf_evlist__free_stats(evlist); + return -1; +} + +void perf_evlist__free_stats(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) { + perf_evsel__free_stat_priv(evsel); + perf_evsel__free_counts(evsel); + perf_evsel__free_prev_raw_counts(evsel); + } +} + +void perf_evlist__reset_stats(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) { + perf_evsel__reset_stat_priv(evsel); + perf_evsel__reset_counts(evsel); + } +} diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 454b26875aef..5f62db2472c7 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -70,6 +70,8 @@ static inline void init_stats(struct stats *stats) } struct perf_evsel; +struct perf_evlist; + bool __perf_evsel_stat__is(struct perf_evsel *evsel, enum perf_stat_evsel_id id); @@ -100,4 +102,8 @@ void perf_evsel__free_stat_priv(struct perf_evsel *evsel); int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel); + +int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); +void perf_evlist__free_stats(struct perf_evlist *evlist); +void perf_evlist__reset_stats(struct perf_evlist *evlist); #endif -- cgit v1.2.3 From a7d0a102e4ae46b75b70a9500979e7ed3cdf183f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:17 +0200 Subject: perf stat: Introduce perf_evsel__alloc_stats function Move all stat allocation logic related to stat object under single function. This way we can use it separately for stat object out of evlist object. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-13-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat.c | 20 ++++++++++++++------ tools/perf/util/stat.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 818cb022fcb6..f2a0d1521e26 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -189,17 +189,25 @@ void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) evsel->prev_raw_counts = NULL; } +int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw) +{ + int ncpus = perf_evsel__nr_cpus(evsel); + int nthreads = thread_map__nr(evsel->threads); + + if (perf_evsel__alloc_stat_priv(evsel) < 0 || + perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 || + (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0)) + return -ENOMEM; + + return 0; +} + int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) { struct perf_evsel *evsel; - int nthreads = thread_map__nr(evlist->threads); evlist__for_each(evlist, evsel) { - int ncpus = perf_evsel__nr_cpus(evsel); - - if (perf_evsel__alloc_stat_priv(evsel) < 0 || - perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 || - (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0)) + if (perf_evsel__alloc_stats(evsel, alloc_raw)) goto out_free; } diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 5f62db2472c7..9f05c571befe 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -103,6 +103,8 @@ int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel); +int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw); + int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); void perf_evlist__free_stats(struct perf_evlist *evlist); void perf_evlist__reset_stats(struct perf_evlist *evlist); -- cgit v1.2.3 From f99f4719b841a9745d6a7652eef3956aaf2db66a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:18 +0200 Subject: perf stat: Introduce perf_evsel__read function Adding simple read function that reads/store data into given struct perf_counts_values *count object. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-14-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 14 ++++++++++++++ tools/perf/util/evsel.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index cd6ce7066f85..2e0a4e064f44 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -955,6 +955,20 @@ int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread, return cb(evsel, cpu, thread, &count); } +int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, + struct perf_counts_values *count) +{ + memset(count, 0, sizeof(*count)); + + if (FD(evsel, cpu, thread) < 0) + return -EINVAL; + + if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) < 0) + return -errno; + + return 0; +} + int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, int cpu, int thread, bool scale) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 020f7e13634a..a79944a21e8f 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -236,6 +236,9 @@ typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel, int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread, perf_evsel__read_cb_t cb); +int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, + struct perf_counts_values *count); + int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, int cpu, int thread, bool scale); -- cgit v1.2.3 From 106a94a0f8c207ef4113ce7e32f34a00b3b174e7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:19 +0200 Subject: perf stat: Introduce read_counters function Moving read counters logic into single read_counters function, which will be called for both interval and overall processing legs. The reason is to split reading and processing (following patches) counters code, so we could read counters from other sources (like perf.data) and process them in the same way as 'perf stat' command does. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-15-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 3e385f9f12ee..158859e622d3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -323,27 +323,35 @@ static int read_counter(struct perf_evsel *counter) return 0; } -static void print_interval(void) +static void read_counters(bool close) { - static int num_print_interval; struct perf_evsel *counter; struct perf_stat *ps; - struct timespec ts, rs; - char prefix[64]; - if (aggr_mode == AGGR_GLOBAL) { - evlist__for_each(evsel_list, counter) { - ps = counter->priv; - memset(ps->res_stats, 0, sizeof(ps->res_stats)); + evlist__for_each(evsel_list, counter) { + ps = counter->priv; + memset(ps->res_stats, 0, sizeof(ps->res_stats)); + + if (aggr_mode == AGGR_GLOBAL) read_counter_aggr(counter); - } - } else { - evlist__for_each(evsel_list, counter) { - ps = counter->priv; - memset(ps->res_stats, 0, sizeof(ps->res_stats)); + else read_counter(counter); + + if (close) { + perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), + thread_map__nr(evsel_list->threads)); } } +} + +static void print_interval(void) +{ + static int num_print_interval; + struct perf_evsel *counter; + struct timespec ts, rs; + char prefix[64]; + + read_counters(false); clock_gettime(CLOCK_MONOTONIC, &ts); diff_timespec(&rs, &ts, &ref_time); @@ -525,18 +533,7 @@ static int __run_perf_stat(int argc, const char **argv) update_stats(&walltime_nsecs_stats, t1 - t0); - if (aggr_mode == AGGR_GLOBAL) { - evlist__for_each(evsel_list, counter) { - read_counter_aggr(counter); - perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), - thread_map__nr(evsel_list->threads)); - } - } else { - evlist__for_each(evsel_list, counter) { - read_counter(counter); - perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); - } - } + read_counters(true); return WEXITSTATUS(status); } -- cgit v1.2.3 From 3b3eb044519ac4c422dbc6084303c470b8d2dc61 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:20 +0200 Subject: perf stat: Separate counters reading and processing Separating counters reading and processing so we could use the processing part in following patches. Using simple reading via perf_evsel__read function to read counters now, because part of the processing was in the read_cb callback. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-16-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 56 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 17 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 158859e622d3..74ac92baa2bd 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -217,8 +217,9 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) return 0; } -static int read_cb(struct perf_evsel *evsel, int cpu, int thread, - struct perf_counts_values *count) +static int +process_counter_values(struct perf_evsel *evsel, int cpu, int thread, + struct perf_counts_values *count) { struct perf_counts_values *aggr = &evsel->counts->aggr; static struct perf_counts_values zero; @@ -239,7 +240,6 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread, if (!evsel->snapshot) perf_evsel__compute_deltas(evsel, cpu, thread, count); perf_counts_values__scale(count, scale, NULL); - *perf_counts(evsel->counts, cpu, thread) = *count; if (aggr_mode == AGGR_NONE) perf_stat__update_shadow_stats(evsel, count->values, cpu); break; @@ -256,23 +256,41 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread, return 0; } -static int read_counter(struct perf_evsel *counter); +static int process_counter_maps(struct perf_evsel *counter) +{ + int nthreads = thread_map__nr(counter->threads); + int ncpus = perf_evsel__nr_cpus(counter); + int cpu, thread; -/* - * Read out the results of a single counter: - * aggregate counts across CPUs in system-wide mode - */ -static int read_counter_aggr(struct perf_evsel *counter) + if (counter->system_wide) + nthreads = 1; + + for (thread = 0; thread < nthreads; thread++) { + for (cpu = 0; cpu < ncpus; cpu++) { + if (process_counter_values(counter, cpu, thread, + perf_counts(counter->counts, cpu, thread))) + return -1; + } + } + + return 0; +} + +static int process_counter(struct perf_evsel *counter) { struct perf_counts_values *aggr = &counter->counts->aggr; struct perf_stat *ps = counter->priv; u64 *count = counter->counts->aggr.values; - int i; + int i, ret; aggr->val = aggr->ena = aggr->run = 0; - if (read_counter(counter)) - return -1; + ret = process_counter_maps(counter); + if (ret) + return ret; + + if (aggr_mode != AGGR_GLOBAL) + return 0; if (!counter->snapshot) perf_evsel__compute_deltas(counter, -1, -1, aggr); @@ -315,7 +333,10 @@ static int read_counter(struct perf_evsel *counter) for (thread = 0; thread < nthreads; thread++) { for (cpu = 0; cpu < ncpus; cpu++) { - if (perf_evsel__read_cb(counter, cpu, thread, read_cb)) + struct perf_counts_values *count; + + count = perf_counts(counter->counts, cpu, thread); + if (perf_evsel__read(counter, cpu, thread, count)) return -1; } } @@ -332,10 +353,11 @@ static void read_counters(bool close) ps = counter->priv; memset(ps->res_stats, 0, sizeof(ps->res_stats)); - if (aggr_mode == AGGR_GLOBAL) - read_counter_aggr(counter); - else - read_counter(counter); + if (read_counter(counter)) + pr_warning("failed to read counter %s\n", counter->name); + + if (process_counter(counter)) + pr_warning("failed to process counter %s\n", counter->name); if (close) { perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), -- cgit v1.2.3 From 32ce0a47aaa401a7dd27dfe65210f3e3aa809682 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:21 +0200 Subject: perf stat: Move zero_per_pkg into counter process code Moving zero_per_pkg into counter process code, to make the reading path free of processing logic. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-17-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 74ac92baa2bd..b7c184bd559c 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -285,6 +285,9 @@ static int process_counter(struct perf_evsel *counter) aggr->val = aggr->ena = aggr->run = 0; + if (counter->per_pkg) + zero_per_pkg(counter); + ret = process_counter_maps(counter); if (ret) return ret; @@ -328,9 +331,6 @@ static int read_counter(struct perf_evsel *counter) if (counter->system_wide) nthreads = 1; - if (counter->per_pkg) - zero_per_pkg(counter); - for (thread = 0; thread < nthreads; thread++) { for (cpu = 0; cpu < ncpus; cpu++) { struct perf_counts_values *count; -- cgit v1.2.3 From 7ddb1b6bbf1e614e6700f226cb0a559c5c635336 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:22 +0200 Subject: perf stat: Move perf_stat initialization counter process code Moving perf_stat initialization counter process code, to make the reading path free of processing logic. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-18-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index b7c184bd559c..526f67753664 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -284,6 +284,7 @@ static int process_counter(struct perf_evsel *counter) int i, ret; aggr->val = aggr->ena = aggr->run = 0; + memset(ps->res_stats, 0, sizeof(ps->res_stats)); if (counter->per_pkg) zero_per_pkg(counter); @@ -347,12 +348,8 @@ static int read_counter(struct perf_evsel *counter) static void read_counters(bool close) { struct perf_evsel *counter; - struct perf_stat *ps; evlist__for_each(evsel_list, counter) { - ps = counter->priv; - memset(ps->res_stats, 0, sizeof(ps->res_stats)); - if (read_counter(counter)) pr_warning("failed to read counter %s\n", counter->name); -- cgit v1.2.3 From d8ee3b54d0458cbed0a31a410458f4bfd38fc147 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:23 +0200 Subject: perf stat: Remove perf_evsel__read_cb function It's no longer used, the stat command uses perf_evsel__read now. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-19-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 16 ---------------- tools/perf/util/evsel.h | 7 ------- 2 files changed, 23 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 2e0a4e064f44..2936b3080722 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -939,22 +939,6 @@ void perf_counts_values__scale(struct perf_counts_values *count, *pscaled = scaled; } -int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread, - perf_evsel__read_cb_t cb) -{ - struct perf_counts_values count; - - memset(&count, 0, sizeof(count)); - - if (FD(evsel, cpu, thread) < 0) - return -EINVAL; - - if (readn(FD(evsel, cpu, thread), &count, sizeof(count)) < 0) - return -errno; - - return cb(evsel, cpu, thread, &count); -} - int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index a79944a21e8f..4a7ed5656cf0 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -229,13 +229,6 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, (a)->attr.type == (b)->attr.type && \ (a)->attr.config == (b)->attr.config) -typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel, - int cpu, int thread, - struct perf_counts_values *count); - -int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread, - perf_evsel__read_cb_t cb); - int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, struct perf_counts_values *count); -- cgit v1.2.3 From ba411a954eae3e88c02667a5670cac97fb9c3f58 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:24 +0200 Subject: perf stat: Rename print_interval to process_interval It suits better, because the function also reads counter's data. Also the 'print_interval' name will be used in following generalization of counters display. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-20-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 526f67753664..aa706fca410e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -363,7 +363,7 @@ static void read_counters(bool close) } } -static void print_interval(void) +static void process_interval(void) { static int num_print_interval; struct perf_evsel *counter; @@ -526,7 +526,7 @@ static int __run_perf_stat(int argc, const char **argv) if (interval) { while (!waitpid(child_pid, &status, WNOHANG)) { nanosleep(&ts, NULL); - print_interval(); + process_interval(); } } wait(&status); @@ -544,7 +544,7 @@ static int __run_perf_stat(int argc, const char **argv) while (!done) { nanosleep(&ts, NULL); if (interval) - print_interval(); + process_interval(); } } -- cgit v1.2.3 From 5835e2286583e4fa6c2a609446e1320e7da2b161 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:25 +0200 Subject: perf stat: Using init_stats instead of memset The init_stats function is meant to init 'struct stats'. Reported-by: David Ahern Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-21-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index aa706fca410e..39a97ade2cf3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -284,7 +284,7 @@ static int process_counter(struct perf_evsel *counter) int i, ret; aggr->val = aggr->ena = aggr->run = 0; - memset(ps->res_stats, 0, sizeof(ps->res_stats)); + init_stats(ps->res_stats); if (counter->per_pkg) zero_per_pkg(counter); -- cgit v1.2.3 From d4f63a4741a808c0bf25d92884713008706fca16 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:26 +0200 Subject: perf stat: Introduce print_counters function Centralize counters print code into single print_counters function. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-22-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 127 +++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 63 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 39a97ade2cf3..56dc8881cb05 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -67,10 +67,7 @@ #define CNTR_NOT_SUPPORTED "" #define CNTR_NOT_COUNTED "" -static void print_stat(int argc, const char **argv); -static void print_counter_aggr(struct perf_evsel *counter, char *prefix); -static void print_counter(struct perf_evsel *counter, char *prefix); -static void print_aggr(char *prefix); +static void print_counters(struct timespec *ts, int argc, const char **argv); /* Default events used for perf stat -T */ static const char *transaction_attrs = { @@ -365,53 +362,14 @@ static void read_counters(bool close) static void process_interval(void) { - static int num_print_interval; - struct perf_evsel *counter; struct timespec ts, rs; - char prefix[64]; read_counters(false); clock_gettime(CLOCK_MONOTONIC, &ts); diff_timespec(&rs, &ts, &ref_time); - sprintf(prefix, "%6lu.%09lu%s", rs.tv_sec, rs.tv_nsec, csv_sep); - - if (num_print_interval == 0 && !csv_output) { - switch (aggr_mode) { - case AGGR_SOCKET: - fprintf(output, "# time socket cpus counts %*s events\n", unit_width, "unit"); - break; - case AGGR_CORE: - fprintf(output, "# time core cpus counts %*s events\n", unit_width, "unit"); - break; - case AGGR_NONE: - fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit"); - break; - case AGGR_GLOBAL: - default: - fprintf(output, "# time counts %*s events\n", unit_width, "unit"); - } - } - - if (++num_print_interval == 25) - num_print_interval = 0; - switch (aggr_mode) { - case AGGR_CORE: - case AGGR_SOCKET: - print_aggr(prefix); - break; - case AGGR_NONE: - evlist__for_each(evsel_list, counter) - print_counter(counter, prefix); - break; - case AGGR_GLOBAL: - default: - evlist__for_each(evsel_list, counter) - print_counter_aggr(counter, prefix); - } - - fflush(output); + print_counters(&rs, 0, NULL); } static void handle_initial_delay(void) @@ -901,9 +859,35 @@ static void print_counter(struct perf_evsel *counter, char *prefix) } } -static void print_stat(int argc, const char **argv) +static void print_interval(char *prefix, struct timespec *ts) +{ + static int num_print_interval; + + sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); + + if (num_print_interval == 0 && !csv_output) { + switch (aggr_mode) { + case AGGR_SOCKET: + fprintf(output, "# time socket cpus counts %*s events\n", unit_width, "unit"); + break; + case AGGR_CORE: + fprintf(output, "# time core cpus counts %*s events\n", unit_width, "unit"); + break; + case AGGR_NONE: + fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit"); + break; + case AGGR_GLOBAL: + default: + fprintf(output, "# time counts %*s events\n", unit_width, "unit"); + } + } + + if (++num_print_interval == 25) + num_print_interval = 0; +} + +static void print_header(int argc, const char **argv) { - struct perf_evsel *counter; int i; fflush(stdout); @@ -929,36 +913,53 @@ static void print_stat(int argc, const char **argv) fprintf(output, " (%d runs)", run_count); fprintf(output, ":\n\n"); } +} + +static void print_footer(void) +{ + if (!null_run) + fprintf(output, "\n"); + fprintf(output, " %17.9f seconds time elapsed", + avg_stats(&walltime_nsecs_stats)/1e9); + if (run_count > 1) { + fprintf(output, " "); + print_noise_pct(stddev_stats(&walltime_nsecs_stats), + avg_stats(&walltime_nsecs_stats)); + } + fprintf(output, "\n\n"); +} + +static void print_counters(struct timespec *ts, int argc, const char **argv) +{ + struct perf_evsel *counter; + char buf[64], *prefix = NULL; + + if (interval) + print_interval(prefix = buf, ts); + else + print_header(argc, argv); switch (aggr_mode) { case AGGR_CORE: case AGGR_SOCKET: - print_aggr(NULL); + print_aggr(prefix); break; case AGGR_GLOBAL: evlist__for_each(evsel_list, counter) - print_counter_aggr(counter, NULL); + print_counter_aggr(counter, prefix); break; case AGGR_NONE: evlist__for_each(evsel_list, counter) - print_counter(counter, NULL); + print_counter(counter, prefix); break; default: break; } - if (!csv_output) { - if (!null_run) - fprintf(output, "\n"); - fprintf(output, " %17.9f seconds time elapsed", - avg_stats(&walltime_nsecs_stats)/1e9); - if (run_count > 1) { - fprintf(output, " "); - print_noise_pct(stddev_stats(&walltime_nsecs_stats), - avg_stats(&walltime_nsecs_stats)); - } - fprintf(output, "\n\n"); - } + if (!interval && !csv_output) + print_footer(); + + fflush(output); } static volatile int signr = -1; @@ -1407,13 +1408,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) status = run_perf_stat(argc, argv); if (forever && status != -1) { - print_stat(argc, argv); + print_counters(NULL, argc, argv); perf_stat__reset_stats(); } } if (!forever && status != -1 && !interval) - print_stat(argc, argv); + print_counters(NULL, argc, argv); perf_evlist__free_stats(evsel_list); out: -- cgit v1.2.3 From 32b8af82e3708bc19af75c31fa773a98449f0edc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Jun 2015 11:29:27 +0200 Subject: perf stat: Introduce --per-thread option Currently all the -p option PID arguments tasks values get aggregated and printed as single values. Adding --per-tasks option to print values per task. $ perf stat -e cycles,instructions --per-thread -p 30190,30242 ^C Performance counter stats for process id '30190,30242': cat-30190 0 cycles yes-30242 3,842,525,421 cycles cat-30190 0 instructions yes-30242 10,370,817,010 instructions 1.143155657 seconds time elapsed Also works under interval mode: $ perf stat -e cycles,instructions --per-thread -p 30190,30242 -I 1000 # time comm-pid counts unit events 1.000073435 cat-30190 89,058 cycles 1.000073435 yes-30242 3,360,786,902 cycles (100.00%) 1.000073435 cat-30190 14,066 instructions 1.000073435 yes-30242 9,069,937,462 instructions 2.000204830 cat-30190 0 cycles 2.000204830 yes-30242 3,351,667,626 cycles 2.000204830 cat-30190 0 instructions 2.000204830 yes-30242 9,045,796,885 instructions ^C 2.771286639 cat-30190 0 cycles 2.771286639 yes-30242 2,593,884,166 cycles 2.771286639 cat-30190 0 instructions 2.771286639 yes-30242 7,001,171,191 instructions It works only with -t and -p options, otherwise following error is printed: $ perf stat -e cycles --per-thread -I 1000 ls The --per-thread option is only available when monitoring via -p -t options. -p, --pid stat events on existing process id -t, --tid stat events on existing thread id Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1435310967-14570-23-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-stat.txt | 4 ++ tools/perf/builtin-stat.c | 76 +++++++++++++++++++++++++++++++++- tools/perf/util/stat.h | 1 + 3 files changed, 79 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 04e150d83e7d..47469abdcc1c 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt @@ -144,6 +144,10 @@ is a useful mode to detect imbalance between physical cores. To enable this mod use --per-core in addition to -a. (system-wide). The output includes the core number and the number of online logical processors on that physical processor. +--per-thread:: +Aggregate counts per monitored threads, when monitoring threads (-t option) +or processes (-p option). + -D msecs:: --delay msecs:: After starting the program, wait msecs before measuring. This is useful to diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 56dc8881cb05..37e301a32f43 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -231,6 +231,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread, count = &zero; switch (aggr_mode) { + case AGGR_THREAD: case AGGR_CORE: case AGGR_SOCKET: case AGGR_NONE: @@ -602,6 +603,14 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) csv_output ? 0 : -4, perf_evsel__cpus(evsel)->map[id], csv_sep); break; + case AGGR_THREAD: + fprintf(output, "%*s-%*d%s", + csv_output ? 0 : 16, + thread_map__comm(evsel->threads, id), + csv_output ? 0 : -8, + thread_map__pid(evsel->threads, id), + csv_sep); + break; case AGGR_GLOBAL: default: break; @@ -750,6 +759,40 @@ static void print_aggr(char *prefix) } } +static void print_aggr_thread(struct perf_evsel *counter, char *prefix) +{ + int nthreads = thread_map__nr(counter->threads); + int ncpus = cpu_map__nr(counter->cpus); + int cpu, thread; + double uval; + + for (thread = 0; thread < nthreads; thread++) { + u64 ena = 0, run = 0, val = 0; + + for (cpu = 0; cpu < ncpus; cpu++) { + val += perf_counts(counter->counts, cpu, thread)->val; + ena += perf_counts(counter->counts, cpu, thread)->ena; + run += perf_counts(counter->counts, cpu, thread)->run; + } + + if (prefix) + fprintf(output, "%s", prefix); + + uval = val * counter->scale; + + if (nsec_counter(counter)) + nsec_printout(thread, 0, counter, uval); + else + abs_printout(thread, 0, counter, uval); + + if (!csv_output) + print_noise(counter, 1.0); + + print_running(run, ena); + fputc('\n', output); + } +} + /* * Print out the results of a single counter: * aggregated counts in system-wide mode @@ -876,6 +919,9 @@ static void print_interval(char *prefix, struct timespec *ts) case AGGR_NONE: fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit"); break; + case AGGR_THREAD: + fprintf(output, "# time comm-pid counts %*s events\n", unit_width, "unit"); + break; case AGGR_GLOBAL: default: fprintf(output, "# time counts %*s events\n", unit_width, "unit"); @@ -944,6 +990,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) case AGGR_SOCKET: print_aggr(prefix); break; + case AGGR_THREAD: + evlist__for_each(evsel_list, counter) + print_aggr_thread(counter, prefix); + break; case AGGR_GLOBAL: evlist__for_each(evsel_list, counter) print_counter_aggr(counter, prefix); @@ -1031,6 +1081,7 @@ static int perf_stat_init_aggr_mode(void) break; case AGGR_NONE: case AGGR_GLOBAL: + case AGGR_THREAD: default: break; } @@ -1255,6 +1306,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "aggregate counts per processor socket", AGGR_SOCKET), OPT_SET_UINT(0, "per-core", &aggr_mode, "aggregate counts per physical processor core", AGGR_CORE), + OPT_SET_UINT(0, "per-thread", &aggr_mode, + "aggregate counts per thread", AGGR_THREAD), OPT_UINTEGER('D', "delay", &initial_delay, "ms to wait before starting measurement after program start"), OPT_END() @@ -1346,8 +1399,19 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) run_count = 1; } - /* no_aggr, cgroup are for system-wide only */ - if ((aggr_mode != AGGR_GLOBAL || nr_cgroups) && + if ((aggr_mode == AGGR_THREAD) && !target__has_task(&target)) { + fprintf(stderr, "The --per-thread option is only available " + "when monitoring via -p -t options.\n"); + parse_options_usage(NULL, options, "p", 1); + parse_options_usage(NULL, options, "t", 1); + goto out; + } + + /* + * no_aggr, cgroup are for system-wide only + * --per-thread is aggregated per thread, we dont mix it with cpu mode + */ + if (((aggr_mode != AGGR_GLOBAL && aggr_mode != AGGR_THREAD) || nr_cgroups) && !target__has_cpu(&target)) { fprintf(stderr, "both cgroup and no-aggregation " "modes only available in system-wide mode\n"); @@ -1375,6 +1439,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) } goto out; } + + /* + * Initialize thread_map with comm names, + * so we could print it out on output. + */ + if (aggr_mode == AGGR_THREAD) + thread_map__read_comms(evsel_list->threads); + if (interval && interval < 100) { pr_err("print interval must be >= 100ms\n"); parse_options_usage(stat_usage, options, "I", 1); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 9f05c571befe..1cfbe0a980ac 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -30,6 +30,7 @@ enum aggr_mode { AGGR_GLOBAL, AGGR_SOCKET, AGGR_CORE, + AGGR_THREAD, }; struct perf_counts_values { -- cgit v1.2.3 From 36c8bb56a9f718a9a5f35d1834ca9dcec95deb4a Mon Sep 17 00:00:00 2001 From: Li Zhang Date: Fri, 19 Jun 2015 16:57:33 +0800 Subject: perf symbols: Check access permission when reading symbol files There 2 problems when reading symbols files: * It doesn't report any errors even if when users specify symbol files which don't exist with --kallsyms or --vmlinux. The result just shows the address without symbols, which is not what is expected. So it's better to report errors and exit the program. * When using command perf report --kallsyms=/proc/kallsyms with a non-root user, symbols are resolved. Then select one symbol and annotate it, it reports the error as the following: Can't annotate __clear_user: No vmlinux file with build id xxx was found. The problem is caused by reading /proc/kcore without access permission. /proc/kcore requires CAP_SYS_RAWIO capability to access, so it needs to change access permission to allow a specific user to read /proc/kcore or use root to execute the perf command. This patch is to report errors when symbol files specified by users don't exist. And check access permission of /proc/kcore when reading it. Signed-off-by: Li Zhang Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1434704253-2632-1-git-send-email-zhlcindy@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 11 +++++++++++ tools/perf/util/symbol.c | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 32626ea3e227..348bed4a2abf 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -742,6 +742,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) argc = parse_options(argc, argv, options, report_usage, 0); + if (symbol_conf.vmlinux_name && + access(symbol_conf.vmlinux_name, R_OK)) { + pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name); + return -EINVAL; + } + if (symbol_conf.kallsyms_name && + access(symbol_conf.kallsyms_name, R_OK)) { + pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name); + return -EINVAL; + } + if (report.use_stdio) use_browser = 0; else if (report.use_tui) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 504f2d73b7ee..48b588c6951a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1132,8 +1132,11 @@ static int dso__load_kcore(struct dso *dso, struct map *map, INIT_LIST_HEAD(&md.maps); fd = open(kcore_filename, O_RDONLY); - if (fd < 0) + if (fd < 0) { + pr_err("%s requires CAP_SYS_RAWIO capability to access.\n", + kcore_filename); return -EINVAL; + } /* Read new maps into temporary lists */ err = file__read_maps(fd, md.type == MAP__FUNCTION, kcore_mapfn, &md, -- cgit v1.2.3 From ceb92913078e41e2305250754e0ea144fc3e9b28 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 29 Jun 2015 13:27:45 +0200 Subject: perf tools: Add missing break for PERF_RECORD_ITRACE_START Missing switch break since introduction of new event: c4937a91ea56 perf tools: handle PERF_RECORD_LOST_SAMPLES Also removing unneeded break for PERF_RECORD_LOST_SAMPLES. Signed-off-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Kan Liang Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20150629112745.GA21507@krava.brq.redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 4744673aff1b..7ff682770fdb 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1448,10 +1448,9 @@ int machine__process_event(struct machine *machine, union perf_event *event, case PERF_RECORD_AUX: ret = machine__process_aux_event(machine, event); break; case PERF_RECORD_ITRACE_START: - ret = machine__process_itrace_start_event(machine, event); + ret = machine__process_itrace_start_event(machine, event); break; case PERF_RECORD_LOST_SAMPLES: ret = machine__process_lost_samples_event(machine, event, sample); break; - break; default: ret = -1; break; -- cgit v1.2.3 From 9fedfb0c5b05ae6c315de722a0548bb1f1328bf5 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Tue, 30 Jun 2015 17:15:20 +0900 Subject: perf inject: Fill in the missing session freeing after an error occurs When an error occur an error value is just returned without freeing the session. So allocating and freeing session have to be matched as a pair even if an error occurs. Signed-off-by: Taeung Song Acked-by: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1435652124-22414-2-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 52ec66b23607..01b06492bd6a 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -630,12 +630,13 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) if (inject.session == NULL) return -1; - if (symbol__init(&inject.session->header.env) < 0) - return -1; + ret = symbol__init(&inject.session->header.env); + if (ret < 0) + goto out_delete; ret = __cmd_inject(&inject); +out_delete: perf_session__delete(inject.session); - return ret; } -- cgit v1.2.3 From 249ca1a86067e6a4198f7b2b7e19b505e2f41864 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Tue, 30 Jun 2015 17:15:21 +0900 Subject: perf kmem: Fill in the missing session freeing after an error occurs When an error occurs an error value is just returned without freeing the session. So allocating and freeing session have to be matched as a pair even if an error occurs. Signed-off-by: Taeung Song Acked-by: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1435652124-22414-3-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 950f296dfcf7..23b1faaaa4cc 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -1916,7 +1916,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) if (!perf_evlist__find_tracepoint_by_name(session->evlist, "kmem:kmalloc")) { pr_err(errmsg, "slab", "slab"); - return -1; + goto out_delete; } } @@ -1927,7 +1927,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) "kmem:mm_page_alloc"); if (evsel == NULL) { pr_err(errmsg, "page", "page"); - return -1; + goto out_delete; } kmem_page_size = pevent_get_page_size(evsel->tp_format->pevent); -- cgit v1.2.3 From 07a716fff25b826461baa2a07faa2df8c171f220 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Tue, 30 Jun 2015 17:15:24 +0900 Subject: perf report: Fill in the missing session freeing after an error occurs When an error occurs an error value is just returned without freeing the session. So allocating and freeing session have to be matched as a pair even if an error occurs. Signed-off-by: Taeung Song Acked-by: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1435652124-22414-6-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 348bed4a2abf..95a47719aec3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -839,8 +839,10 @@ repeat: if (report.header || report.header_only) { perf_session__fprintf_info(session, stdout, report.show_full_info); - if (report.header_only) - return 0; + if (report.header_only) { + ret = 0; + goto error; + } } else if (use_browser == 0) { fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n", stdout); -- cgit v1.2.3 From 41b983609a1618e9fa70023d83232ed959056c8a Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Wed, 1 Jul 2015 00:18:44 +0900 Subject: perf kvm: Fill in the missing session freeing after an error occurs When an error occurs an error value is just returned without freeing the session. So allocating and freeing session have to be matched as a pair even if an error occurs. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1435677525-28055-1-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 74878cd75078..fc1cffb1b7a2 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1061,8 +1061,10 @@ static int read_events(struct perf_kvm_stat *kvm) symbol__init(&kvm->session->header.env); - if (!perf_session__has_traces(kvm->session, "kvm record")) - return -EINVAL; + if (!perf_session__has_traces(kvm->session, "kvm record")) { + ret = -EINVAL; + goto out_delete; + } /* * Do not use 'isa' recorded in kvm_exit tracepoint since it is not @@ -1070,9 +1072,13 @@ static int read_events(struct perf_kvm_stat *kvm) */ ret = cpu_isa_config(kvm); if (ret < 0) - return ret; + goto out_delete; - return perf_session__process_events(kvm->session); + ret = perf_session__process_events(kvm->session); + +out_delete: + perf_session__delete(kvm->session); + return ret; } static int parse_target_str(struct perf_kvm_stat *kvm) -- cgit v1.2.3 From 1df9fade87ea4831c024de9806f88427f9f33e62 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Wed, 1 Jul 2015 21:08:19 +0900 Subject: perf mem: Fill in the missing session freeing after an error occurs When an error occurs an error value is just returned without freeing the session. So allocating and freeing session have to be matched as a pair even if an error occurs. Signed-off-by: Taeung Song Acked-by: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1435752499-11752-1-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-mem.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index da2ec06f0742..80170aace5d4 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -124,7 +124,6 @@ static int report_raw_events(struct perf_mem *mem) .mode = PERF_DATA_MODE_READ, .force = mem->force, }; - int err = -EINVAL; int ret; struct perf_session *session = perf_session__new(&file, false, &mem->tool); @@ -135,24 +134,21 @@ static int report_raw_events(struct perf_mem *mem) if (mem->cpu_list) { ret = perf_session__cpu_bitmap(session, mem->cpu_list, mem->cpu_bitmap); - if (ret) + if (ret < 0) goto out_delete; } - if (symbol__init(&session->header.env) < 0) - return -1; + ret = symbol__init(&session->header.env); + if (ret < 0) + goto out_delete; printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); - err = perf_session__process_events(session); - if (err) - return err; - - return 0; + ret = perf_session__process_events(session); out_delete: perf_session__delete(session); - return err; + return ret; } static int report_events(int argc, const char **argv, struct perf_mem *mem) -- cgit v1.2.3 From 642273795fa81da11290ffa90bce6ff242f2a7bb Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 1 Jul 2015 14:54:42 +0300 Subject: perf tools: Create config.detected into OUTPUT directory Create config.detected into OUTPUT directory instead of source directory. This fixes parallel builds that share the same source directory. Signed-off-by: Aaro Koskinen Acked-by: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1435751683-18500-1-git-send-email-aaro.koskinen@nokia.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.build | 2 +- tools/perf/Makefile.perf | 2 +- tools/perf/config/Makefile | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build index a51244a8022f..faca2bf6a430 100644 --- a/tools/build/Makefile.build +++ b/tools/build/Makefile.build @@ -25,7 +25,7 @@ build-dir := $(srctree)/tools/build include $(build-dir)/Build.include # do not force detected configuration --include .config-detected +-include $(OUTPUT).config-detected # Init all relevant variables used in build files so # 1) they have correct type diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 1af0cfeb7a57..0e0938afbbb1 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -545,7 +545,7 @@ config-clean: clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete - $(Q)$(RM) .config-detected + $(Q)$(RM) $(OUTPUT).config-detected $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 317001c94660..094ddaee104c 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -11,9 +11,9 @@ ifneq ($(obj-perf),) obj-perf := $(abspath $(obj-perf))/ endif -$(shell echo -n > .config-detected) -detected = $(shell echo "$(1)=y" >> .config-detected) -detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected) +$(shell echo -n > $(OUTPUT).config-detected) +detected = $(shell echo "$(1)=y" >> $(OUTPUT).config-detected) +detected_var = $(shell echo "$(1)=$($(1))" >> $(OUTPUT).config-detected) CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) -- cgit v1.2.3 From 5ef7bbb09f7b91ef06524c72e1ab1fc48e0d6682 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 1 Jul 2015 14:54:43 +0300 Subject: perf tools: Allow to specify custom linker command Allow to specify custom linker command. This fixes MIPS64 builds for 64-bit userspace as it will allow to pass a linker using the correct linker flags for 64-bit ABI (by default GNU binutils ld will assume N32). Signed-off-by: Aaro Koskinen Acked-by: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1435751683-18500-2-git-send-email-aaro.koskinen@nokia.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 0e0938afbbb1..7a4b549214e3 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -110,7 +110,7 @@ $(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD $(Q)touch $(OUTPUT)PERF-VERSION-FILE CC = $(CROSS_COMPILE)gcc -LD = $(CROSS_COMPILE)ld +LD ?= $(CROSS_COMPILE)ld AR = $(CROSS_COMPILE)ar PKG_CONFIG = $(CROSS_COMPILE)pkg-config -- cgit v1.2.3