perf/core improvements and fixes
User visible: 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: Fix build on 32-bit systems (Arnaldo Carvalho de Melo) Cleanups: o Convert open coded equivalents to asprintf() (Andy Shevchenko) Plumbing: 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> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTvEAcAAoJENZQFvNTUqpA/MgP/iv8Qfe464fpsqnUZCAHMEw5 CINVqTagB0xA5ga+UO9sMTuxY6ZEvd7C9eIsTBcuhxx84J7AHMuwaxFB6KnmaDGf 5KyP81nP/lafKO06eiD/ERxi/Y1X6UjB9x5dYtItMVL+uyFRmBzyfFFfjAzju/rR RiC3HdnTm0xiFXKAEQShhVcLb1xpnm49amiFLgz+zK/WTWK1Mo2/jMuEIGFy9F8R zFuVbRuHFYmoFkNAlv5byHbGm+d2mwMZa7jc5hVbkFGb/SxZTMYANUTmYMFEZImU lOo4g6UwdZ/aEO/p/iqWV/mhhV8qTKzgoMhGR239xG/yA6MDqwDrkDKZZz4xHQJZ I5i6/xj3iesViSO8p7nYEZPq3VARPo+93x38snq+fMPTj/beSTlLcWcr7iP+L6EZ 5iJ9lWTLqohpi3Lvla2soqlpS8vwKNspsL6VRzBiGSmp4vLs3KGDCACjIaLA1D0u 4uCrDq68lwR8BT+sE+4AJ2q/7KRU1VM7RC7k9B27OiF8Cb2RXQQ5LpW8i2Er6spV DYfbBCi+Tkgn/Y0Vr9OqnvxvFRtYA1iD6pfWzsDjLovzVcdXwVEs5FtGzfl2A0vB ZriNg2ByudA/K6Yj0jbox7O+aJaYzvOBn9gHTZSuWfnOwOEX0SCDIV8lZaqVWem3 rzy3m/ArvTYyzzW4+W85 =tb1y -----END PGP SIGNATURE----- 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>
This commit is contained in:
Коммит
f4aa84fc2a
|
@ -2,3 +2,4 @@ ifndef NO_DWARF
|
||||||
PERF_HAVE_DWARF_REGS := 1
|
PERF_HAVE_DWARF_REGS := 1
|
||||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
|
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
|
||||||
endif
|
endif
|
||||||
|
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Implementation of get_cpuid().
|
||||||
|
*
|
||||||
|
* Copyright 2014 IBM Corp.
|
||||||
|
* Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License (version 2 only)
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../../util/header.h"
|
||||||
|
|
||||||
|
int get_cpuid(char *buffer, size_t sz)
|
||||||
|
{
|
||||||
|
const char *cpuid = "IBM/S390";
|
||||||
|
|
||||||
|
if (strlen(cpuid) + 1 > sz)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
strcpy(buffer, cpuid);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -15,3 +15,4 @@ endif
|
||||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
|
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
|
||||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
|
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
|
||||||
LIB_H += arch/$(ARCH)/util/tsc.h
|
LIB_H += arch/$(ARCH)/util/tsc.h
|
||||||
|
HAVE_KVM_STAT_SUPPORT := 1
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#ifdef HAVE_KVM_STAT_SUPPORT
|
||||||
#include <asm/svm.h>
|
#include <asm/svm.h>
|
||||||
#include <asm/vmx.h>
|
#include <asm/vmx.h>
|
||||||
#include <asm/kvm.h>
|
#include <asm/kvm.h>
|
||||||
|
@ -99,7 +99,6 @@ struct perf_kvm_stat {
|
||||||
int trace_vcpu;
|
int trace_vcpu;
|
||||||
|
|
||||||
struct exit_reasons_table *exit_reasons;
|
struct exit_reasons_table *exit_reasons;
|
||||||
int exit_reasons_size;
|
|
||||||
const char *exit_reasons_isa;
|
const char *exit_reasons_isa;
|
||||||
|
|
||||||
struct kvm_events_ops *events_ops;
|
struct kvm_events_ops *events_ops;
|
||||||
|
@ -158,20 +157,19 @@ static bool exit_event_end(struct perf_evsel *evsel,
|
||||||
return kvm_entry_event(evsel);
|
return kvm_entry_event(evsel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct exit_reasons_table vmx_exit_reasons[] = {
|
#define define_exit_reasons_table(name, symbols) \
|
||||||
VMX_EXIT_REASONS
|
static struct exit_reasons_table name[] = { \
|
||||||
};
|
symbols, { -1, NULL } \
|
||||||
|
}
|
||||||
|
|
||||||
static struct exit_reasons_table svm_exit_reasons[] = {
|
define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
|
||||||
SVM_EXIT_REASONS
|
define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
|
||||||
};
|
|
||||||
|
|
||||||
static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code)
|
static const char *get_exit_reason(struct perf_kvm_stat *kvm,
|
||||||
|
struct exit_reasons_table *tbl,
|
||||||
|
u64 exit_code)
|
||||||
{
|
{
|
||||||
int i = kvm->exit_reasons_size;
|
while (tbl->reason != NULL) {
|
||||||
struct exit_reasons_table *tbl = kvm->exit_reasons;
|
|
||||||
|
|
||||||
while (i--) {
|
|
||||||
if (tbl->exit_code == exit_code)
|
if (tbl->exit_code == exit_code)
|
||||||
return tbl->reason;
|
return tbl->reason;
|
||||||
tbl++;
|
tbl++;
|
||||||
|
@ -186,7 +184,8 @@ static void exit_event_decode_key(struct perf_kvm_stat *kvm,
|
||||||
struct event_key *key,
|
struct event_key *key,
|
||||||
char decode[20])
|
char decode[20])
|
||||||
{
|
{
|
||||||
const char *exit_reason = get_exit_reason(kvm, key->key);
|
const char *exit_reason = get_exit_reason(kvm, kvm->exit_reasons,
|
||||||
|
key->key);
|
||||||
|
|
||||||
scnprintf(decode, 20, "%s", exit_reason);
|
scnprintf(decode, 20, "%s", exit_reason);
|
||||||
}
|
}
|
||||||
|
@ -836,37 +835,45 @@ static int process_sample_event(struct perf_tool *tool,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid)
|
||||||
|
{
|
||||||
|
if (strstr(cpuid, "Intel")) {
|
||||||
|
kvm->exit_reasons = vmx_exit_reasons;
|
||||||
|
kvm->exit_reasons_isa = "VMX";
|
||||||
|
} else if (strstr(cpuid, "AMD")) {
|
||||||
|
kvm->exit_reasons = svm_exit_reasons;
|
||||||
|
kvm->exit_reasons_isa = "SVM";
|
||||||
|
} else
|
||||||
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int cpu_isa_config(struct perf_kvm_stat *kvm)
|
static int cpu_isa_config(struct perf_kvm_stat *kvm)
|
||||||
{
|
{
|
||||||
char buf[64], *cpuid;
|
char buf[64], *cpuid;
|
||||||
int err, isa;
|
int err;
|
||||||
|
|
||||||
if (kvm->live) {
|
if (kvm->live) {
|
||||||
err = get_cpuid(buf, sizeof(buf));
|
err = get_cpuid(buf, sizeof(buf));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
pr_err("Failed to look up CPU type (Intel or AMD)\n");
|
pr_err("Failed to look up CPU type\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
cpuid = buf;
|
cpuid = buf;
|
||||||
} else
|
} else
|
||||||
cpuid = kvm->session->header.env.cpuid;
|
cpuid = kvm->session->header.env.cpuid;
|
||||||
|
|
||||||
if (strstr(cpuid, "Intel"))
|
if (!cpuid) {
|
||||||
isa = 1;
|
pr_err("Failed to look up CPU type\n");
|
||||||
else if (strstr(cpuid, "AMD"))
|
return -EINVAL;
|
||||||
isa = 0;
|
}
|
||||||
else {
|
|
||||||
|
err = cpu_isa_init(kvm, cpuid);
|
||||||
|
if (err == -ENOTSUP)
|
||||||
pr_err("CPU %s is not supported.\n", cpuid);
|
pr_err("CPU %s is not supported.\n", cpuid);
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isa == 1) {
|
return err;
|
||||||
kvm->exit_reasons = vmx_exit_reasons;
|
|
||||||
kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
|
|
||||||
kvm->exit_reasons_isa = "VMX";
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool verify_vcpu(int vcpu)
|
static bool verify_vcpu(int vcpu)
|
||||||
|
@ -1585,9 +1592,6 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
|
||||||
.report_event = "vmexit",
|
.report_event = "vmexit",
|
||||||
.sort_key = "sample",
|
.sort_key = "sample",
|
||||||
|
|
||||||
.exit_reasons = svm_exit_reasons,
|
|
||||||
.exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
|
|
||||||
.exit_reasons_isa = "SVM",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
|
@ -1609,7 +1613,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
|
||||||
perf_stat:
|
perf_stat:
|
||||||
return cmd_stat(argc, argv, NULL);
|
return cmd_stat(argc, argv, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* HAVE_KVM_STAT_SUPPORT */
|
||||||
|
|
||||||
static int __cmd_record(const char *file_name, int argc, const char **argv)
|
static int __cmd_record(const char *file_name, int argc, const char **argv)
|
||||||
{
|
{
|
||||||
|
@ -1726,7 +1730,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
return cmd_top(argc, argv, NULL);
|
return cmd_top(argc, argv, NULL);
|
||||||
else if (!strncmp(argv[0], "buildid-list", 12))
|
else if (!strncmp(argv[0], "buildid-list", 12))
|
||||||
return __cmd_buildid_list(file_name, argc, argv);
|
return __cmd_buildid_list(file_name, argc, argv);
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#ifdef HAVE_KVM_STAT_SUPPORT
|
||||||
else if (!strncmp(argv[0], "stat", 4))
|
else if (!strncmp(argv[0], "stat", 4))
|
||||||
return kvm_cmd_stat(file_name, argc, argv);
|
return kvm_cmd_stat(file_name, argc, argv);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1133,6 +1133,7 @@ struct thread_trace {
|
||||||
u64 exit_time;
|
u64 exit_time;
|
||||||
bool entry_pending;
|
bool entry_pending;
|
||||||
unsigned long nr_events;
|
unsigned long nr_events;
|
||||||
|
unsigned long pfmaj, pfmin;
|
||||||
char *entry_str;
|
char *entry_str;
|
||||||
double runtime_ms;
|
double runtime_ms;
|
||||||
struct {
|
struct {
|
||||||
|
@ -1787,12 +1788,12 @@ static void print_location(FILE *f, struct perf_sample *sample,
|
||||||
fprintf(f, "%s@", al->map->dso->long_name);
|
fprintf(f, "%s@", al->map->dso->long_name);
|
||||||
|
|
||||||
if ((verbose || print_sym) && al->sym)
|
if ((verbose || print_sym) && al->sym)
|
||||||
fprintf(f, "%s+0x%lx", al->sym->name,
|
fprintf(f, "%s+0x%" PRIx64, al->sym->name,
|
||||||
al->addr - al->sym->start);
|
al->addr - al->sym->start);
|
||||||
else if (al->map)
|
else if (al->map)
|
||||||
fprintf(f, "0x%lx", al->addr);
|
fprintf(f, "0x%" PRIx64, al->addr);
|
||||||
else
|
else
|
||||||
fprintf(f, "0x%lx", sample->addr);
|
fprintf(f, "0x%" PRIx64, sample->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int trace__pgfault(struct trace *trace,
|
static int trace__pgfault(struct trace *trace,
|
||||||
|
@ -1804,8 +1805,20 @@ static int trace__pgfault(struct trace *trace,
|
||||||
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
||||||
struct addr_location al;
|
struct addr_location al;
|
||||||
char map_type = 'd';
|
char map_type = 'd';
|
||||||
|
struct thread_trace *ttrace;
|
||||||
|
|
||||||
thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
|
thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
|
||||||
|
ttrace = thread__trace(thread, trace->output);
|
||||||
|
if (ttrace == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)
|
||||||
|
ttrace->pfmaj++;
|
||||||
|
else
|
||||||
|
ttrace->pfmin++;
|
||||||
|
|
||||||
|
if (trace->summary_only)
|
||||||
|
return 0;
|
||||||
|
|
||||||
thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION,
|
thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION,
|
||||||
sample->ip, &al);
|
sample->ip, &al);
|
||||||
|
@ -2346,6 +2359,10 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
|
||||||
printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
|
printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
|
||||||
printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
|
printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
|
||||||
printed += fprintf(fp, "%.1f%%", ratio);
|
printed += fprintf(fp, "%.1f%%", ratio);
|
||||||
|
if (ttrace->pfmaj)
|
||||||
|
printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
|
||||||
|
if (ttrace->pfmin)
|
||||||
|
printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
|
||||||
printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
|
printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
|
||||||
printed += thread__dump_stats(ttrace, trace, fp);
|
printed += thread__dump_stats(ttrace, trace, fp);
|
||||||
|
|
||||||
|
|
|
@ -594,6 +594,10 @@ ifndef NO_LIBNUMA
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef HAVE_KVM_STAT_SUPPORT
|
||||||
|
CFLAGS += -DHAVE_KVM_STAT_SUPPORT
|
||||||
|
endif
|
||||||
|
|
||||||
# Among the variables below, these:
|
# Among the variables below, these:
|
||||||
# perfexecdir
|
# perfexecdir
|
||||||
# template_dir
|
# template_dir
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#define mb() asm volatile("bcr 15,0" ::: "memory")
|
#define mb() asm volatile("bcr 15,0" ::: "memory")
|
||||||
#define wmb() asm volatile("bcr 15,0" ::: "memory")
|
#define wmb() asm volatile("bcr 15,0" ::: "memory")
|
||||||
#define rmb() asm volatile("bcr 15,0" ::: "memory")
|
#define rmb() asm volatile("bcr 15,0" ::: "memory")
|
||||||
|
#define CPUINFO_PROC "vendor_id"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __sh__
|
#ifdef __sh__
|
||||||
|
|
|
@ -150,7 +150,7 @@ unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser)
|
||||||
while (nd != NULL) {
|
while (nd != NULL) {
|
||||||
ui_browser__gotorc(browser, row, 0);
|
ui_browser__gotorc(browser, row, 0);
|
||||||
browser->write(browser, nd, row);
|
browser->write(browser, nd, row);
|
||||||
if (++row == browser->height)
|
if (++row == browser->rows)
|
||||||
break;
|
break;
|
||||||
nd = rb_next(nd);
|
nd = rb_next(nd);
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row)
|
||||||
void ui_browser__refresh_dimensions(struct ui_browser *browser)
|
void ui_browser__refresh_dimensions(struct ui_browser *browser)
|
||||||
{
|
{
|
||||||
browser->width = SLtt_Screen_Cols - 1;
|
browser->width = SLtt_Screen_Cols - 1;
|
||||||
browser->height = SLtt_Screen_Rows - 2;
|
browser->height = browser->rows = SLtt_Screen_Rows - 2;
|
||||||
browser->y = 1;
|
browser->y = 1;
|
||||||
browser->x = 0;
|
browser->x = 0;
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,10 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
|
||||||
int err;
|
int err;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
ui_browser__refresh_dimensions(browser);
|
if (browser->refresh_dimensions == NULL)
|
||||||
|
browser->refresh_dimensions = ui_browser__refresh_dimensions;
|
||||||
|
|
||||||
|
browser->refresh_dimensions(browser);
|
||||||
|
|
||||||
pthread_mutex_lock(&ui__lock);
|
pthread_mutex_lock(&ui__lock);
|
||||||
__ui_browser__show_title(browser, title);
|
__ui_browser__show_title(browser, title);
|
||||||
|
@ -367,7 +370,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
|
||||||
|
|
||||||
if (key == K_RESIZE) {
|
if (key == K_RESIZE) {
|
||||||
ui__refresh_dimensions(false);
|
ui__refresh_dimensions(false);
|
||||||
ui_browser__refresh_dimensions(browser);
|
browser->refresh_dimensions(browser);
|
||||||
__ui_browser__show_title(browser, browser->title);
|
__ui_browser__show_title(browser, browser->title);
|
||||||
ui_helpline__puts(browser->helpline);
|
ui_helpline__puts(browser->helpline);
|
||||||
continue;
|
continue;
|
||||||
|
@ -389,7 +392,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
|
||||||
if (browser->index == browser->nr_entries - 1)
|
if (browser->index == browser->nr_entries - 1)
|
||||||
break;
|
break;
|
||||||
++browser->index;
|
++browser->index;
|
||||||
if (browser->index == browser->top_idx + browser->height) {
|
if (browser->index == browser->top_idx + browser->rows) {
|
||||||
++browser->top_idx;
|
++browser->top_idx;
|
||||||
browser->seek(browser, +1, SEEK_CUR);
|
browser->seek(browser, +1, SEEK_CUR);
|
||||||
}
|
}
|
||||||
|
@ -405,10 +408,10 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
|
||||||
break;
|
break;
|
||||||
case K_PGDN:
|
case K_PGDN:
|
||||||
case ' ':
|
case ' ':
|
||||||
if (browser->top_idx + browser->height > browser->nr_entries - 1)
|
if (browser->top_idx + browser->rows > browser->nr_entries - 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
offset = browser->height;
|
offset = browser->rows;
|
||||||
if (browser->index + offset > browser->nr_entries - 1)
|
if (browser->index + offset > browser->nr_entries - 1)
|
||||||
offset = browser->nr_entries - 1 - browser->index;
|
offset = browser->nr_entries - 1 - browser->index;
|
||||||
browser->index += offset;
|
browser->index += offset;
|
||||||
|
@ -419,10 +422,10 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
|
||||||
if (browser->top_idx == 0)
|
if (browser->top_idx == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (browser->top_idx < browser->height)
|
if (browser->top_idx < browser->rows)
|
||||||
offset = browser->top_idx;
|
offset = browser->top_idx;
|
||||||
else
|
else
|
||||||
offset = browser->height;
|
offset = browser->rows;
|
||||||
|
|
||||||
browser->index -= offset;
|
browser->index -= offset;
|
||||||
browser->top_idx -= offset;
|
browser->top_idx -= offset;
|
||||||
|
@ -432,7 +435,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs)
|
||||||
ui_browser__reset_index(browser);
|
ui_browser__reset_index(browser);
|
||||||
break;
|
break;
|
||||||
case K_END:
|
case K_END:
|
||||||
offset = browser->height - 1;
|
offset = browser->rows - 1;
|
||||||
if (offset >= browser->nr_entries)
|
if (offset >= browser->nr_entries)
|
||||||
offset = browser->nr_entries - 1;
|
offset = browser->nr_entries - 1;
|
||||||
|
|
||||||
|
@ -462,7 +465,7 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *browser)
|
||||||
if (!browser->filter || !browser->filter(browser, pos)) {
|
if (!browser->filter || !browser->filter(browser, pos)) {
|
||||||
ui_browser__gotorc(browser, row, 0);
|
ui_browser__gotorc(browser, row, 0);
|
||||||
browser->write(browser, pos, row);
|
browser->write(browser, pos, row);
|
||||||
if (++row == browser->height)
|
if (++row == browser->rows)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -587,7 +590,7 @@ unsigned int ui_browser__argv_refresh(struct ui_browser *browser)
|
||||||
if (!browser->filter || !browser->filter(browser, *pos)) {
|
if (!browser->filter || !browser->filter(browser, *pos)) {
|
||||||
ui_browser__gotorc(browser, row, 0);
|
ui_browser__gotorc(browser, row, 0);
|
||||||
browser->write(browser, pos, row);
|
browser->write(browser, pos, row);
|
||||||
if (++row == browser->height)
|
if (++row == browser->rows)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,7 +626,7 @@ static void __ui_browser__line_arrow_up(struct ui_browser *browser,
|
||||||
|
|
||||||
SLsmg_set_char_set(1);
|
SLsmg_set_char_set(1);
|
||||||
|
|
||||||
if (start < browser->top_idx + browser->height) {
|
if (start < browser->top_idx + browser->rows) {
|
||||||
row = start - browser->top_idx;
|
row = start - browser->top_idx;
|
||||||
ui_browser__gotorc(browser, row, column);
|
ui_browser__gotorc(browser, row, column);
|
||||||
SLsmg_write_char(SLSMG_LLCORN_CHAR);
|
SLsmg_write_char(SLSMG_LLCORN_CHAR);
|
||||||
|
@ -633,7 +636,7 @@ static void __ui_browser__line_arrow_up(struct ui_browser *browser,
|
||||||
if (row-- == 0)
|
if (row-- == 0)
|
||||||
goto out;
|
goto out;
|
||||||
} else
|
} else
|
||||||
row = browser->height - 1;
|
row = browser->rows - 1;
|
||||||
|
|
||||||
if (end > browser->top_idx)
|
if (end > browser->top_idx)
|
||||||
end_row = end - browser->top_idx;
|
end_row = end - browser->top_idx;
|
||||||
|
@ -675,8 +678,8 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser,
|
||||||
} else
|
} else
|
||||||
row = 0;
|
row = 0;
|
||||||
|
|
||||||
if (end >= browser->top_idx + browser->height)
|
if (end >= browser->top_idx + browser->rows)
|
||||||
end_row = browser->height - 1;
|
end_row = browser->rows - 1;
|
||||||
else
|
else
|
||||||
end_row = end - browser->top_idx;
|
end_row = end - browser->top_idx;
|
||||||
|
|
||||||
|
@ -684,7 +687,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser,
|
||||||
SLsmg_draw_vline(end_row - row + 1);
|
SLsmg_draw_vline(end_row - row + 1);
|
||||||
|
|
||||||
ui_browser__gotorc(browser, end_row, column);
|
ui_browser__gotorc(browser, end_row, column);
|
||||||
if (end < browser->top_idx + browser->height) {
|
if (end < browser->top_idx + browser->rows) {
|
||||||
SLsmg_write_char(SLSMG_LLCORN_CHAR);
|
SLsmg_write_char(SLSMG_LLCORN_CHAR);
|
||||||
ui_browser__gotorc(browser, end_row, column + 1);
|
ui_browser__gotorc(browser, end_row, column + 1);
|
||||||
SLsmg_write_char(SLSMG_HLINE_CHAR);
|
SLsmg_write_char(SLSMG_HLINE_CHAR);
|
||||||
|
|
|
@ -14,11 +14,12 @@
|
||||||
struct ui_browser {
|
struct ui_browser {
|
||||||
u64 index, top_idx;
|
u64 index, top_idx;
|
||||||
void *top, *entries;
|
void *top, *entries;
|
||||||
u16 y, x, width, height;
|
u16 y, x, width, height, rows;
|
||||||
int current_color;
|
int current_color;
|
||||||
void *priv;
|
void *priv;
|
||||||
const char *title;
|
const char *title;
|
||||||
char *helpline;
|
char *helpline;
|
||||||
|
void (*refresh_dimensions)(struct ui_browser *browser);
|
||||||
unsigned int (*refresh)(struct ui_browser *browser);
|
unsigned int (*refresh)(struct ui_browser *browser);
|
||||||
void (*write)(struct ui_browser *browser, void *entry, int row);
|
void (*write)(struct ui_browser *browser, void *entry, int row);
|
||||||
void (*seek)(struct ui_browser *browser, off_t offset, int whence);
|
void (*seek)(struct ui_browser *browser, off_t offset, int whence);
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct hist_browser {
|
||||||
struct map_symbol *selection;
|
struct map_symbol *selection;
|
||||||
int print_seq;
|
int print_seq;
|
||||||
bool show_dso;
|
bool show_dso;
|
||||||
|
bool show_headers;
|
||||||
float min_pcnt;
|
float min_pcnt;
|
||||||
u64 nr_non_filtered_entries;
|
u64 nr_non_filtered_entries;
|
||||||
u64 nr_callchain_rows;
|
u64 nr_callchain_rows;
|
||||||
|
@ -56,11 +57,42 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
|
||||||
return nr_entries + hb->nr_callchain_rows;
|
return nr_entries + hb->nr_callchain_rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hist_browser__refresh_dimensions(struct hist_browser *browser)
|
static void hist_browser__update_rows(struct hist_browser *hb)
|
||||||
{
|
{
|
||||||
|
struct ui_browser *browser = &hb->b;
|
||||||
|
u16 header_offset = hb->show_headers ? 1 : 0, index_row;
|
||||||
|
|
||||||
|
browser->rows = browser->height - header_offset;
|
||||||
|
/*
|
||||||
|
* Verify if we were at the last line and that line isn't
|
||||||
|
* visibe because we now show the header line(s).
|
||||||
|
*/
|
||||||
|
index_row = browser->index - browser->top_idx;
|
||||||
|
if (index_row >= browser->rows)
|
||||||
|
browser->index -= index_row - browser->rows + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hist_browser__refresh_dimensions(struct ui_browser *browser)
|
||||||
|
{
|
||||||
|
struct hist_browser *hb = container_of(browser, struct hist_browser, b);
|
||||||
|
|
||||||
/* 3 == +/- toggle symbol before actual hist_entry rendering */
|
/* 3 == +/- toggle symbol before actual hist_entry rendering */
|
||||||
browser->b.width = 3 + (hists__sort_list_width(browser->hists) +
|
browser->width = 3 + (hists__sort_list_width(hb->hists) + sizeof("[k]"));
|
||||||
sizeof("[k]"));
|
/*
|
||||||
|
* FIXME: Just keeping existing behaviour, but this really should be
|
||||||
|
* before updating browser->width, as it will invalidate the
|
||||||
|
* calculation above. Fix this and the fallout in another
|
||||||
|
* changeset.
|
||||||
|
*/
|
||||||
|
ui_browser__refresh_dimensions(browser);
|
||||||
|
hist_browser__update_rows(hb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hist_browser__gotorc(struct hist_browser *browser, int row, int column)
|
||||||
|
{
|
||||||
|
u16 header_offset = browser->show_headers ? 1 : 0;
|
||||||
|
|
||||||
|
ui_browser__gotorc(&browser->b, row + header_offset, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hist_browser__reset(struct hist_browser *browser)
|
static void hist_browser__reset(struct hist_browser *browser)
|
||||||
|
@ -73,7 +105,7 @@ static void hist_browser__reset(struct hist_browser *browser)
|
||||||
|
|
||||||
hist_browser__update_nr_entries(browser);
|
hist_browser__update_nr_entries(browser);
|
||||||
browser->b.nr_entries = hist_browser__nr_entries(browser);
|
browser->b.nr_entries = hist_browser__nr_entries(browser);
|
||||||
hist_browser__refresh_dimensions(browser);
|
hist_browser__refresh_dimensions(&browser->b);
|
||||||
ui_browser__reset_index(&browser->b);
|
ui_browser__reset_index(&browser->b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,7 +387,6 @@ static int hist_browser__run(struct hist_browser *browser,
|
||||||
browser->b.entries = &browser->hists->entries;
|
browser->b.entries = &browser->hists->entries;
|
||||||
browser->b.nr_entries = hist_browser__nr_entries(browser);
|
browser->b.nr_entries = hist_browser__nr_entries(browser);
|
||||||
|
|
||||||
hist_browser__refresh_dimensions(browser);
|
|
||||||
hists__browser_title(browser->hists, title, sizeof(title));
|
hists__browser_title(browser->hists, title, sizeof(title));
|
||||||
|
|
||||||
if (ui_browser__show(&browser->b, title,
|
if (ui_browser__show(&browser->b, title,
|
||||||
|
@ -392,10 +423,10 @@ static int hist_browser__run(struct hist_browser *browser,
|
||||||
struct hist_entry *h = rb_entry(browser->b.top,
|
struct hist_entry *h = rb_entry(browser->b.top,
|
||||||
struct hist_entry, rb_node);
|
struct hist_entry, rb_node);
|
||||||
ui_helpline__pop();
|
ui_helpline__pop();
|
||||||
ui_helpline__fpush("%d: nr_ent=(%d,%d), height=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
|
ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
|
||||||
seq++, browser->b.nr_entries,
|
seq++, browser->b.nr_entries,
|
||||||
browser->hists->nr_entries,
|
browser->hists->nr_entries,
|
||||||
browser->b.height,
|
browser->b.rows,
|
||||||
browser->b.index,
|
browser->b.index,
|
||||||
browser->b.top_idx,
|
browser->b.top_idx,
|
||||||
h->row_offset, h->nr_rows);
|
h->row_offset, h->nr_rows);
|
||||||
|
@ -409,6 +440,10 @@ static int hist_browser__run(struct hist_browser *browser,
|
||||||
/* Expand the whole world. */
|
/* Expand the whole world. */
|
||||||
hist_browser__set_folding(browser, true);
|
hist_browser__set_folding(browser, true);
|
||||||
break;
|
break;
|
||||||
|
case 'H':
|
||||||
|
browser->show_headers = !browser->show_headers;
|
||||||
|
hist_browser__update_rows(browser);
|
||||||
|
break;
|
||||||
case K_ENTER:
|
case K_ENTER:
|
||||||
if (hist_browser__toggle_fold(browser))
|
if (hist_browser__toggle_fold(browser))
|
||||||
break;
|
break;
|
||||||
|
@ -508,13 +543,13 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_browser__set_color(&browser->b, color);
|
ui_browser__set_color(&browser->b, color);
|
||||||
ui_browser__gotorc(&browser->b, row, 0);
|
hist_browser__gotorc(browser, row, 0);
|
||||||
slsmg_write_nstring(" ", offset + extra_offset);
|
slsmg_write_nstring(" ", offset + extra_offset);
|
||||||
slsmg_printf("%c ", folded_sign);
|
slsmg_printf("%c ", folded_sign);
|
||||||
slsmg_write_nstring(str, width);
|
slsmg_write_nstring(str, width);
|
||||||
free(alloc_str);
|
free(alloc_str);
|
||||||
|
|
||||||
if (++row == browser->b.height)
|
if (++row == browser->b.rows)
|
||||||
goto out;
|
goto out;
|
||||||
do_next:
|
do_next:
|
||||||
if (folded_sign == '+')
|
if (folded_sign == '+')
|
||||||
|
@ -527,7 +562,7 @@ do_next:
|
||||||
new_level, row, row_offset,
|
new_level, row, row_offset,
|
||||||
is_current_entry);
|
is_current_entry);
|
||||||
}
|
}
|
||||||
if (row == browser->b.height)
|
if (row == browser->b.rows)
|
||||||
goto out;
|
goto out;
|
||||||
node = next;
|
node = next;
|
||||||
}
|
}
|
||||||
|
@ -567,13 +602,13 @@ static int hist_browser__show_callchain_node(struct hist_browser *browser,
|
||||||
|
|
||||||
s = callchain_list__sym_name(chain, bf, sizeof(bf),
|
s = callchain_list__sym_name(chain, bf, sizeof(bf),
|
||||||
browser->show_dso);
|
browser->show_dso);
|
||||||
ui_browser__gotorc(&browser->b, row, 0);
|
hist_browser__gotorc(browser, row, 0);
|
||||||
ui_browser__set_color(&browser->b, color);
|
ui_browser__set_color(&browser->b, color);
|
||||||
slsmg_write_nstring(" ", offset);
|
slsmg_write_nstring(" ", offset);
|
||||||
slsmg_printf("%c ", folded_sign);
|
slsmg_printf("%c ", folded_sign);
|
||||||
slsmg_write_nstring(s, width - 2);
|
slsmg_write_nstring(s, width - 2);
|
||||||
|
|
||||||
if (++row == browser->b.height)
|
if (++row == browser->b.rows)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +637,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
|
||||||
row += hist_browser__show_callchain_node(browser, node, level,
|
row += hist_browser__show_callchain_node(browser, node, level,
|
||||||
row, row_offset,
|
row, row_offset,
|
||||||
is_current_entry);
|
is_current_entry);
|
||||||
if (row == browser->b.height)
|
if (row == browser->b.rows)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +767,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
|
||||||
.ptr = &arg,
|
.ptr = &arg,
|
||||||
};
|
};
|
||||||
|
|
||||||
ui_browser__gotorc(&browser->b, row, 0);
|
hist_browser__gotorc(browser, row, 0);
|
||||||
|
|
||||||
perf_hpp__for_each_format(fmt) {
|
perf_hpp__for_each_format(fmt) {
|
||||||
if (perf_hpp__should_skip(fmt))
|
if (perf_hpp__should_skip(fmt))
|
||||||
|
@ -776,7 +811,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
|
||||||
} else
|
} else
|
||||||
--row_offset;
|
--row_offset;
|
||||||
|
|
||||||
if (folded_sign == '-' && row != browser->b.height) {
|
if (folded_sign == '-' && row != browser->b.rows) {
|
||||||
printed += hist_browser__show_callchain(browser, &entry->sorted_chain,
|
printed += hist_browser__show_callchain(browser, &entry->sorted_chain,
|
||||||
1, row, &row_offset,
|
1, row, &row_offset,
|
||||||
¤t_entry);
|
¤t_entry);
|
||||||
|
@ -787,6 +822,56 @@ static int hist_browser__show_entry(struct hist_browser *browser,
|
||||||
return printed;
|
return printed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int advance_hpp_check(struct perf_hpp *hpp, int inc)
|
||||||
|
{
|
||||||
|
advance_hpp(hpp, inc);
|
||||||
|
return hpp->size <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
|
||||||
|
{
|
||||||
|
struct perf_hpp dummy_hpp = {
|
||||||
|
.buf = buf,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
struct perf_hpp_fmt *fmt;
|
||||||
|
size_t ret = 0;
|
||||||
|
|
||||||
|
if (symbol_conf.use_callchain) {
|
||||||
|
ret = scnprintf(buf, size, " ");
|
||||||
|
if (advance_hpp_check(&dummy_hpp, ret))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
perf_hpp__for_each_format(fmt) {
|
||||||
|
if (perf_hpp__should_skip(fmt))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* We need to add the length of the columns header. */
|
||||||
|
perf_hpp__reset_width(fmt, hists);
|
||||||
|
|
||||||
|
ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
|
||||||
|
if (advance_hpp_check(&dummy_hpp, ret))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " ");
|
||||||
|
if (advance_hpp_check(&dummy_hpp, ret))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hist_browser__show_headers(struct hist_browser *browser)
|
||||||
|
{
|
||||||
|
char headers[1024];
|
||||||
|
|
||||||
|
hists__scnprintf_headers(headers, sizeof(headers), browser->hists);
|
||||||
|
ui_browser__gotorc(&browser->b, 0, 0);
|
||||||
|
ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
|
||||||
|
slsmg_write_nstring(headers, browser->b.width + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void ui_browser__hists_init_top(struct ui_browser *browser)
|
static void ui_browser__hists_init_top(struct ui_browser *browser)
|
||||||
{
|
{
|
||||||
if (browser->top == NULL) {
|
if (browser->top == NULL) {
|
||||||
|
@ -800,9 +885,15 @@ static void ui_browser__hists_init_top(struct ui_browser *browser)
|
||||||
static unsigned int hist_browser__refresh(struct ui_browser *browser)
|
static unsigned int hist_browser__refresh(struct ui_browser *browser)
|
||||||
{
|
{
|
||||||
unsigned row = 0;
|
unsigned row = 0;
|
||||||
|
u16 header_offset = 0;
|
||||||
struct rb_node *nd;
|
struct rb_node *nd;
|
||||||
struct hist_browser *hb = container_of(browser, struct hist_browser, b);
|
struct hist_browser *hb = container_of(browser, struct hist_browser, b);
|
||||||
|
|
||||||
|
if (hb->show_headers) {
|
||||||
|
hist_browser__show_headers(hb);
|
||||||
|
header_offset = 1;
|
||||||
|
}
|
||||||
|
|
||||||
ui_browser__hists_init_top(browser);
|
ui_browser__hists_init_top(browser);
|
||||||
|
|
||||||
for (nd = browser->top; nd; nd = rb_next(nd)) {
|
for (nd = browser->top; nd; nd = rb_next(nd)) {
|
||||||
|
@ -817,11 +908,11 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
row += hist_browser__show_entry(hb, h, row);
|
row += hist_browser__show_entry(hb, h, row);
|
||||||
if (row == browser->height)
|
if (row == browser->rows)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return row;
|
return row + header_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rb_node *hists__filter_entries(struct rb_node *nd,
|
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)
|
||||||
if (browser) {
|
if (browser) {
|
||||||
browser->hists = hists;
|
browser->hists = hists;
|
||||||
browser->b.refresh = hist_browser__refresh;
|
browser->b.refresh = hist_browser__refresh;
|
||||||
|
browser->b.refresh_dimensions = hist_browser__refresh_dimensions;
|
||||||
browser->b.seek = ui_browser__hists_seek;
|
browser->b.seek = ui_browser__hists_seek;
|
||||||
browser->b.use_navkeypressed = true;
|
browser->b.use_navkeypressed = true;
|
||||||
|
browser->show_headers = symbol_conf.show_hist_headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
return browser;
|
return browser;
|
||||||
|
@ -1421,6 +1514,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
|
||||||
"d Zoom into current DSO\n" \
|
"d Zoom into current DSO\n" \
|
||||||
"E Expand all callchains\n" \
|
"E Expand all callchains\n" \
|
||||||
"F Toggle percentage of filtered entries\n" \
|
"F Toggle percentage of filtered entries\n" \
|
||||||
|
"H Display column headers\n" \
|
||||||
|
|
||||||
/* help messages are sorted by lexical order of the hotkey */
|
/* help messages are sorted by lexical order of the hotkey */
|
||||||
const char report_help[] = HIST_BROWSER_HELP_COMMON
|
const char report_help[] = HIST_BROWSER_HELP_COMMON
|
||||||
|
|
|
@ -350,6 +350,16 @@ static int perf_default_core_config(const char *var __maybe_unused,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int perf_ui_config(const char *var, const char *value)
|
||||||
|
{
|
||||||
|
/* Add other config variables here. */
|
||||||
|
if (!strcmp(var, "ui.show-headers")) {
|
||||||
|
symbol_conf.show_hist_headers = perf_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int perf_default_config(const char *var, const char *value,
|
int perf_default_config(const char *var, const char *value,
|
||||||
void *dummy __maybe_unused)
|
void *dummy __maybe_unused)
|
||||||
{
|
{
|
||||||
|
@ -359,6 +369,9 @@ int perf_default_config(const char *var, const char *value,
|
||||||
if (!prefixcmp(var, "hist."))
|
if (!prefixcmp(var, "hist."))
|
||||||
return perf_hist_config(var, value);
|
return perf_hist_config(var, value);
|
||||||
|
|
||||||
|
if (!prefixcmp(var, "ui."))
|
||||||
|
return perf_ui_config(var, value);
|
||||||
|
|
||||||
/* Add other config variables here. */
|
/* Add other config variables here. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ static int open_file_read(struct perf_data_file *file)
|
||||||
goto out_close;
|
goto out_close;
|
||||||
|
|
||||||
if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
|
if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
|
||||||
pr_err("file %s not owned by current user or root\n",
|
pr_err("File %s not owned by current user or root (use -f to override)\n",
|
||||||
file->path);
|
file->path);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1215,7 +1215,7 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
|
||||||
hse = container_of(fmt, struct hpp_sort_entry, hpp);
|
hse = container_of(fmt, struct hpp_sort_entry, hpp);
|
||||||
len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
|
len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
|
||||||
|
|
||||||
return scnprintf(hpp->buf, hpp->size, "%*s", len, hse->se->se_header);
|
return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
|
static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct symbol_conf symbol_conf = {
|
||||||
.annotate_src = true,
|
.annotate_src = true,
|
||||||
.demangle = true,
|
.demangle = true,
|
||||||
.cumulate_callchain = true,
|
.cumulate_callchain = true,
|
||||||
|
.show_hist_headers = true,
|
||||||
.symfs = "",
|
.symfs = "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,8 @@ struct symbol_conf {
|
||||||
annotate_src,
|
annotate_src,
|
||||||
event_group,
|
event_group,
|
||||||
demangle,
|
demangle,
|
||||||
filter_relative;
|
filter_relative,
|
||||||
|
show_hist_headers;
|
||||||
const char *vmlinux_name,
|
const char *vmlinux_name,
|
||||||
*kallsyms_name,
|
*kallsyms_name,
|
||||||
*source_prefix,
|
*source_prefix,
|
||||||
|
|
|
@ -191,12 +191,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps)
|
||||||
strcmp(dent->d_name, "..") == 0 ||
|
strcmp(dent->d_name, "..") == 0 ||
|
||||||
!name_in_tp_list(dent->d_name, tps))
|
!name_in_tp_list(dent->d_name, tps))
|
||||||
continue;
|
continue;
|
||||||
format = malloc(strlen(sys) + strlen(dent->d_name) + 10);
|
if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
|
||||||
if (!format) {
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sprintf(format, "%s/%s/format", sys, dent->d_name);
|
|
||||||
ret = stat(format, &st);
|
ret = stat(format, &st);
|
||||||
free(format);
|
free(format);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -217,12 +215,10 @@ static int copy_event_system(const char *sys, struct tracepoint_path *tps)
|
||||||
strcmp(dent->d_name, "..") == 0 ||
|
strcmp(dent->d_name, "..") == 0 ||
|
||||||
!name_in_tp_list(dent->d_name, tps))
|
!name_in_tp_list(dent->d_name, tps))
|
||||||
continue;
|
continue;
|
||||||
format = malloc(strlen(sys) + strlen(dent->d_name) + 10);
|
if (asprintf(&format, "%s/%s/format", sys, dent->d_name) < 0) {
|
||||||
if (!format) {
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sprintf(format, "%s/%s/format", sys, dent->d_name);
|
|
||||||
ret = stat(format, &st);
|
ret = stat(format, &st);
|
||||||
|
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
|
@ -317,12 +313,10 @@ static int record_event_files(struct tracepoint_path *tps)
|
||||||
strcmp(dent->d_name, "ftrace") == 0 ||
|
strcmp(dent->d_name, "ftrace") == 0 ||
|
||||||
!system_in_tp_list(dent->d_name, tps))
|
!system_in_tp_list(dent->d_name, tps))
|
||||||
continue;
|
continue;
|
||||||
sys = malloc(strlen(path) + strlen(dent->d_name) + 2);
|
if (asprintf(&sys, "%s/%s", path, dent->d_name) < 0) {
|
||||||
if (!sys) {
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
sprintf(sys, "%s/%s", path, dent->d_name);
|
|
||||||
ret = stat(sys, &st);
|
ret = stat(sys, &st);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
ssize_t size = strlen(dent->d_name) + 1;
|
ssize_t size = strlen(dent->d_name) + 1;
|
||||||
|
|
|
@ -333,12 +333,9 @@ const char *find_tracing_dir(void)
|
||||||
if (!debugfs)
|
if (!debugfs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
tracing = malloc(strlen(debugfs) + 9);
|
if (asprintf(&tracing, "%s/tracing", debugfs) < 0)
|
||||||
if (!tracing)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sprintf(tracing, "%s/tracing", debugfs);
|
|
||||||
|
|
||||||
tracing_found = 1;
|
tracing_found = 1;
|
||||||
return tracing;
|
return tracing;
|
||||||
}
|
}
|
||||||
|
@ -352,11 +349,9 @@ char *get_tracing_file(const char *name)
|
||||||
if (!tracing)
|
if (!tracing)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
file = malloc(strlen(tracing) + strlen(name) + 2);
|
if (asprintf(&file, "%s/%s", tracing, name) < 0)
|
||||||
if (!file)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sprintf(file, "%s/%s", tracing, name);
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче