diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-07-16 07:46:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-07-16 07:46:34 -0400 |
commit | f4aa84fc2a1c3a1ae1b81e434e8cde1c5f98a6b4 (patch) | |
tree | 5cccbfb9ef7d5d848afe67740f5ca6fa1cf5fb04 /tools | |
parent | fbe26abe118ee1262b4ab0d12fefd42647eaea35 (diff) | |
parent | 4414a3c51028aea2ae2fe06c0377490eaa6abbfd (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
o Prep patches to support 'perf kvm stat' on s390 (Alexander Yarygin)
o Add pagefault statistics in 'trace' (Stanislav Fomichev)
o Add header for columns in 'top' and 'report' TUI browsers (Jiri Olsa)
o Add pagefault statistics in 'trace' (Stanislav Fomichev)
Build fixes:
o Fix build on 32-bit systems (Arnaldo Carvalho de Melo)
Cleanups:
o Convert open coded equivalents to asprintf() (Andy Shevchenko)
Plumbing changes:
o Allow reserving a row for header purposes in the hists browser (Arnaldo Carvalho de Melo)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/arch/s390/Makefile | 1 | ||||
-rw-r--r-- | tools/perf/arch/s390/util/header.c | 28 | ||||
-rw-r--r-- | tools/perf/arch/x86/Makefile | 1 | ||||
-rw-r--r-- | tools/perf/builtin-kvm.c | 72 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 23 | ||||
-rw-r--r-- | tools/perf/config/Makefile | 4 | ||||
-rw-r--r-- | tools/perf/perf-sys.h | 1 | ||||
-rw-r--r-- | tools/perf/ui/browser.c | 37 | ||||
-rw-r--r-- | tools/perf/ui/browser.h | 3 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 128 | ||||
-rw-r--r-- | tools/perf/util/config.c | 13 | ||||
-rw-r--r-- | tools/perf/util/data.c | 2 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 1 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 3 | ||||
-rw-r--r-- | tools/perf/util/trace-event-info.c | 12 | ||||
-rw-r--r-- | tools/perf/util/util.c | 9 |
17 files changed, 249 insertions, 91 deletions
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile index 15130b50dfe3..744e629797be 100644 --- a/tools/perf/arch/s390/Makefile +++ b/tools/perf/arch/s390/Makefile | |||
@@ -2,3 +2,4 @@ ifndef NO_DWARF | |||
2 | PERF_HAVE_DWARF_REGS := 1 | 2 | PERF_HAVE_DWARF_REGS := 1 |
3 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o | 3 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o |
4 | endif | 4 | endif |
5 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o | ||
diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c new file mode 100644 index 000000000000..9fa6c3e5782c --- /dev/null +++ b/tools/perf/arch/s390/util/header.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Implementation of get_cpuid(). | ||
3 | * | ||
4 | * Copyright 2014 IBM Corp. | ||
5 | * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License (version 2 only) | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <sys/types.h> | ||
13 | #include <unistd.h> | ||
14 | #include <stdio.h> | ||
15 | #include <string.h> | ||
16 | |||
17 | #include "../../util/header.h" | ||
18 | |||
19 | int get_cpuid(char *buffer, size_t sz) | ||
20 | { | ||
21 | const char *cpuid = "IBM/S390"; | ||
22 | |||
23 | if (strlen(cpuid) + 1 > sz) | ||
24 | return -1; | ||
25 | |||
26 | strcpy(buffer, cpuid); | ||
27 | return 0; | ||
28 | } | ||
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 1641542e3636..d3939014a877 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile | |||
@@ -15,3 +15,4 @@ endif | |||
15 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o | 15 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o |
16 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o | 16 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o |
17 | LIB_H += arch/$(ARCH)/util/tsc.h | 17 | LIB_H += arch/$(ARCH)/util/tsc.h |
18 | HAVE_KVM_STAT_SUPPORT := 1 | ||
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 0f1e5a2f6ad7..41dbeaf8cc11 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <pthread.h> | 29 | #include <pthread.h> |
30 | #include <math.h> | 30 | #include <math.h> |
31 | 31 | ||
32 | #if defined(__i386__) || defined(__x86_64__) | 32 | #ifdef HAVE_KVM_STAT_SUPPORT |
33 | #include <asm/svm.h> | 33 | #include <asm/svm.h> |
34 | #include <asm/vmx.h> | 34 | #include <asm/vmx.h> |
35 | #include <asm/kvm.h> | 35 | #include <asm/kvm.h> |
@@ -99,7 +99,6 @@ struct perf_kvm_stat { | |||
99 | int trace_vcpu; | 99 | int trace_vcpu; |
100 | 100 | ||
101 | struct exit_reasons_table *exit_reasons; | 101 | struct exit_reasons_table *exit_reasons; |
102 | int exit_reasons_size; | ||
103 | const char *exit_reasons_isa; | 102 | const char *exit_reasons_isa; |
104 | 103 | ||
105 | struct kvm_events_ops *events_ops; | 104 | struct kvm_events_ops *events_ops; |
@@ -158,20 +157,19 @@ static bool exit_event_end(struct perf_evsel *evsel, | |||
158 | return kvm_entry_event(evsel); | 157 | return kvm_entry_event(evsel); |
159 | } | 158 | } |
160 | 159 | ||
161 | static struct exit_reasons_table vmx_exit_reasons[] = { | 160 | #define define_exit_reasons_table(name, symbols) \ |
162 | VMX_EXIT_REASONS | 161 | static struct exit_reasons_table name[] = { \ |
163 | }; | 162 | symbols, { -1, NULL } \ |
163 | } | ||
164 | 164 | ||
165 | static struct exit_reasons_table svm_exit_reasons[] = { | 165 | define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); |
166 | SVM_EXIT_REASONS | 166 | define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); |
167 | }; | ||
168 | 167 | ||
169 | static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code) | 168 | static const char *get_exit_reason(struct perf_kvm_stat *kvm, |
169 | struct exit_reasons_table *tbl, | ||
170 | u64 exit_code) | ||
170 | { | 171 | { |
171 | int i = kvm->exit_reasons_size; | 172 | while (tbl->reason != NULL) { |
172 | struct exit_reasons_table *tbl = kvm->exit_reasons; | ||
173 | |||
174 | while (i--) { | ||
175 | if (tbl->exit_code == exit_code) | 173 | if (tbl->exit_code == exit_code) |
176 | return tbl->reason; | 174 | return tbl->reason; |
177 | tbl++; | 175 | tbl++; |
@@ -186,7 +184,8 @@ static void exit_event_decode_key(struct perf_kvm_stat *kvm, | |||
186 | struct event_key *key, | 184 | struct event_key *key, |
187 | char decode[20]) | 185 | char decode[20]) |
188 | { | 186 | { |
189 | const char *exit_reason = get_exit_reason(kvm, key->key); | 187 | const char *exit_reason = get_exit_reason(kvm, kvm->exit_reasons, |
188 | key->key); | ||
190 | 189 | ||
191 | scnprintf(decode, 20, "%s", exit_reason); | 190 | scnprintf(decode, 20, "%s", exit_reason); |
192 | } | 191 | } |
@@ -836,37 +835,45 @@ static int process_sample_event(struct perf_tool *tool, | |||
836 | return 0; | 835 | return 0; |
837 | } | 836 | } |
838 | 837 | ||
838 | static int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) | ||
839 | { | ||
840 | if (strstr(cpuid, "Intel")) { | ||
841 | kvm->exit_reasons = vmx_exit_reasons; | ||
842 | kvm->exit_reasons_isa = "VMX"; | ||
843 | } else if (strstr(cpuid, "AMD")) { | ||
844 | kvm->exit_reasons = svm_exit_reasons; | ||
845 | kvm->exit_reasons_isa = "SVM"; | ||
846 | } else | ||
847 | return -ENOTSUP; | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
839 | static int cpu_isa_config(struct perf_kvm_stat *kvm) | 852 | static int cpu_isa_config(struct perf_kvm_stat *kvm) |
840 | { | 853 | { |
841 | char buf[64], *cpuid; | 854 | char buf[64], *cpuid; |
842 | int err, isa; | 855 | int err; |
843 | 856 | ||
844 | if (kvm->live) { | 857 | if (kvm->live) { |
845 | err = get_cpuid(buf, sizeof(buf)); | 858 | err = get_cpuid(buf, sizeof(buf)); |
846 | if (err != 0) { | 859 | if (err != 0) { |
847 | pr_err("Failed to look up CPU type (Intel or AMD)\n"); | 860 | pr_err("Failed to look up CPU type\n"); |
848 | return err; | 861 | return err; |
849 | } | 862 | } |
850 | cpuid = buf; | 863 | cpuid = buf; |
851 | } else | 864 | } else |
852 | cpuid = kvm->session->header.env.cpuid; | 865 | cpuid = kvm->session->header.env.cpuid; |
853 | 866 | ||
854 | if (strstr(cpuid, "Intel")) | 867 | if (!cpuid) { |
855 | isa = 1; | 868 | pr_err("Failed to look up CPU type\n"); |
856 | else if (strstr(cpuid, "AMD")) | 869 | return -EINVAL; |
857 | isa = 0; | ||
858 | else { | ||
859 | pr_err("CPU %s is not supported.\n", cpuid); | ||
860 | return -ENOTSUP; | ||
861 | } | 870 | } |
862 | 871 | ||
863 | if (isa == 1) { | 872 | err = cpu_isa_init(kvm, cpuid); |
864 | kvm->exit_reasons = vmx_exit_reasons; | 873 | if (err == -ENOTSUP) |
865 | kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons); | 874 | pr_err("CPU %s is not supported.\n", cpuid); |
866 | kvm->exit_reasons_isa = "VMX"; | ||
867 | } | ||
868 | 875 | ||
869 | return 0; | 876 | return err; |
870 | } | 877 | } |
871 | 878 | ||
872 | static bool verify_vcpu(int vcpu) | 879 | static bool verify_vcpu(int vcpu) |
@@ -1585,9 +1592,6 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv) | |||
1585 | .report_event = "vmexit", | 1592 | .report_event = "vmexit", |
1586 | .sort_key = "sample", | 1593 | .sort_key = "sample", |
1587 | 1594 | ||
1588 | .exit_reasons = svm_exit_reasons, | ||
1589 | .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons), | ||
1590 | .exit_reasons_isa = "SVM", | ||
1591 | }; | 1595 | }; |
1592 | 1596 | ||
1593 | if (argc == 1) { | 1597 | if (argc == 1) { |
@@ -1609,7 +1613,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv) | |||
1609 | perf_stat: | 1613 | perf_stat: |
1610 | return cmd_stat(argc, argv, NULL); | 1614 | return cmd_stat(argc, argv, NULL); |
1611 | } | 1615 | } |
1612 | #endif | 1616 | #endif /* HAVE_KVM_STAT_SUPPORT */ |
1613 | 1617 | ||
1614 | static int __cmd_record(const char *file_name, int argc, const char **argv) | 1618 | static int __cmd_record(const char *file_name, int argc, const char **argv) |
1615 | { | 1619 | { |
@@ -1726,7 +1730,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1726 | return cmd_top(argc, argv, NULL); | 1730 | return cmd_top(argc, argv, NULL); |
1727 | else if (!strncmp(argv[0], "buildid-list", 12)) | 1731 | else if (!strncmp(argv[0], "buildid-list", 12)) |
1728 | return __cmd_buildid_list(file_name, argc, argv); | 1732 | return __cmd_buildid_list(file_name, argc, argv); |
1729 | #if defined(__i386__) || defined(__x86_64__) | 1733 | #ifdef HAVE_KVM_STAT_SUPPORT |
1730 | else if (!strncmp(argv[0], "stat", 4)) | 1734 | else if (!strncmp(argv[0], "stat", 4)) |
1731 | return kvm_cmd_stat(file_name, argc, argv); | 1735 | return kvm_cmd_stat(file_name, argc, argv); |
1732 | #endif | 1736 | #endif |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index dc7a694b61fe..c4a5a7d7b2cf 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -1133,6 +1133,7 @@ struct thread_trace { | |||
1133 | u64 exit_time; | 1133 | u64 exit_time; |
1134 | bool entry_pending; | 1134 | bool entry_pending; |
1135 | unsigned long nr_events; | 1135 | unsigned long nr_events; |
1136 | unsigned long pfmaj, pfmin; | ||
1136 | char *entry_str; | 1137 | char *entry_str; |
1137 | double runtime_ms; | 1138 | double runtime_ms; |
1138 | struct { | 1139 | struct { |
@@ -1787,12 +1788,12 @@ static void print_location(FILE *f, struct perf_sample *sample, | |||
1787 | fprintf(f, "%s@", al->map->dso->long_name); | 1788 | fprintf(f, "%s@", al->map->dso->long_name); |
1788 | 1789 | ||
1789 | if ((verbose || print_sym) && al->sym) | 1790 | if ((verbose || print_sym) && al->sym) |
1790 | fprintf(f, "%s+0x%lx", al->sym->name, | 1791 | fprintf(f, "%s+0x%" PRIx64, al->sym->name, |
1791 | al->addr - al->sym->start); | 1792 | al->addr - al->sym->start); |
1792 | else if (al->map) | 1793 | else if (al->map) |
1793 | fprintf(f, "0x%lx", al->addr); | 1794 | fprintf(f, "0x%" PRIx64, al->addr); |
1794 | else | 1795 | else |
1795 | fprintf(f, "0x%lx", sample->addr); | 1796 | fprintf(f, "0x%" PRIx64, sample->addr); |
1796 | } | 1797 | } |
1797 | 1798 | ||
1798 | static int trace__pgfault(struct trace *trace, | 1799 | static int trace__pgfault(struct trace *trace, |
@@ -1804,8 +1805,20 @@ static int trace__pgfault(struct trace *trace, | |||
1804 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 1805 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
1805 | struct addr_location al; | 1806 | struct addr_location al; |
1806 | char map_type = 'd'; | 1807 | char map_type = 'd'; |
1808 | struct thread_trace *ttrace; | ||
1807 | 1809 | ||
1808 | thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); | 1810 | thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); |
1811 | ttrace = thread__trace(thread, trace->output); | ||
1812 | if (ttrace == NULL) | ||
1813 | return -1; | ||
1814 | |||
1815 | if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) | ||
1816 | ttrace->pfmaj++; | ||
1817 | else | ||
1818 | ttrace->pfmin++; | ||
1819 | |||
1820 | if (trace->summary_only) | ||
1821 | return 0; | ||
1809 | 1822 | ||
1810 | thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION, | 1823 | thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION, |
1811 | sample->ip, &al); | 1824 | sample->ip, &al); |
@@ -2346,6 +2359,10 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv) | |||
2346 | printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid); | 2359 | printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid); |
2347 | printed += fprintf(fp, "%lu events, ", ttrace->nr_events); | 2360 | printed += fprintf(fp, "%lu events, ", ttrace->nr_events); |
2348 | printed += fprintf(fp, "%.1f%%", ratio); | 2361 | printed += fprintf(fp, "%.1f%%", ratio); |
2362 | if (ttrace->pfmaj) | ||
2363 | printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj); | ||
2364 | if (ttrace->pfmin) | ||
2365 | printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin); | ||
2349 | printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); | 2366 | printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); |
2350 | printed += thread__dump_stats(ttrace, trace, fp); | 2367 | printed += thread__dump_stats(ttrace, trace, fp); |
2351 | 2368 | ||
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 346bdb617544..b7f42d577c4e 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -594,6 +594,10 @@ ifndef NO_LIBNUMA | |||
594 | endif | 594 | endif |
595 | endif | 595 | endif |
596 | 596 | ||
597 | ifdef HAVE_KVM_STAT_SUPPORT | ||
598 | CFLAGS += -DHAVE_KVM_STAT_SUPPORT | ||
599 | endif | ||
600 | |||
597 | # Among the variables below, these: | 601 | # Among the variables below, these: |
598 | # perfexecdir | 602 | # perfexecdir |
599 | # template_dir | 603 | # template_dir |
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h index 5268a1481d23..937e4324ad94 100644 --- a/tools/perf/perf-sys.h +++ b/tools/perf/perf-sys.h | |||
@@ -54,6 +54,7 @@ | |||
54 | #define mb() asm volatile("bcr 15,0" ::: "memory") | 54 | #define mb() asm volatile("bcr 15,0" ::: "memory") |
55 | #define wmb() asm volatile("bcr 15,0" ::: "memory") | 55 | #define wmb() asm volatile("bcr 15,0" ::: "memory") |
56 | #define rmb() asm volatile("bcr 15,0" ::: "memory") | 56 | #define rmb() asm volatile("bcr 15,0" ::: "memory") |
57 | #define CPUINFO_PROC "vendor_id" | ||
57 | #endif | 58 | #endif |
58 | 59 | ||
59 | #ifdef __sh__ | 60 | #ifdef __sh__ |
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 9d2294efc00c..6680fa5cb9dd 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c | |||
@@ -150,7 +150,7 @@ unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser) | |||
150 | while (nd != NULL) { | 150 | while (nd != NULL) { |
151 | ui_browser__gotorc(browser, row, 0); | 151 | ui_browser__gotorc(browser, row, 0); |
152 | browser->write(browser, nd, row); | 152 | browser->write(browser, nd, row); |
153 | if (++row == browser->height) | 153 | if (++row == browser->rows) |
154 | break; | 154 | break; |
155 | nd = rb_next(nd); | 155 | nd = rb_next(nd); |
156 | } | 156 | } |
@@ -166,7 +166,7 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row) | |||
166 | void ui_browser__refresh_dimensions(struct ui_browser *browser) | 166 | void ui_browser__refresh_dimensions(struct ui_browser *browser) |
167 | { | 167 | { |
168 | browser->width = SLtt_Screen_Cols - 1; | 168 | browser->width = SLtt_Screen_Cols - 1; |
169 | browser->height = SLtt_Screen_Rows - 2; | 169 | browser->height = browser->rows = SLtt_Screen_Rows - 2; |
170 | browser->y = 1; | 170 | browser->y = 1; |
171 | browser->x = 0; | 171 | browser->x = 0; |
172 | } | 172 | } |
@@ -250,7 +250,10 @@ int ui_browser__show(struct ui_browser *browser, const char *title, | |||
250 | int err; | 250 | int err; |
251 | va_list ap; | 251 | va_list ap; |
252 | 252 | ||
253 | ui_browser__refresh_dimensions(browser); | 253 | if (browser->refresh_dimensions == NULL) |
254 | browser->refresh_dimensions = ui_browser__refresh_dimensions; | ||
255 | |||
256 | browser->refresh_dimensions(browser); | ||
254 | 257 | ||
255 | pthread_mutex_lock(&ui__lock); | 258 | pthread_mutex_lock(&ui__lock); |
256 | __ui_browser__show_title(browser, title); | 259 | __ui_browser__show_title(browser, title); |
@@ -367,7 +370,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
367 | 370 | ||
368 | if (key == K_RESIZE) { | 371 | if (key == K_RESIZE) { |
369 | ui__refresh_dimensions(false); | 372 | ui__refresh_dimensions(false); |
370 | ui_browser__refresh_dimensions(browser); | 373 | browser->refresh_dimensions(browser); |
371 | __ui_browser__show_title(browser, browser->title); | 374 | __ui_browser__show_title(browser, browser->title); |
372 | ui_helpline__puts(browser->helpline); | 375 | ui_helpline__puts(browser->helpline); |
373 | continue; | 376 | continue; |
@@ -389,7 +392,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
389 | if (browser->index == browser->nr_entries - 1) | 392 | if (browser->index == browser->nr_entries - 1) |
390 | break; | 393 | break; |
391 | ++browser->index; | 394 | ++browser->index; |
392 | if (browser->index == browser->top_idx + browser->height) { | 395 | if (browser->index == browser->top_idx + browser->rows) { |
393 | ++browser->top_idx; | 396 | ++browser->top_idx; |
394 | browser->seek(browser, +1, SEEK_CUR); | 397 | browser->seek(browser, +1, SEEK_CUR); |
395 | } | 398 | } |
@@ -405,10 +408,10 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
405 | break; | 408 | break; |
406 | case K_PGDN: | 409 | case K_PGDN: |
407 | case ' ': | 410 | case ' ': |
408 | if (browser->top_idx + browser->height > browser->nr_entries - 1) | 411 | if (browser->top_idx + browser->rows > browser->nr_entries - 1) |
409 | break; | 412 | break; |
410 | 413 | ||
411 | offset = browser->height; | 414 | offset = browser->rows; |
412 | if (browser->index + offset > browser->nr_entries - 1) | 415 | if (browser->index + offset > browser->nr_entries - 1) |
413 | offset = browser->nr_entries - 1 - browser->index; | 416 | offset = browser->nr_entries - 1 - browser->index; |
414 | browser->index += offset; | 417 | browser->index += offset; |
@@ -419,10 +422,10 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
419 | if (browser->top_idx == 0) | 422 | if (browser->top_idx == 0) |
420 | break; | 423 | break; |
421 | 424 | ||
422 | if (browser->top_idx < browser->height) | 425 | if (browser->top_idx < browser->rows) |
423 | offset = browser->top_idx; | 426 | offset = browser->top_idx; |
424 | else | 427 | else |
425 | offset = browser->height; | 428 | offset = browser->rows; |
426 | 429 | ||
427 | browser->index -= offset; | 430 | browser->index -= offset; |
428 | browser->top_idx -= offset; | 431 | browser->top_idx -= offset; |
@@ -432,7 +435,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
432 | ui_browser__reset_index(browser); | 435 | ui_browser__reset_index(browser); |
433 | break; | 436 | break; |
434 | case K_END: | 437 | case K_END: |
435 | offset = browser->height - 1; | 438 | offset = browser->rows - 1; |
436 | if (offset >= browser->nr_entries) | 439 | if (offset >= browser->nr_entries) |
437 | offset = browser->nr_entries - 1; | 440 | offset = browser->nr_entries - 1; |
438 | 441 | ||
@@ -462,7 +465,7 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *browser) | |||
462 | if (!browser->filter || !browser->filter(browser, pos)) { | 465 | if (!browser->filter || !browser->filter(browser, pos)) { |
463 | ui_browser__gotorc(browser, row, 0); | 466 | ui_browser__gotorc(browser, row, 0); |
464 | browser->write(browser, pos, row); | 467 | browser->write(browser, pos, row); |
465 | if (++row == browser->height) | 468 | if (++row == browser->rows) |
466 | break; | 469 | break; |
467 | } | 470 | } |
468 | } | 471 | } |
@@ -587,7 +590,7 @@ unsigned int ui_browser__argv_refresh(struct ui_browser *browser) | |||
587 | if (!browser->filter || !browser->filter(browser, *pos)) { | 590 | if (!browser->filter || !browser->filter(browser, *pos)) { |
588 | ui_browser__gotorc(browser, row, 0); | 591 | ui_browser__gotorc(browser, row, 0); |
589 | browser->write(browser, pos, row); | 592 | browser->write(browser, pos, row); |
590 | if (++row == browser->height) | 593 | if (++row == browser->rows) |
591 | break; | 594 | break; |
592 | } | 595 | } |
593 | 596 | ||
@@ -623,7 +626,7 @@ static void __ui_browser__line_arrow_up(struct ui_browser *browser, | |||
623 | 626 | ||
624 | SLsmg_set_char_set(1); | 627 | SLsmg_set_char_set(1); |
625 | 628 | ||
626 | if (start < browser->top_idx + browser->height) { | 629 | if (start < browser->top_idx + browser->rows) { |
627 | row = start - browser->top_idx; | 630 | row = start - browser->top_idx; |
628 | ui_browser__gotorc(browser, row, column); | 631 | ui_browser__gotorc(browser, row, column); |
629 | SLsmg_write_char(SLSMG_LLCORN_CHAR); | 632 | SLsmg_write_char(SLSMG_LLCORN_CHAR); |
@@ -633,7 +636,7 @@ static void __ui_browser__line_arrow_up(struct ui_browser *browser, | |||
633 | if (row-- == 0) | 636 | if (row-- == 0) |
634 | goto out; | 637 | goto out; |
635 | } else | 638 | } else |
636 | row = browser->height - 1; | 639 | row = browser->rows - 1; |
637 | 640 | ||
638 | if (end > browser->top_idx) | 641 | if (end > browser->top_idx) |
639 | end_row = end - browser->top_idx; | 642 | end_row = end - browser->top_idx; |
@@ -675,8 +678,8 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser, | |||
675 | } else | 678 | } else |
676 | row = 0; | 679 | row = 0; |
677 | 680 | ||
678 | if (end >= browser->top_idx + browser->height) | 681 | if (end >= browser->top_idx + browser->rows) |
679 | end_row = browser->height - 1; | 682 | end_row = browser->rows - 1; |
680 | else | 683 | else |
681 | end_row = end - browser->top_idx; | 684 | end_row = end - browser->top_idx; |
682 | 685 | ||
@@ -684,7 +687,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser, | |||
684 | SLsmg_draw_vline(end_row - row + 1); | 687 | SLsmg_draw_vline(end_row - row + 1); |
685 | 688 | ||
686 | ui_browser__gotorc(browser, end_row, column); | 689 | ui_browser__gotorc(browser, end_row, column); |
687 | if (end < browser->top_idx + browser->height) { | 690 | if (end < browser->top_idx + browser->rows) { |
688 | SLsmg_write_char(SLSMG_LLCORN_CHAR); | 691 | SLsmg_write_char(SLSMG_LLCORN_CHAR); |
689 | ui_browser__gotorc(browser, end_row, column + 1); | 692 | ui_browser__gotorc(browser, end_row, column + 1); |
690 | SLsmg_write_char(SLSMG_HLINE_CHAR); | 693 | SLsmg_write_char(SLSMG_HLINE_CHAR); |
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index 03d4d6295f10..92ae72113965 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h | |||
@@ -14,11 +14,12 @@ | |||
14 | struct ui_browser { | 14 | struct ui_browser { |
15 | u64 index, top_idx; | 15 | u64 index, top_idx; |
16 | void *top, *entries; | 16 | void *top, *entries; |
17 | u16 y, x, width, height; | 17 | u16 y, x, width, height, rows; |
18 | int current_color; | 18 | int current_color; |
19 | void *priv; | 19 | void *priv; |
20 | const char *title; | 20 | const char *title; |
21 | char *helpline; | 21 | char *helpline; |
22 | void (*refresh_dimensions)(struct ui_browser *browser); | ||
22 | unsigned int (*refresh)(struct ui_browser *browser); | 23 | unsigned int (*refresh)(struct ui_browser *browser); |
23 | void (*write)(struct ui_browser *browser, void *entry, int row); | 24 | void (*write)(struct ui_browser *browser, void *entry, int row); |
24 | void (*seek)(struct ui_browser *browser, off_t offset, int whence); | 25 | void (*seek)(struct ui_browser *browser, off_t offset, int whence); |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 2185091c5227..a94b11fc5e00 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -26,6 +26,7 @@ struct hist_browser { | |||
26 | struct map_symbol *selection; | 26 | struct map_symbol *selection; |
27 | int print_seq; | 27 | int print_seq; |
28 | bool show_dso; | 28 | bool show_dso; |
29 | bool show_headers; | ||
29 | float min_pcnt; | 30 | float min_pcnt; |
30 | u64 nr_non_filtered_entries; | 31 | u64 nr_non_filtered_entries; |
31 | u64 nr_callchain_rows; | 32 | u64 nr_callchain_rows; |
@@ -56,11 +57,42 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb) | |||
56 | return nr_entries + hb->nr_callchain_rows; | 57 | return nr_entries + hb->nr_callchain_rows; |
57 | } | 58 | } |
58 | 59 | ||
59 | static void hist_browser__refresh_dimensions(struct hist_browser *browser) | 60 | static void hist_browser__update_rows(struct hist_browser *hb) |
60 | { | 61 | { |
62 | struct ui_browser *browser = &hb->b; | ||
63 | u16 header_offset = hb->show_headers ? 1 : 0, index_row; | ||
64 | |||
65 | browser->rows = browser->height - header_offset; | ||
66 | /* | ||
67 | * Verify if we were at the last line and that line isn't | ||
68 | * visibe because we now show the header line(s). | ||
69 | */ | ||
70 | index_row = browser->index - browser->top_idx; | ||
71 | if (index_row >= browser->rows) | ||
72 | browser->index -= index_row - browser->rows + 1; | ||
73 | } | ||
74 | |||
75 | static void hist_browser__refresh_dimensions(struct ui_browser *browser) | ||
76 | { | ||
77 | struct hist_browser *hb = container_of(browser, struct hist_browser, b); | ||
78 | |||
61 | /* 3 == +/- toggle symbol before actual hist_entry rendering */ | 79 | /* 3 == +/- toggle symbol before actual hist_entry rendering */ |
62 | browser->b.width = 3 + (hists__sort_list_width(browser->hists) + | 80 | browser->width = 3 + (hists__sort_list_width(hb->hists) + sizeof("[k]")); |
63 | sizeof("[k]")); | 81 | /* |
82 | * FIXME: Just keeping existing behaviour, but this really should be | ||
83 | * before updating browser->width, as it will invalidate the | ||
84 | * calculation above. Fix this and the fallout in another | ||
85 | * changeset. | ||
86 | */ | ||
87 | ui_browser__refresh_dimensions(browser); | ||
88 | hist_browser__update_rows(hb); | ||
89 | } | ||
90 | |||
91 | static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) | ||
92 | { | ||
93 | u16 header_offset = browser->show_headers ? 1 : 0; | ||
94 | |||
95 | ui_browser__gotorc(&browser->b, row + header_offset, column); | ||
64 | } | 96 | } |
65 | 97 | ||
66 | static void hist_browser__reset(struct hist_browser *browser) | 98 | static void hist_browser__reset(struct hist_browser *browser) |
@@ -73,7 +105,7 @@ static void hist_browser__reset(struct hist_browser *browser) | |||
73 | 105 | ||
74 | hist_browser__update_nr_entries(browser); | 106 | hist_browser__update_nr_entries(browser); |
75 | browser->b.nr_entries = hist_browser__nr_entries(browser); | 107 | browser->b.nr_entries = hist_browser__nr_entries(browser); |
76 | hist_browser__refresh_dimensions(browser); | 108 | hist_browser__refresh_dimensions(&browser->b); |
77 | ui_browser__reset_index(&browser->b); | 109 | ui_browser__reset_index(&browser->b); |
78 | } | 110 | } |
79 | 111 | ||
@@ -355,7 +387,6 @@ static int hist_browser__run(struct hist_browser *browser, | |||
355 | browser->b.entries = &browser->hists->entries; | 387 | browser->b.entries = &browser->hists->entries; |
356 | browser->b.nr_entries = hist_browser__nr_entries(browser); | 388 | browser->b.nr_entries = hist_browser__nr_entries(browser); |
357 | 389 | ||
358 | hist_browser__refresh_dimensions(browser); | ||
359 | hists__browser_title(browser->hists, title, sizeof(title)); | 390 | hists__browser_title(browser->hists, title, sizeof(title)); |
360 | 391 | ||
361 | if (ui_browser__show(&browser->b, title, | 392 | if (ui_browser__show(&browser->b, title, |
@@ -392,10 +423,10 @@ static int hist_browser__run(struct hist_browser *browser, | |||
392 | struct hist_entry *h = rb_entry(browser->b.top, | 423 | struct hist_entry *h = rb_entry(browser->b.top, |
393 | struct hist_entry, rb_node); | 424 | struct hist_entry, rb_node); |
394 | ui_helpline__pop(); | 425 | ui_helpline__pop(); |
395 | ui_helpline__fpush("%d: nr_ent=(%d,%d), height=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", | 426 | ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", |
396 | seq++, browser->b.nr_entries, | 427 | seq++, browser->b.nr_entries, |
397 | browser->hists->nr_entries, | 428 | browser->hists->nr_entries, |
398 | browser->b.height, | 429 | browser->b.rows, |
399 | browser->b.index, | 430 | browser->b.index, |
400 | browser->b.top_idx, | 431 | browser->b.top_idx, |
401 | h->row_offset, h->nr_rows); | 432 | h->row_offset, h->nr_rows); |
@@ -409,6 +440,10 @@ static int hist_browser__run(struct hist_browser *browser, | |||
409 | /* Expand the whole world. */ | 440 | /* Expand the whole world. */ |
410 | hist_browser__set_folding(browser, true); | 441 | hist_browser__set_folding(browser, true); |
411 | break; | 442 | break; |
443 | case 'H': | ||
444 | browser->show_headers = !browser->show_headers; | ||
445 | hist_browser__update_rows(browser); | ||
446 | break; | ||
412 | case K_ENTER: | 447 | case K_ENTER: |
413 | if (hist_browser__toggle_fold(browser)) | 448 | if (hist_browser__toggle_fold(browser)) |
414 | break; | 449 | break; |
@@ -508,13 +543,13 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse | |||
508 | } | 543 | } |
509 | 544 | ||
510 | ui_browser__set_color(&browser->b, color); | 545 | ui_browser__set_color(&browser->b, color); |
511 | ui_browser__gotorc(&browser->b, row, 0); | 546 | hist_browser__gotorc(browser, row, 0); |
512 | slsmg_write_nstring(" ", offset + extra_offset); | 547 | slsmg_write_nstring(" ", offset + extra_offset); |
513 | slsmg_printf("%c ", folded_sign); | 548 | slsmg_printf("%c ", folded_sign); |
514 | slsmg_write_nstring(str, width); | 549 | slsmg_write_nstring(str, width); |
515 | free(alloc_str); | 550 | free(alloc_str); |
516 | 551 | ||
517 | if (++row == browser->b.height) | 552 | if (++row == browser->b.rows) |
518 | goto out; | 553 | goto out; |
519 | do_next: | 554 | do_next: |
520 | if (folded_sign == '+') | 555 | if (folded_sign == '+') |
@@ -527,7 +562,7 @@ do_next: | |||
527 | new_level, row, row_offset, | 562 | new_level, row, row_offset, |
528 | is_current_entry); | 563 | is_current_entry); |
529 | } | 564 | } |
530 | if (row == browser->b.height) | 565 | if (row == browser->b.rows) |
531 | goto out; | 566 | goto out; |
532 | node = next; | 567 | node = next; |
533 | } | 568 | } |
@@ -567,13 +602,13 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser, | |||
567 | 602 | ||
568 | s = callchain_list__sym_name(chain, bf, sizeof(bf), | 603 | s = callchain_list__sym_name(chain, bf, sizeof(bf), |
569 | browser->show_dso); | 604 | browser->show_dso); |
570 | ui_browser__gotorc(&browser->b, row, 0); | 605 | hist_browser__gotorc(browser, row, 0); |
571 | ui_browser__set_color(&browser->b, color); | 606 | ui_browser__set_color(&browser->b, color); |
572 | slsmg_write_nstring(" ", offset); | 607 | slsmg_write_nstring(" ", offset); |
573 | slsmg_printf("%c ", folded_sign); | 608 | slsmg_printf("%c ", folded_sign); |
574 | slsmg_write_nstring(s, width - 2); | 609 | slsmg_write_nstring(s, width - 2); |
575 | 610 | ||
576 | if (++row == browser->b.height) | 611 | if (++row == browser->b.rows) |
577 | goto out; | 612 | goto out; |
578 | } | 613 | } |
579 | 614 | ||
@@ -602,7 +637,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, | |||
602 | row += hist_browser__show_callchain_node(browser, node, level, | 637 | row += hist_browser__show_callchain_node(browser, node, level, |
603 | row, row_offset, | 638 | row, row_offset, |
604 | is_current_entry); | 639 | is_current_entry); |
605 | if (row == browser->b.height) | 640 | if (row == browser->b.rows) |
606 | break; | 641 | break; |
607 | } | 642 | } |
608 | 643 | ||
@@ -732,7 +767,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
732 | .ptr = &arg, | 767 | .ptr = &arg, |
733 | }; | 768 | }; |
734 | 769 | ||
735 | ui_browser__gotorc(&browser->b, row, 0); | 770 | hist_browser__gotorc(browser, row, 0); |
736 | 771 | ||
737 | perf_hpp__for_each_format(fmt) { | 772 | perf_hpp__for_each_format(fmt) { |
738 | if (perf_hpp__should_skip(fmt)) | 773 | if (perf_hpp__should_skip(fmt)) |
@@ -776,7 +811,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
776 | } else | 811 | } else |
777 | --row_offset; | 812 | --row_offset; |
778 | 813 | ||
779 | if (folded_sign == '-' && row != browser->b.height) { | 814 | if (folded_sign == '-' && row != browser->b.rows) { |
780 | printed += hist_browser__show_callchain(browser, &entry->sorted_chain, | 815 | printed += hist_browser__show_callchain(browser, &entry->sorted_chain, |
781 | 1, row, &row_offset, | 816 | 1, row, &row_offset, |
782 | ¤t_entry); | 817 | ¤t_entry); |
@@ -787,6 +822,56 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
787 | return printed; | 822 | return printed; |
788 | } | 823 | } |
789 | 824 | ||
825 | static int advance_hpp_check(struct perf_hpp *hpp, int inc) | ||
826 | { | ||
827 | advance_hpp(hpp, inc); | ||
828 | return hpp->size <= 0; | ||
829 | } | ||
830 | |||
831 | static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists) | ||
832 | { | ||
833 | struct perf_hpp dummy_hpp = { | ||
834 | .buf = buf, | ||
835 | .size = size, | ||
836 | }; | ||
837 | struct perf_hpp_fmt *fmt; | ||
838 | size_t ret = 0; | ||
839 | |||
840 | if (symbol_conf.use_callchain) { | ||
841 | ret = scnprintf(buf, size, " "); | ||
842 | if (advance_hpp_check(&dummy_hpp, ret)) | ||
843 | return ret; | ||
844 | } | ||
845 | |||
846 | perf_hpp__for_each_format(fmt) { | ||
847 | if (perf_hpp__should_skip(fmt)) | ||
848 | continue; | ||
849 | |||
850 | /* We need to add the length of the columns header. */ | ||
851 | perf_hpp__reset_width(fmt, hists); | ||
852 | |||
853 | ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); | ||
854 | if (advance_hpp_check(&dummy_hpp, ret)) | ||
855 | break; | ||
856 | |||
857 | ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " "); | ||
858 | if (advance_hpp_check(&dummy_hpp, ret)) | ||
859 | break; | ||
860 | } | ||
861 | |||
862 | return ret; | ||
863 | } | ||
864 | |||
865 | static void hist_browser__show_headers(struct hist_browser *browser) | ||
866 | { | ||
867 | char headers[1024]; | ||
868 | |||
869 | hists__scnprintf_headers(headers, sizeof(headers), browser->hists); | ||
870 | ui_browser__gotorc(&browser->b, 0, 0); | ||
871 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); | ||
872 | slsmg_write_nstring(headers, browser->b.width + 1); | ||
873 | } | ||
874 | |||
790 | static void ui_browser__hists_init_top(struct ui_browser *browser) | 875 | static void ui_browser__hists_init_top(struct ui_browser *browser) |
791 | { | 876 | { |
792 | if (browser->top == NULL) { | 877 | if (browser->top == NULL) { |
@@ -800,9 +885,15 @@ static void ui_browser__hists_init_top(struct ui_browser *browser) | |||
800 | static unsigned int hist_browser__refresh(struct ui_browser *browser) | 885 | static unsigned int hist_browser__refresh(struct ui_browser *browser) |
801 | { | 886 | { |
802 | unsigned row = 0; | 887 | unsigned row = 0; |
888 | u16 header_offset = 0; | ||
803 | struct rb_node *nd; | 889 | struct rb_node *nd; |
804 | struct hist_browser *hb = container_of(browser, struct hist_browser, b); | 890 | struct hist_browser *hb = container_of(browser, struct hist_browser, b); |
805 | 891 | ||
892 | if (hb->show_headers) { | ||
893 | hist_browser__show_headers(hb); | ||
894 | header_offset = 1; | ||
895 | } | ||
896 | |||
806 | ui_browser__hists_init_top(browser); | 897 | ui_browser__hists_init_top(browser); |
807 | 898 | ||
808 | for (nd = browser->top; nd; nd = rb_next(nd)) { | 899 | for (nd = browser->top; nd; nd = rb_next(nd)) { |
@@ -817,11 +908,11 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) | |||
817 | continue; | 908 | continue; |
818 | 909 | ||
819 | row += hist_browser__show_entry(hb, h, row); | 910 | row += hist_browser__show_entry(hb, h, row); |
820 | if (row == browser->height) | 911 | if (row == browser->rows) |
821 | break; | 912 | break; |
822 | } | 913 | } |
823 | 914 | ||
824 | return row; | 915 | return row + header_offset; |
825 | } | 916 | } |
826 | 917 | ||
827 | static struct rb_node *hists__filter_entries(struct rb_node *nd, | 918 | static struct rb_node *hists__filter_entries(struct rb_node *nd, |
@@ -1190,8 +1281,10 @@ static struct hist_browser *hist_browser__new(struct hists *hists) | |||
1190 | if (browser) { | 1281 | if (browser) { |
1191 | browser->hists = hists; | 1282 | browser->hists = hists; |
1192 | browser->b.refresh = hist_browser__refresh; | 1283 | browser->b.refresh = hist_browser__refresh; |
1284 | browser->b.refresh_dimensions = hist_browser__refresh_dimensions; | ||
1193 | browser->b.seek = ui_browser__hists_seek; | 1285 | browser->b.seek = ui_browser__hists_seek; |
1194 | browser->b.use_navkeypressed = true; | 1286 | browser->b.use_navkeypressed = true; |
1287 | browser->show_headers = symbol_conf.show_hist_headers; | ||
1195 | } | 1288 | } |
1196 | 1289 | ||
1197 | return browser; | 1290 | return browser; |
@@ -1421,6 +1514,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1421 | "d Zoom into current DSO\n" \ | 1514 | "d Zoom into current DSO\n" \ |
1422 | "E Expand all callchains\n" \ | 1515 | "E Expand all callchains\n" \ |
1423 | "F Toggle percentage of filtered entries\n" \ | 1516 | "F Toggle percentage of filtered entries\n" \ |
1517 | "H Display column headers\n" \ | ||
1424 | 1518 | ||
1425 | /* help messages are sorted by lexical order of the hotkey */ | 1519 | /* help messages are sorted by lexical order of the hotkey */ |
1426 | const char report_help[] = HIST_BROWSER_HELP_COMMON | 1520 | const char report_help[] = HIST_BROWSER_HELP_COMMON |
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 24519e14ac56..1e5e2e5af6b1 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -350,6 +350,16 @@ static int perf_default_core_config(const char *var __maybe_unused, | |||
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | 352 | ||
353 | static int perf_ui_config(const char *var, const char *value) | ||
354 | { | ||
355 | /* Add other config variables here. */ | ||
356 | if (!strcmp(var, "ui.show-headers")) { | ||
357 | symbol_conf.show_hist_headers = perf_config_bool(var, value); | ||
358 | return 0; | ||
359 | } | ||
360 | return 0; | ||
361 | } | ||
362 | |||
353 | int perf_default_config(const char *var, const char *value, | 363 | int perf_default_config(const char *var, const char *value, |
354 | void *dummy __maybe_unused) | 364 | void *dummy __maybe_unused) |
355 | { | 365 | { |
@@ -359,6 +369,9 @@ int perf_default_config(const char *var, const char *value, | |||
359 | if (!prefixcmp(var, "hist.")) | 369 | if (!prefixcmp(var, "hist.")) |
360 | return perf_hist_config(var, value); | 370 | return perf_hist_config(var, value); |
361 | 371 | ||
372 | if (!prefixcmp(var, "ui.")) | ||
373 | return perf_ui_config(var, value); | ||
374 | |||
362 | /* Add other config variables here. */ | 375 | /* Add other config variables here. */ |
363 | return 0; | 376 | return 0; |
364 | } | 377 | } |
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index 55de44ecebef..ee370a7f2444 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c | |||
@@ -65,7 +65,7 @@ static int open_file_read(struct perf_data_file *file) | |||
65 | goto out_close; | 65 | goto out_close; |
66 | 66 | ||
67 | if (!file->force && st.st_uid && (st.st_uid != geteuid())) { | 67 | if (!file->force && st.st_uid && (st.st_uid != geteuid())) { |
68 | pr_err("file %s not owned by current user or root\n", | 68 | pr_err("File %s not owned by current user or root (use -f to override)\n", |
69 | file->path); | 69 | file->path); |
70 | goto out_close; | 70 | goto out_close; |
71 | } | 71 | } |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 1ec57dd82284..14e5a039bc45 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -1215,7 +1215,7 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | |||
1215 | hse = container_of(fmt, struct hpp_sort_entry, hpp); | 1215 | hse = container_of(fmt, struct hpp_sort_entry, hpp); |
1216 | len = hists__col_len(&evsel->hists, hse->se->se_width_idx); | 1216 | len = hists__col_len(&evsel->hists, hse->se->se_width_idx); |
1217 | 1217 | ||
1218 | return scnprintf(hpp->buf, hpp->size, "%*s", len, hse->se->se_header); | 1218 | return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header); |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | static int __sort__hpp_width(struct perf_hpp_fmt *fmt, | 1221 | static int __sort__hpp_width(struct perf_hpp_fmt *fmt, |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 7b9096f29cdb..2e6a2e219eb9 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -34,6 +34,7 @@ struct symbol_conf symbol_conf = { | |||
34 | .annotate_src = true, | 34 | .annotate_src = true, |
35 | .demangle = true, | 35 | .demangle = true, |
36 | .cumulate_callchain = true, | 36 | .cumulate_callchain = true, |
37 | .show_hist_headers = true, | ||
37 | .symfs = "", | 38 | .symfs = "", |
38 | }; | 39 | }; |
39 | 40 | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 615c752dd767..a81877b1dee0 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -118,7 +118,8 @@ struct symbol_conf { | |||
118 | annotate_src, | 118 | annotate_src, |
119 | event_group, | 119 | event_group, |
120 | demangle, | 120 | demangle, |
121 | filter_relative; | 121 | filter_relative, |
122 | show_hist_headers; | ||
122 | const char *vmlinux_name, | 123 | const char *vmlinux_name, |
123 | *kallsyms_name, | 124 | *kallsyms_name, |
124 | *source_prefix, | 125 | *source_prefix, |
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 7e6fcfe8b438..c3bba883f5c3 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c | |||
@@ -191,12 +191,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps) | |||
191 | strcmp(dent->d_name, "..") == 0 || | 191 | strcmp(dent->d_name, "..") == 0 || |
192 | !name_in_tp_list(dent->d_name, tps)) | 192 | !name_in_tp_list(dent->d_name, tps)) |
193 | continue; | 193 | continue; |
194 | format = malloc(strlen(sys) + strlen(dent->d_name) + 10); | 194 | if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { |
195 | if (!format) { | ||
196 | err = -ENOMEM; | 195 | err = -ENOMEM; |
197 | goto out; | 196 | goto out; |
198 | } | 197 | } |
199 | sprintf(format, "%s/%s/format", sys, dent->d_name); | ||
200 | ret = stat(format, &st); | 198 | ret = stat(format, &st); |
201 | free(format); | 199 | free(format); |
202 | if (ret < 0) | 200 | if (ret < 0) |
@@ -217,12 +215,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps) | |||
217 | strcmp(dent->d_name, "..") == 0 || | 215 | strcmp(dent->d_name, "..") == 0 || |
218 | !name_in_tp_list(dent->d_name, tps)) | 216 | !name_in_tp_list(dent->d_name, tps)) |
219 | continue; | 217 | continue; |
220 | format = malloc(strlen(sys) + strlen(dent->d_name) + 10); | 218 | if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) { |
221 | if (!format) { | ||
222 | err = -ENOMEM; | 219 | err = -ENOMEM; |
223 | goto out; | 220 | goto out; |
224 | } | 221 | } |
225 | sprintf(format, "%s/%s/format", sys, dent->d_name); | ||
226 | ret = stat(format, &st); | 222 | ret = stat(format, &st); |
227 | 223 | ||
228 | if (ret >= 0) { | 224 | if (ret >= 0) { |
@@ -317,12 +313,10 @@ static int record_event_files(struct tracepoint_path *tps) | |||
317 | strcmp(dent->d_name, "ftrace") == 0 || | 313 | strcmp(dent->d_name, "ftrace") == 0 || |
318 | !system_in_tp_list(dent->d_name, tps)) | 314 | !system_in_tp_list(dent->d_name, tps)) |
319 | continue; | 315 | continue; |
320 | sys = malloc(strlen(path) + strlen(dent->d_name) + 2); | 316 | if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) { |
321 | if (!sys) { | ||
322 | err = -ENOMEM; | 317 | err = -ENOMEM; |
323 | goto out; | 318 | goto out; |
324 | } | 319 | } |
325 | sprintf(sys, "%s/%s", path, dent->d_name); | ||
326 | ret = stat(sys, &st); | 320 | ret = stat(sys, &st); |
327 | if (ret >= 0) { | 321 | if (ret >= 0) { |
328 | ssize_t size = strlen(dent->d_name) + 1; | 322 | ssize_t size = strlen(dent->d_name) + 1; |
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 95aefa78bb07..e4132aeeb780 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -333,12 +333,9 @@ const char *find_tracing_dir(void) | |||
333 | if (!debugfs) | 333 | if (!debugfs) |
334 | return NULL; | 334 | return NULL; |
335 | 335 | ||
336 | tracing = malloc(strlen(debugfs) + 9); | 336 | if (asprintf(&tracing, "%s/tracing", debugfs) < 0) |
337 | if (!tracing) | ||
338 | return NULL; | 337 | return NULL; |
339 | 338 | ||
340 | sprintf(tracing, "%s/tracing", debugfs); | ||
341 | |||
342 | tracing_found = 1; | 339 | tracing_found = 1; |
343 | return tracing; | 340 | return tracing; |
344 | } | 341 | } |
@@ -352,11 +349,9 @@ char *get_tracing_file(const char *name) | |||
352 | if (!tracing) | 349 | if (!tracing) |
353 | return NULL; | 350 | return NULL; |
354 | 351 | ||
355 | file = malloc(strlen(tracing) + strlen(name) + 2); | 352 | if (asprintf(&file, "%s/%s", tracing, name) < 0) |
356 | if (!file) | ||
357 | return NULL; | 353 | return NULL; |
358 | 354 | ||
359 | sprintf(file, "%s/%s", tracing, name); | ||
360 | return file; | 355 | return file; |
361 | } | 356 | } |
362 | 357 | ||