Commit 203e04c1 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

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:

. perf build-id cache now can show DSOs present in a perf.data file that are
  not in the cache, to integrate with build-id servers being put in place by
  organizations such as Fedora.

. perf buildid-list -i an-elf-file-instead-of-a-perf.data is back showing its
  build-id.

. No need to do feature checks when doing a 'make tags'

. Fix some 'perf test' errors and make them use the tracepoint evsel constructor.

. perf top now shares more of the evsel config/creation routines with 'record',
  paving the way for further integration like 'top' snapshots, etc.

. perf top now supports DWARF callchains.

. perf evlist decodes sample_type and read_format, helping diagnose problems.

. Fix mmap limitations on 32-bit, fix from David Miller.

. perf diff fixes from Jiri Olsa.

. Ignore ABS symbols when loading data maps, fix from Namhyung Kim

. Hists improvements from Namhyung Kim

. Don't check configuration on make clean, from Namhyung Kim

. Fix dso__fprintf() print statement, from Stephane Eranian.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents ba6fdda4 2376c67a
...@@ -222,10 +222,14 @@ install-pdf: pdf ...@@ -222,10 +222,14 @@ install-pdf: pdf
#install-html: html #install-html: html
# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) # '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),tags)
$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE
-include $(OUTPUT)PERF-VERSION-FILE -include $(OUTPUT)PERF-VERSION-FILE
endif
endif
# #
# Determine "include::" file references in asciidoc files. # Determine "include::" file references in asciidoc files.
......
...@@ -24,6 +24,9 @@ OPTIONS ...@@ -24,6 +24,9 @@ OPTIONS
-r:: -r::
--remove=:: --remove=::
Remove specified file from the cache. Remove specified file from the cache.
-M::
--missing=::
List missing build ids in the cache for the specified file.
-v:: -v::
--verbose:: --verbose::
Be more verbose. Be more verbose.
......
...@@ -22,10 +22,6 @@ specified perf.data files. ...@@ -22,10 +22,6 @@ specified perf.data files.
OPTIONS OPTIONS
------- -------
-M::
--displacement::
Show position displacement relative to baseline.
-D:: -D::
--dump-raw-trace:: --dump-raw-trace::
Dump raw trace in ASCII. Dump raw trace in ASCII.
......
...@@ -60,7 +60,7 @@ Default is to monitor all CPUS. ...@@ -60,7 +60,7 @@ Default is to monitor all CPUS.
-i:: -i::
--inherit:: --inherit::
Child tasks inherit counters, only makes sens with -p option. Child tasks do not inherit counters.
-k <path>:: -k <path>::
--vmlinux=<path>:: --vmlinux=<path>::
......
...@@ -153,6 +153,8 @@ INSTALL = install ...@@ -153,6 +153,8 @@ INSTALL = install
# explicitly what architecture to check for. Fix this up for yours.. # explicitly what architecture to check for. Fix this up for yours..
SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),tags)
-include config/feature-tests.mak -include config/feature-tests.mak
ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
...@@ -206,6 +208,8 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) ...@@ -206,6 +208,8 @@ ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
BASIC_CFLAGS += -I. BASIC_CFLAGS += -I.
endif endif
endif # MAKECMDGOALS != tags
endif # MAKECMDGOALS != clean
# Guard against environment variables # Guard against environment variables
BUILTIN_OBJS = BUILTIN_OBJS =
...@@ -230,11 +234,19 @@ endif ...@@ -230,11 +234,19 @@ endif
LIBTRACEEVENT = $(TE_PATH)libtraceevent.a LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
TE_LIB := -L$(TE_PATH) -ltraceevent TE_LIB := -L$(TE_PATH) -ltraceevent
export LIBTRACEEVENT
# python extension build directories
PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
export LIBTRACEEVENT
$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
$(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
--quiet build_ext; \ --quiet build_ext; \
...@@ -378,8 +390,11 @@ LIB_H += util/rblist.h ...@@ -378,8 +390,11 @@ LIB_H += util/rblist.h
LIB_H += util/intlist.h LIB_H += util/intlist.h
LIB_H += util/perf_regs.h LIB_H += util/perf_regs.h
LIB_H += util/unwind.h LIB_H += util/unwind.h
LIB_H += ui/helpline.h
LIB_H += util/vdso.h LIB_H += util/vdso.h
LIB_H += ui/helpline.h
LIB_H += ui/progress.h
LIB_H += ui/util.h
LIB_H += ui/ui.h
LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o LIB_OBJS += $(OUTPUT)util/alias.o
...@@ -453,6 +468,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o ...@@ -453,6 +468,7 @@ LIB_OBJS += $(OUTPUT)util/stat.o
LIB_OBJS += $(OUTPUT)ui/setup.o LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/progress.o LIB_OBJS += $(OUTPUT)ui/progress.o
LIB_OBJS += $(OUTPUT)ui/util.o
LIB_OBJS += $(OUTPUT)ui/hist.o LIB_OBJS += $(OUTPUT)ui/hist.o
LIB_OBJS += $(OUTPUT)ui/stdio/hist.o LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
...@@ -471,7 +487,6 @@ LIB_OBJS += $(OUTPUT)tests/rdpmc.o ...@@ -471,7 +487,6 @@ LIB_OBJS += $(OUTPUT)tests/rdpmc.o
LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
LIB_OBJS += $(OUTPUT)tests/pmu.o LIB_OBJS += $(OUTPUT)tests/pmu.o
LIB_OBJS += $(OUTPUT)tests/util.o
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
BUILTIN_OBJS += $(OUTPUT)builtin-bench.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
...@@ -510,6 +525,8 @@ PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) ...@@ -510,6 +525,8 @@ PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
# #
# Platform specific tweaks # Platform specific tweaks
# #
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),tags)
# We choose to avoid "if .. else if .. else .. endif endif" # We choose to avoid "if .. else if .. else .. endif endif"
# because maintaining the nesting to match is a pain. If # because maintaining the nesting to match is a pain. If
...@@ -646,7 +663,6 @@ ifndef NO_NEWT ...@@ -646,7 +663,6 @@ ifndef NO_NEWT
LIB_OBJS += $(OUTPUT)ui/browsers/hists.o LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
LIB_OBJS += $(OUTPUT)ui/browsers/map.o LIB_OBJS += $(OUTPUT)ui/browsers/map.o
LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
LIB_OBJS += $(OUTPUT)ui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/setup.o LIB_OBJS += $(OUTPUT)ui/tui/setup.o
LIB_OBJS += $(OUTPUT)ui/tui/util.o LIB_OBJS += $(OUTPUT)ui/tui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/helpline.o LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
...@@ -655,9 +671,6 @@ ifndef NO_NEWT ...@@ -655,9 +671,6 @@ ifndef NO_NEWT
LIB_H += ui/browsers/map.h LIB_H += ui/browsers/map.h
LIB_H += ui/keysyms.h LIB_H += ui/keysyms.h
LIB_H += ui/libslang.h LIB_H += ui/libslang.h
LIB_H += ui/progress.h
LIB_H += ui/util.h
LIB_H += ui/ui.h
endif endif
endif endif
...@@ -677,10 +690,6 @@ ifndef NO_GTK2 ...@@ -677,10 +690,6 @@ ifndef NO_GTK2
LIB_OBJS += $(OUTPUT)ui/gtk/util.o LIB_OBJS += $(OUTPUT)ui/gtk/util.o
LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
LIB_OBJS += $(OUTPUT)ui/gtk/progress.o LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
# Make sure that it'd be included only once.
ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
LIB_OBJS += $(OUTPUT)ui/util.o
endif
endif endif
endif endif
...@@ -707,7 +716,7 @@ disable-python = $(eval $(disable-python_code)) ...@@ -707,7 +716,7 @@ disable-python = $(eval $(disable-python_code))
define disable-python_code define disable-python_code
BASIC_CFLAGS += -DNO_LIBPYTHON BASIC_CFLAGS += -DNO_LIBPYTHON
$(if $(1),$(warning No $(1) was found)) $(if $(1),$(warning No $(1) was found))
$(warning Python support won't be built) $(warning Python support will not be built)
endef endef
override PYTHON := \ override PYTHON := \
...@@ -715,19 +724,10 @@ override PYTHON := \ ...@@ -715,19 +724,10 @@ override PYTHON := \
ifndef PYTHON ifndef PYTHON
$(call disable-python,python interpreter) $(call disable-python,python interpreter)
python-clean :=
else else
PYTHON_WORD := $(call shell-wordify,$(PYTHON)) PYTHON_WORD := $(call shell-wordify,$(PYTHON))
# python extension build directories
PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
ifdef NO_LIBPYTHON ifdef NO_LIBPYTHON
$(call disable-python) $(call disable-python)
else else
...@@ -843,6 +843,9 @@ ifdef ASCIIDOC8 ...@@ -843,6 +843,9 @@ ifdef ASCIIDOC8
export ASCIIDOC8 export ASCIIDOC8
endif endif
endif # MAKECMDGOALS != tags
endif # MAKECMDGOALS != clean
# Shell quote (do not use $(call) to accommodate ancient setups); # Shell quote (do not use $(call) to accommodate ancient setups);
ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
...@@ -1099,7 +1102,7 @@ perfexec_instdir = $(prefix)/$(perfexecdir) ...@@ -1099,7 +1102,7 @@ perfexec_instdir = $(prefix)/$(perfexecdir)
endif endif
perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
install: all try-install-man install-bin: all
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)' $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
...@@ -1120,6 +1123,8 @@ install: all try-install-man ...@@ -1120,6 +1123,8 @@ install: all try-install-man
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
$(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
install: install-bin try-install-man
install-python_ext: install-python_ext:
$(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "util/parse-options.h" #include "util/parse-options.h"
#include "util/strlist.h" #include "util/strlist.h"
#include "util/build-id.h" #include "util/build-id.h"
#include "util/session.h"
#include "util/symbol.h" #include "util/symbol.h"
static int build_id_cache__add_file(const char *filename, const char *debugdir) static int build_id_cache__add_file(const char *filename, const char *debugdir)
...@@ -58,19 +59,59 @@ static int build_id_cache__remove_file(const char *filename, ...@@ -58,19 +59,59 @@ static int build_id_cache__remove_file(const char *filename,
return err; return err;
} }
static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
{
char filename[PATH_MAX];
u8 build_id[BUILD_ID_SIZE];
if (dso__build_id_filename(dso, filename, sizeof(filename)) &&
filename__read_build_id(filename, build_id,
sizeof(build_id)) != sizeof(build_id)) {
if (errno == ENOENT)
return false;
pr_warning("Problems with %s file, consider removing it from the cache\n",
filename);
} else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
pr_warning("Problems with %s file, consider removing it from the cache\n",
filename);
}
return true;
}
static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
{
struct perf_session *session = perf_session__new(filename, O_RDONLY,
force, false, NULL);
if (session == NULL)
return -1;
perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
perf_session__delete(session);
return 0;
}
int cmd_buildid_cache(int argc, const char **argv, int cmd_buildid_cache(int argc, const char **argv,
const char *prefix __maybe_unused) const char *prefix __maybe_unused)
{ {
struct strlist *list; struct strlist *list;
struct str_node *pos; struct str_node *pos;
int ret = 0;
bool force = false;
char debugdir[PATH_MAX]; char debugdir[PATH_MAX];
char const *add_name_list_str = NULL, char const *add_name_list_str = NULL,
*remove_name_list_str = NULL; *remove_name_list_str = NULL,
*missing_filename = NULL;
const struct option buildid_cache_options[] = { const struct option buildid_cache_options[] = {
OPT_STRING('a', "add", &add_name_list_str, OPT_STRING('a', "add", &add_name_list_str,
"file list", "file(s) to add"), "file list", "file(s) to add"),
OPT_STRING('r', "remove", &remove_name_list_str, "file list", OPT_STRING('r', "remove", &remove_name_list_str, "file list",
"file(s) to remove"), "file(s) to remove"),
OPT_STRING('M', "missing", &missing_filename, "file",
"to find missing build ids in the cache"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_INCR('v', "verbose", &verbose, "be more verbose"),
OPT_END() OPT_END()
}; };
...@@ -125,5 +166,8 @@ int cmd_buildid_cache(int argc, const char **argv, ...@@ -125,5 +166,8 @@ int cmd_buildid_cache(int argc, const char **argv,
} }
} }
return 0; if (missing_filename)
ret = build_id_cache__fprintf_missing(missing_filename, force, stdout);
return ret;
} }
...@@ -44,23 +44,26 @@ static int filename__fprintf_build_id(const char *name, FILE *fp) ...@@ -44,23 +44,26 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
return fprintf(fp, "%s\n", sbuild_id); return fprintf(fp, "%s\n", sbuild_id);
} }
static bool dso__skip_buildid(struct dso *dso, int with_hits)
{
return with_hits && !dso->hit;
}
static int perf_session__list_build_ids(bool force, bool with_hits) static int perf_session__list_build_ids(bool force, bool with_hits)
{ {
struct perf_session *session; struct perf_session *session;
symbol__elf_init(); symbol__elf_init();
session = perf_session__new(input_name, O_RDONLY, force, false,
&build_id__mark_dso_hit_ops);
if (session == NULL)
return -1;
/* /*
* See if this is an ELF file first: * See if this is an ELF file first:
*/ */
if (filename__fprintf_build_id(session->filename, stdout)) if (filename__fprintf_build_id(input_name, stdout))
goto out; goto out;
session = perf_session__new(input_name, O_RDONLY, force, false,
&build_id__mark_dso_hit_ops);
if (session == NULL)
return -1;
/* /*
* in pipe-mode, the only way to get the buildids is to parse * in pipe-mode, the only way to get the buildids is to parse
* the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
...@@ -68,9 +71,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits) ...@@ -68,9 +71,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
if (with_hits || session->fd_pipe) if (with_hits || session->fd_pipe)
perf_session__process_events(session, &build_id__mark_dso_hit_ops); perf_session__process_events(session, &build_id__mark_dso_hit_ops);
perf_session__fprintf_dsos_buildid(session, stdout, with_hits); perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
out:
perf_session__delete(session); perf_session__delete(session);
out:
return 0; return 0;
} }
......
...@@ -23,7 +23,6 @@ static char const *input_old = "perf.data.old", ...@@ -23,7 +23,6 @@ static char const *input_old = "perf.data.old",
*input_new = "perf.data"; *input_new = "perf.data";
static char diff__default_sort_order[] = "dso,symbol"; static char diff__default_sort_order[] = "dso,symbol";
static bool force; static bool force;
static bool show_displacement;
static bool show_period; static bool show_period;
static bool show_formula; static bool show_formula;
static bool show_baseline_only; static bool show_baseline_only;
...@@ -146,58 +145,47 @@ static int setup_compute(const struct option *opt, const char *str, ...@@ -146,58 +145,47 @@ static int setup_compute(const struct option *opt, const char *str,
return -EINVAL; return -EINVAL;
} }
static double get_period_percent(struct hist_entry *he, u64 period) double perf_diff__period_percent(struct hist_entry *he, u64 period)
{ {
u64 total = he->hists->stats.total_period; u64 total = he->hists->stats.total_period;
return (period * 100.0) / total; return (period * 100.0) / total;
} }
double perf_diff__compute_delta(struct hist_entry *he) double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair)
{ {
struct hist_entry *pair = hist_entry__next_pair(he); double new_percent = perf_diff__period_percent(he, he->stat.period);
double new_percent = get_period_percent(he, he->stat.period); double old_percent = perf_diff__period_percent(pair, pair->stat.period);
double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
he->diff.period_ratio_delta = new_percent - old_percent; he->diff.period_ratio_delta = new_percent - old_percent;
he->diff.computed = true; he->diff.computed = true;
return he->diff.period_ratio_delta; return he->diff.period_ratio_delta;
} }
double perf_diff__compute_ratio(struct hist_entry *he) double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
double new_period = he->stat.period; double new_period = he->stat.period;
double old_period = pair ? pair->stat.period : 0; double old_period = pair->stat.period;
he->diff.computed = true; he->diff.computed = true;
he->diff.period_ratio = pair ? (new_period / old_period) : 0; he->diff.period_ratio = new_period / old_period;
return he->diff.period_ratio; return he->diff.period_ratio;
} }
s64 perf_diff__compute_wdiff(struct hist_entry *he) s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
u64 new_period = he->stat.period; u64 new_period = he->stat.period;
u64 old_period = pair ? pair->stat.period : 0; u64 old_period = pair->stat.period;
he->diff.computed = true; he->diff.computed = true;
he->diff.wdiff = new_period * compute_wdiff_w2 -
if (!pair) old_period * compute_wdiff_w1;
he->diff.wdiff = 0;
else
he->diff.wdiff = new_period * compute_wdiff_w2 -
old_period * compute_wdiff_w1;
return he->diff.wdiff; return he->diff.wdiff;
} }
static int formula_delta(struct hist_entry *he, char *buf, size_t size) static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
char *buf, size_t size)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
if (!pair)
return -1;
return scnprintf(buf, size, return scnprintf(buf, size,
"(%" PRIu64 " * 100 / %" PRIu64 ") - " "(%" PRIu64 " * 100 / %" PRIu64 ") - "
"(%" PRIu64 " * 100 / %" PRIu64 ")", "(%" PRIu64 " * 100 / %" PRIu64 ")",
...@@ -205,41 +193,36 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size) ...@@ -205,41 +193,36 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size)
pair->stat.period, pair->hists->stats.total_period); pair->stat.period, pair->hists->stats.total_period);
} }
static int formula_ratio(struct hist_entry *he, char *buf, size_t size) static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
char *buf, size_t size)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
double new_period = he->stat.period; double new_period = he->stat.period;
double old_period = pair ? pair->stat.period : 0; double old_period = pair->stat.period;
if (!pair)
return -1;
return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period); return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
} }
static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair,
char *buf, size_t size)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
u64 new_period = he->stat.period; u64 new_period = he->stat.period;
u64 old_period = pair ? pair->stat.period : 0; u64 old_period = pair->stat.period;
if (!pair)
return -1;
return scnprintf(buf, size, return scnprintf(buf, size,
"(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")", "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
new_period, compute_wdiff_w2, old_period, compute_wdiff_w1); new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
} }
int perf_diff__formula(char *buf, size_t size, struct hist_entry *he) int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
char *buf, size_t size)
{ {
switch (compute) { switch (compute) {
case COMPUTE_DELTA: case COMPUTE_DELTA:
return formula_delta(he, buf, size); return formula_delta(he, pair, buf, size);
case COMPUTE_RATIO: case COMPUTE_RATIO:
return formula_ratio(he, buf, size); return formula_ratio(he, pair, buf, size);
case COMPUTE_WEIGHTED_DIFF: case COMPUTE_WEIGHTED_DIFF:
return formula_wdiff(he, buf, size); return formula_wdiff(he, pair, buf, size);
default: default:
BUG_ON(1); BUG_ON(1);
} }
...@@ -312,9 +295,8 @@ static void insert_hist_entry_by_name(struct rb_root *root, ...@@ -312,9 +295,8 @@ static void insert_hist_entry_by_name(struct rb_root *root,
rb_insert_color(&he->rb_node, root); rb_insert_color(&he->rb_node, root);
} }
static void hists__name_resort(struct hists *self, bool sort) static void hists__name_resort(struct hists *self)
{ {
unsigned long position = 1;
struct rb_root tmp = RB_ROOT; struct rb_root tmp = RB_ROOT;
struct rb_node *next = rb_first(&self->entries); struct rb_node *next = rb_first(&self->entries);
...@@ -322,16 +304,12 @@ static void hists__name_resort(struct hists *self, bool sort) ...@@ -322,16 +304,12 @@ static void hists__name_resort(struct hists *self, bool sort)
struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
next = rb_next(&n->rb_node); next = rb_next(&n->rb_node);
n->position = position++;
if (sort) { rb_erase(&n->rb_node, &self->entries);
rb_erase(&n->rb_node, &self->entries); insert_hist_entry_by_name(&tmp, n);
insert_hist_entry_by_name(&tmp, n);
}
} }
if (sort) self->entries = tmp;
self->entries = tmp;
} }
static struct perf_evsel *evsel_match(struct perf_evsel *evsel, static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
...@@ -355,12 +333,8 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name) ...@@ -355,12 +333,8 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
hists__output_resort(hists); hists__output_resort(hists);
/* if (name)
* The hists__name_resort only sets possition hists__name_resort(hists);
* if name is false.
*/
if (name || ((!name) && show_displacement))
hists__name_resort(hists, name);
} }
} }
...@@ -385,18 +359,21 @@ static void hists__precompute(struct hists *hists) ...@@ -385,18 +359,21 @@ static void hists__precompute(struct hists *hists)
while (next != NULL) { while (next != NULL) {
struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
struct hist_entry *pair = hist_entry__next_pair(he);
next = rb_next(&he->rb_node); next = rb_next(&he->rb_node);
if (!pair)
continue;
switch (compute) { switch (compute) {
case COMPUTE_DELTA: case COMPUTE_DELTA:
perf_diff__compute_delta(he); perf_diff__compute_delta(he, pair);
break; break;
case COMPUTE_RATIO: case COMPUTE_RATIO:
perf_diff__compute_ratio(he); perf_diff__compute_ratio(he, pair);
break; break;
case COMPUTE_WEIGHTED_DIFF: case COMPUTE_WEIGHTED_DIFF:
perf_diff__compute_wdiff(he); perf_diff__compute_wdiff(he, pair);
break; break;
default: default:
BUG_ON(1); BUG_ON(1);
...@@ -562,8 +539,6 @@ static const char * const diff_usage[] = { ...@@ -562,8 +539,6 @@ static const char * const diff_usage[] = {
static const struct option options[] = { static const struct option options[] = {
OPT_INCR('v', "verbose", &verbose, OPT_INCR('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"), "be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('M', "displacement", &show_displacement,
"Show position displacement relative to baseline"),
OPT_BOOLEAN('b', "baseline-only", &show_baseline_only, OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
"Show only items with match in baseline"), "Show only items with match in baseline"),
OPT_CALLBACK('c', "compute", &compute, OPT_CALLBACK('c', "compute", &compute,
...@@ -597,40 +572,32 @@ static const struct option options[] = { ...@@ -597,40 +572,32 @@ static const struct option options[] = {
static void ui_init(void) static void ui_init(void)
{ {
perf_hpp__init();
/* No overhead column. */
perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
/* /*
* Display baseline/delta/ratio/displacement/ * Display baseline/delta/ratio
* formula/periods columns. * formula/periods columns.
*/ */
perf_hpp__column_enable(PERF_HPP__BASELINE, true); perf_hpp__column_enable(PERF_HPP__BASELINE);
switch (compute) { switch (compute) {
case COMPUTE_DELTA: case COMPUTE_DELTA:
perf_hpp__column_enable(PERF_HPP__DELTA, true); perf_hpp__column_enable(PERF_HPP__DELTA);
break; break;
case COMPUTE_RATIO: case COMPUTE_RATIO:
perf_hpp__column_enable(PERF_HPP__RATIO, true); perf_hpp__column_enable(PERF_HPP__RATIO);
break; break;
case COMPUTE_WEIGHTED_DIFF: case COMPUTE_WEIGHTED_DIFF:
perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true); perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF);
break; break;
default: default:
BUG_ON(1); BUG_ON(1);
}; };
if (show_displacement)
perf_hpp__column_enable(PERF_HPP__DISPL, true);
if (show_formula) if (show_formula)
perf_hpp__column_enable(PERF_HPP__FORMULA, true); perf_hpp__column_enable(PERF_HPP__FORMULA);
if (show_period) { if (show_period) {
perf_hpp__column_enable(PERF_HPP__PERIOD, true); perf_hpp__column_enable(PERF_HPP__PERIOD);
perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true); perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE);
} }
} }
......
...@@ -15,39 +15,6 @@ ...@@ -15,39 +15,6 @@
#include "util/parse-options.h" #include "util/parse-options.h"
#include "util/session.h" #include "util/session.h"
struct perf_attr_details {
bool freq;
bool verbose;
};
static int comma_printf(bool *first, const char *fmt, ...)
{
va_list args;
int ret = 0;
if (!*first) {
ret += printf(",");
} else {
ret += printf(":");
*first = false;
}
va_start(args, fmt);
ret += vprintf(fmt, args);
va_end(args);
return ret;
}
static int __if_print(bool *first, const char *field, u64 value)
{
if (value == 0)
return 0;
return comma_printf(first, " %s: %" PRIu64, field, value);
}
#define if_print(field) __if_print(&first, #field, pos->attr.field)
static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
{ {
struct perf_session *session; struct perf_session *session;
...@@ -57,52 +24,8 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details ...@@ -57,52 +24,8 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
if (session == NULL) if (session == NULL)
return -ENOMEM; return -ENOMEM;
list_for_each_entry(pos, &session->evlist->entries, node) { list_for_each_entry(pos, &session->evlist->entries, node)
bool first = true; perf_evsel__fprintf(pos, details, stdout);
printf("%s", perf_evsel__name(pos));
if (details->verbose || details->freq) {
comma_printf(&first, " sample_freq=%" PRIu64,
(u64)pos->attr.sample_freq);
}
if (details->verbose) {
if_print(type);
if_print(config);
if_print(config1);
if_print(config2);
if_print(size);
if_print(sample_type);
if_print(read_format);
if_print(disabled);
if_print(inherit);
if_print(pinned);
if_print(exclusive);
if_print(exclude_user);
if_print(exclude_kernel);
if_print(exclude_hv);
if_print(exclude_idle);
if_print(mmap);
if_print(comm);
if_print(freq);
if_print(inherit_stat);
if_print(enable_on_exec);
if_print(task);
if_print(watermark);
if_print(precise_ip);
if_print(mmap_data);
if_print(sample_id_all);
if_print(exclude_host);
if_print(exclude_guest);
if_print(__reserved_1);
if_print(wakeup_events);
if_print(bp_type);
if_print(branch_sample_type);
}
putchar('\n');
}
perf_session__delete(session); perf_session__delete(session);
return 0; return 0;
......
...@@ -230,14 +230,7 @@ static int perf_record__open(struct perf_record *rec) ...@@ -230,14 +230,7 @@ static int perf_record__open(struct perf_record *rec)
struct perf_record_opts *opts = &rec->opts; struct perf_record_opts *opts = &rec->opts;
int rc = 0; int rc = 0;
/* perf_evlist__config(evlist, opts);
* Set the evsel leader links before we configure attributes,
* since some might depend on this info.
*/
if (opts->group)
perf_evlist__set_leader(evlist);
perf_evlist__config_attrs(evlist, opts);
list_for_each_entry(pos, &evlist->entries, node) { list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr; struct perf_event_attr *attr = &pos->attr;
...@@ -286,7 +279,7 @@ static int perf_record__open(struct perf_record *rec) ...@@ -286,7 +279,7 @@ static int perf_record__open(struct perf_record *rec)
*/ */
opts->sample_id_all_missing = true; opts->sample_id_all_missing = true;
if (!opts->sample_time && !opts->raw_samples && !time_needed) if (!opts->sample_time && !opts->raw_samples && !time_needed)
attr->sample_type &= ~PERF_SAMPLE_TIME; perf_evsel__reset_sample_bit(pos, TIME);
goto retry_sample_id; goto retry_sample_id;
} }
...@@ -875,11 +868,10 @@ static int get_stack_size(char *str, unsigned long *_size) ...@@ -875,11 +868,10 @@ static int get_stack_size(char *str, unsigned long *_size)
} }
#endif /* LIBUNWIND_SUPPORT */ #endif /* LIBUNWIND_SUPPORT */
static int int record_parse_callchain_opt(const struct option *opt,
parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, const char *arg, int unset)
int unset)
{ {
struct perf_record *rec = (struct perf_record *)opt->value; struct perf_record_opts *opts = opt->value;
char *tok, *name, *saveptr = NULL; char *tok, *name, *saveptr = NULL;
char *buf; char *buf;
int ret = -1; int ret = -1;
...@@ -905,7 +897,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, ...@@ -905,7 +897,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
/* Framepointer style */ /* Framepointer style */
if (!strncmp(name, "fp", sizeof("fp"))) { if (!strncmp(name, "fp", sizeof("fp"))) {
if (!strtok_r(NULL, ",", &saveptr)) { if (!strtok_r(NULL, ",", &saveptr)) {
rec->opts.call_graph = CALLCHAIN_FP; opts->call_graph = CALLCHAIN_FP;
ret = 0; ret = 0;
} else } else
pr_err("callchain: No more arguments " pr_err("callchain: No more arguments "
...@@ -918,20 +910,20 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, ...@@ -918,20 +910,20 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
const unsigned long default_stack_dump_size = 8192; const unsigned long default_stack_dump_size = 8192;
ret = 0; ret = 0;
rec->opts.call_graph = CALLCHAIN_DWARF; opts->call_graph = CALLCHAIN_DWARF;
rec->opts.stack_dump_size = default_stack_dump_size; opts->stack_dump_size = default_stack_dump_size;
tok = strtok_r(NULL, ",", &saveptr); tok = strtok_r(NULL, ",", &saveptr);
if (tok) { if (tok) {
unsigned long size = 0; unsigned long size = 0;
ret = get_stack_size(tok, &size); ret = get_stack_size(tok, &size);
rec->opts.stack_dump_size = size; opts->stack_dump_size = size;
} }
if (!ret) if (!ret)
pr_debug("callchain: stack dump size %d\n", pr_debug("callchain: stack dump size %d\n",
rec->opts.stack_dump_size); opts->stack_dump_size);
#endif /* LIBUNWIND_SUPPORT */ #endif /* LIBUNWIND_SUPPORT */
} else { } else {
pr_err("callchain: Unknown -g option " pr_err("callchain: Unknown -g option "
...@@ -944,7 +936,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, ...@@ -944,7 +936,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
free(buf); free(buf);
if (!ret) if (!ret)
pr_debug("callchain: type %d\n", rec->opts.call_graph); pr_debug("callchain: type %d\n", opts->call_graph);
return ret; return ret;
} }
...@@ -982,9 +974,9 @@ static struct perf_record record = { ...@@ -982,9 +974,9 @@ static struct perf_record record = {
#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
#ifdef LIBUNWIND_SUPPORT #ifdef LIBUNWIND_SUPPORT
static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
#else #else
static const char callchain_help[] = CALLCHAIN_HELP "[fp]"; const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
#endif #endif
/* /*
...@@ -1028,9 +1020,9 @@ const struct option record_options[] = { ...@@ -1028,9 +1020,9 @@ const struct option record_options[] = {
"number of mmap data pages"), "number of mmap data pages"),
OPT_BOOLEAN(0, "group", &record.opts.group, OPT_BOOLEAN(0, "group", &record.opts.group,
"put the counters into a counter group"), "put the counters into a counter group"),
OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]", OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
callchain_help, &parse_callchain_opt, "mode[,dump_size]", record_callchain_help,
"fp"), &record_parse_callchain_opt, "fp"),
OPT_INCR('v', "verbose", &verbose, OPT_INCR('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"), "be more verbose (show counter open errors, etc)"),
OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
......
...@@ -692,6 +692,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -692,6 +692,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
setup_browser(true); setup_browser(true);
else { else {
use_browser = 0; use_browser = 0;
perf_hpp__column_enable(PERF_HPP__OVERHEAD);
perf_hpp__init(); perf_hpp__init();
} }
......
...@@ -153,7 +153,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) ...@@ -153,7 +153,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
} }
if (!perf_target__has_task(&target) && if (!perf_target__has_task(&target) &&
!perf_evsel__is_group_member(evsel)) { perf_evsel__is_group_leader(evsel)) {
attr->disabled = 1; attr->disabled = 1;
attr->enable_on_exec = 1; attr->enable_on_exec = 1;
} }
......
This diff is collapsed.
...@@ -455,7 +455,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -455,7 +455,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto out_delete_evlist; goto out_delete_evlist;
} }
perf_evlist__config_attrs(evlist, &trace->opts); perf_evlist__config(evlist, &trace->opts);
signal(SIGCHLD, sig_handler); signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler); signal(SIGINT, sig_handler);
......
...@@ -7,7 +7,7 @@ size=96 ...@@ -7,7 +7,7 @@ size=96
config=0 config=0
sample_period=4000 sample_period=4000
sample_type=263 sample_type=263
read_format=7 read_format=0
disabled=1 disabled=1
inherit=1 inherit=1
pinned=0 pinned=0
......
...@@ -6,12 +6,14 @@ args = --group -e cycles,instructions kill >/dev/null 2>&1 ...@@ -6,12 +6,14 @@ args = --group -e cycles,instructions kill >/dev/null 2>&1
fd=1 fd=1
group_fd=-1 group_fd=-1
sample_type=327 sample_type=327
read_format=4
[event-2:base-record] [event-2:base-record]
fd=2 fd=2
group_fd=1 group_fd=1
config=1 config=1
sample_type=327 sample_type=327
read_format=4
mmap=0 mmap=0
comm=0 comm=0
enable_on_exec=0 enable_on_exec=0
......
...@@ -6,6 +6,7 @@ args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1 ...@@ -6,6 +6,7 @@ args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1
fd=1 fd=1
group_fd=-1 group_fd=-1
sample_type=327 sample_type=327
read_format=4
[event-2:base-record] [event-2:base-record]
fd=2 fd=2
...@@ -13,6 +14,7 @@ group_fd=1 ...@@ -13,6 +14,7 @@ group_fd=1
type=0 type=0
config=1 config=1
sample_type=327 sample_type=327
read_format=4
mmap=0 mmap=0
comm=0 comm=0
enable_on_exec=0 enable_on_exec=0
......
...@@ -22,36 +22,16 @@ int test__basic_mmap(void) ...@@ -22,36 +22,16 @@ int test__basic_mmap(void)
struct thread_map *threads; struct thread_map *threads;
struct cpu_map *cpus; struct cpu_map *cpus;
struct perf_evlist *evlist; struct perf_evlist *evlist;
struct perf_event_attr attr = {
.type = PERF_TYPE_TRACEPOINT,
.read_format = PERF_FORMAT_ID,
.sample_type = PERF_SAMPLE_ID,
.watermark = 0,
};
cpu_set_t cpu_set; cpu_set_t cpu_set;
const char *syscall_names[] = { "getsid", "getppid", "getpgrp", const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
"getpgid", }; "getpgid", };
pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp, pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
(void*)getpgid }; (void*)getpgid };
#define nsyscalls ARRAY_SIZE(syscall_names) #define nsyscalls ARRAY_SIZE(syscall_names)
int ids[nsyscalls];
unsigned int nr_events[nsyscalls], unsigned int nr_events[nsyscalls],
expected_nr_events[nsyscalls], i, j; expected_nr_events[nsyscalls], i, j;
struct perf_evsel *evsels[nsyscalls], *evsel; struct perf_evsel *evsels[nsyscalls], *evsel;
for (i = 0; i < nsyscalls; ++i) {
char name[64];
snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
ids[i] = trace_event__id(name);
if (ids[i] < 0) {
pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
return -1;
}
nr_events[i] = 0;
expected_nr_events[i] = random() % 257;
}
threads = thread_map__new(-1, getpid(), UINT_MAX); threads = thread_map__new(-1, getpid(), UINT_MAX);
if (threads == NULL) { if (threads == NULL) {
pr_debug("thread_map__new\n"); pr_debug("thread_map__new\n");
...@@ -79,18 +59,19 @@ int test__basic_mmap(void) ...@@ -79,18 +59,19 @@ int test__basic_mmap(void)
goto out_free_cpus; goto out_free_cpus;
} }
/* anonymous union fields, can't be initialized above */
attr.wakeup_events = 1;
attr.sample_period = 1;
for (i = 0; i < nsyscalls; ++i) { for (i = 0; i < nsyscalls; ++i) {
attr.config = ids[i]; char name[64];
evsels[i] = perf_evsel__new(&attr, i);
snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
evsels[i] = perf_evsel__newtp("syscalls", name, i);
if (evsels[i] == NULL) { if (evsels[i] == NULL) {
pr_debug("perf_evsel__new\n"); pr_debug("perf_evsel__new\n");
goto out_free_evlist; goto out_free_evlist;
} }
evsels[i]->attr.wakeup_events = 1;
perf_evsel__set_sample_id(evsels[i]);
perf_evlist__add(evlist, evsels[i]); perf_evlist__add(evlist, evsels[i]);
if (perf_evsel__open(evsels[i], cpus, threads) < 0) { if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
...@@ -99,6 +80,9 @@ int test__basic_mmap(void) ...@@ -99,6 +80,9 @@ int test__basic_mmap(void)
strerror(errno)); strerror(errno));
goto out_close_fd; goto out_close_fd;
} }
nr_events[i] = 0;
expected_nr_events[i] = 1 + rand() % 127;
} }
if (perf_evlist__mmap(evlist, 128, true) < 0) { if (perf_evlist__mmap(evlist, 128, true) < 0) {
...@@ -128,6 +112,7 @@ int test__basic_mmap(void) ...@@ -128,6 +112,7 @@ int test__basic_mmap(void)
goto out_munmap; goto out_munmap;
} }
err = -1;
evsel = perf_evlist__id2evsel(evlist, sample.id); evsel = perf_evlist__id2evsel(evlist, sample.id);
if (evsel == NULL) { if (evsel == NULL) {
pr_debug("event with id %" PRIu64 pr_debug("event with id %" PRIu64
...@@ -137,16 +122,17 @@ int test__basic_mmap(void) ...@@ -137,16 +122,17 @@ int test__basic_mmap(void)
nr_events[evsel->idx]++; nr_events[evsel->idx]++;
} }
err = 0;
list_for_each_entry(evsel, &evlist->entries, node) { list_for_each_entry(evsel, &evlist->entries, node) {
if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
pr_debug("expected %d %s events, got %d\n", pr_debug("expected %d %s events, got %d\n",
expected_nr_events[evsel->idx], expected_nr_events[evsel->idx],
perf_evsel__name(evsel), nr_events[evsel->idx]); perf_evsel__name(evsel), nr_events[evsel->idx]);
err = -1;
goto out_munmap; goto out_munmap;
} }
} }
err = 0;
out_munmap: out_munmap:
perf_evlist__munmap(evlist); perf_evlist__munmap(evlist);
out_close_fd: out_close_fd:
......
...@@ -7,20 +7,12 @@ ...@@ -7,20 +7,12 @@
int test__open_syscall_event_on_all_cpus(void) int test__open_syscall_event_on_all_cpus(void)
{ {
int err = -1, fd, cpu; int err = -1, fd, cpu;
struct thread_map *threads;
struct cpu_map *cpus; struct cpu_map *cpus;
struct perf_evsel *evsel; struct perf_evsel *evsel;
struct perf_event_attr attr;
unsigned int nr_open_calls = 111, i; unsigned int nr_open_calls = 111, i;
cpu_set_t cpu_set; cpu_set_t cpu_set;
int id = trace_event__id("sys_enter_open"); struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
if (id < 0) {
pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
return -1;
}
threads = thread_map__new(-1, getpid(), UINT_MAX);
if (threads == NULL) { if (threads == NULL) {
pr_debug("thread_map__new\n"); pr_debug("thread_map__new\n");
return -1; return -1;
...@@ -32,15 +24,11 @@ int test__open_syscall_event_on_all_cpus(void) ...@@ -32,15 +24,11 @@ int test__open_syscall_event_on_all_cpus(void)
goto out_thread_map_delete; goto out_thread_map_delete;
} }
CPU_ZERO(&cpu_set); CPU_ZERO(&cpu_set);
memset(&attr, 0, sizeof(attr)); evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
attr.type = PERF_TYPE_TRACEPOINT;
attr.config = id;
evsel = perf_evsel__new(&attr, 0);
if (evsel == NULL) { if (evsel == NULL) {
pr_debug("perf_evsel__new\n"); pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
goto out_thread_map_delete; goto out_thread_map_delete;
} }
......
...@@ -6,29 +6,18 @@ ...@@ -6,29 +6,18 @@
int test__open_syscall_event(void) int test__open_syscall_event(void)
{ {
int err = -1, fd; int err = -1, fd;
struct thread_map *threads;
struct perf_evsel *evsel; struct perf_evsel *evsel;
struct perf_event_attr attr;
unsigned int nr_open_calls = 111, i; unsigned int nr_open_calls = 111, i;
int id = trace_event__id("sys_enter_open"); struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
if (id < 0) {
pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
return -1;
}
threads = thread_map__new(-1, getpid(), UINT_MAX);
if (threads == NULL) { if (threads == NULL) {
pr_debug("thread_map__new\n"); pr_debug("thread_map__new\n");
return -1; return -1;
} }
memset(&attr, 0, sizeof(attr)); evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
attr.type = PERF_TYPE_TRACEPOINT;
attr.config = id;
evsel = perf_evsel__new(&attr, 0);
if (evsel == NULL) { if (evsel == NULL) {
pr_debug("perf_evsel__new\n"); pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
goto out_thread_map_delete; goto out_thread_map_delete;
} }
......
...@@ -521,7 +521,7 @@ static int test__group1(struct perf_evlist *evlist) ...@@ -521,7 +521,7 @@ static int test__group1(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
/* cycles:upp */ /* cycles:upp */
evsel = perf_evsel__next(evsel); evsel = perf_evsel__next(evsel);
...@@ -557,7 +557,7 @@ static int test__group2(struct perf_evlist *evlist) ...@@ -557,7 +557,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
/* cache-references + :u modifier */ /* cache-references + :u modifier */
evsel = perf_evsel__next(evsel); evsel = perf_evsel__next(evsel);
...@@ -583,7 +583,7 @@ static int test__group2(struct perf_evlist *evlist) ...@@ -583,7 +583,7 @@ static int test__group2(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
return 0; return 0;
} }
...@@ -606,7 +606,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) ...@@ -606,7 +606,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong group name", TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group1")); !strcmp(leader->group_name, "group1"));
...@@ -636,7 +636,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) ...@@ -636,7 +636,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
TEST_ASSERT_VAL("wrong group name", TEST_ASSERT_VAL("wrong group name",
!strcmp(leader->group_name, "group2")); !strcmp(leader->group_name, "group2"));
...@@ -663,7 +663,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) ...@@ -663,7 +663,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
return 0; return 0;
} }
...@@ -687,7 +687,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) ...@@ -687,7 +687,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
/* instructions:kp + p */ /* instructions:kp + p */
evsel = perf_evsel__next(evsel); evsel = perf_evsel__next(evsel);
...@@ -724,7 +724,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) ...@@ -724,7 +724,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
/* instructions + G */ /* instructions + G */
evsel = perf_evsel__next(evsel); evsel = perf_evsel__next(evsel);
...@@ -751,7 +751,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) ...@@ -751,7 +751,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong group name", !evsel->group_name); TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
/* instructions:G */ /* instructions:G */
evsel = perf_evsel__next(evsel); evsel = perf_evsel__next(evsel);
...@@ -777,7 +777,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) ...@@ -777,7 +777,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
return 0; return 0;
} }
......
...@@ -103,10 +103,10 @@ int test__PERF_RECORD(void) ...@@ -103,10 +103,10 @@ int test__PERF_RECORD(void)
* Config the evsels, setting attr->comm on the first one, etc. * Config the evsels, setting attr->comm on the first one, etc.
*/ */
evsel = perf_evlist__first(evlist); evsel = perf_evlist__first(evlist);
evsel->attr.sample_type |= PERF_SAMPLE_CPU; perf_evsel__set_sample_bit(evsel, CPU);
evsel->attr.sample_type |= PERF_SAMPLE_TID; perf_evsel__set_sample_bit(evsel, TID);
evsel->attr.sample_type |= PERF_SAMPLE_TIME; perf_evsel__set_sample_bit(evsel, TIME);
perf_evlist__config_attrs(evlist, &opts); perf_evlist__config(evlist, &opts);
err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
if (err < 0) { if (err < 0) {
......
...@@ -16,7 +16,4 @@ int test__attr(void); ...@@ -16,7 +16,4 @@ int test__attr(void);
int test__dso_data(void); int test__dso_data(void);
int test__parse_events(void); int test__parse_events(void);
/* Util */
int trace_event__id(const char *evname);
#endif /* TESTS_H */ #endif /* TESTS_H */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "tests.h"
#include "debugfs.h"
int trace_event__id(const char *evname)
{
char *filename;
int err = -1, fd;
if (asprintf(&filename,
"%s/syscalls/%s/id",
tracing_events_path, evname) < 0)
return -1;
fd = open(filename, O_RDONLY);
if (fd >= 0) {
char id[16];
if (read(fd, id, sizeof(id)) > 0)
err = atoi(id);
close(fd);
}
free(filename);
return err;
}
...@@ -587,6 +587,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us) ...@@ -587,6 +587,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
void hist_browser__init_hpp(void) void hist_browser__init_hpp(void)
{ {
perf_hpp__column_enable(PERF_HPP__OVERHEAD);
perf_hpp__init(); perf_hpp__init();
perf_hpp__format[PERF_HPP__OVERHEAD].color = perf_hpp__format[PERF_HPP__OVERHEAD].color =
...@@ -607,12 +609,13 @@ static int hist_browser__show_entry(struct hist_browser *browser, ...@@ -607,12 +609,13 @@ static int hist_browser__show_entry(struct hist_browser *browser,
{ {
char s[256]; char s[256];
double percent; double percent;
int i, printed = 0; int printed = 0;
int width = browser->b.width; int width = browser->b.width;
char folded_sign = ' '; char folded_sign = ' ';
bool current_entry = ui_browser__is_current_entry(&browser->b, row); bool current_entry = ui_browser__is_current_entry(&browser->b, row);
off_t row_offset = entry->row_offset; off_t row_offset = entry->row_offset;
bool first = true; bool first = true;
struct perf_hpp_fmt *fmt;
if (current_entry) { if (current_entry) {
browser->he_selection = entry; browser->he_selection = entry;
...@@ -629,12 +632,11 @@ static int hist_browser__show_entry(struct hist_browser *browser, ...@@ -629,12 +632,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
.buf = s, .buf = s,
.size = sizeof(s), .size = sizeof(s),
}; };
int i = 0;
ui_browser__gotorc(&browser->b, row, 0); ui_browser__gotorc(&browser->b, row, 0);
for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { perf_hpp__for_each_format(fmt) {
if (!perf_hpp__format[i].cond)
continue;
if (!first) { if (!first) {
slsmg_printf(" "); slsmg_printf(" ");
...@@ -642,14 +644,14 @@ static int hist_browser__show_entry(struct hist_browser *browser, ...@@ -642,14 +644,14 @@ static int hist_browser__show_entry(struct hist_browser *browser,
} }
first = false; first = false;
if (perf_hpp__format[i].color) { if (fmt->color) {
hpp.ptr = &percent; hpp.ptr = &percent;
/* It will set percent for us. See HPP__COLOR_FN above. */ /* It will set percent for us. See HPP__COLOR_FN above. */
width -= perf_hpp__format[i].color(&hpp, entry); width -= fmt->color(&hpp, entry);
ui_browser__set_percent_color(&browser->b, percent, current_entry); ui_browser__set_percent_color(&browser->b, percent, current_entry);
if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) { if (!i && symbol_conf.use_callchain) {
slsmg_printf("%c ", folded_sign); slsmg_printf("%c ", folded_sign);
width -= 2; width -= 2;
} }
...@@ -659,9 +661,11 @@ static int hist_browser__show_entry(struct hist_browser *browser, ...@@ -659,9 +661,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
if (!current_entry || !browser->b.navkeypressed) if (!current_entry || !browser->b.navkeypressed)
ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL); ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
} else { } else {
width -= perf_hpp__format[i].entry(&hpp, entry); width -= fmt->entry(&hpp, entry);
slsmg_printf("%s", s); slsmg_printf("%s", s);
} }
i++;
} }
/* The scroll bar isn't being used */ /* The scroll bar isn't being used */
......
...@@ -74,6 +74,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us) ...@@ -74,6 +74,8 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
void perf_gtk__init_hpp(void) void perf_gtk__init_hpp(void)
{ {
perf_hpp__column_enable(PERF_HPP__OVERHEAD);
perf_hpp__init(); perf_hpp__init();
perf_hpp__format[PERF_HPP__OVERHEAD].color = perf_hpp__format[PERF_HPP__OVERHEAD].color =
...@@ -90,13 +92,14 @@ void perf_gtk__init_hpp(void) ...@@ -90,13 +92,14 @@ void perf_gtk__init_hpp(void)
static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
{ {
struct perf_hpp_fmt *fmt;
GType col_types[MAX_COLUMNS]; GType col_types[MAX_COLUMNS];
GtkCellRenderer *renderer; GtkCellRenderer *renderer;
struct sort_entry *se; struct sort_entry *se;
GtkListStore *store; GtkListStore *store;
struct rb_node *nd; struct rb_node *nd;
GtkWidget *view; GtkWidget *view;
int i, col_idx; int col_idx;
int nr_cols; int nr_cols;
char s[512]; char s[512];
...@@ -107,12 +110,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) ...@@ -107,12 +110,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
nr_cols = 0; nr_cols = 0;
for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { perf_hpp__for_each_format(fmt)
if (!perf_hpp__format[i].cond)
continue;
col_types[nr_cols++] = G_TYPE_STRING; col_types[nr_cols++] = G_TYPE_STRING;
}
list_for_each_entry(se, &hist_entry__sort_list, list) { list_for_each_entry(se, &hist_entry__sort_list, list) {
if (se->elide) if (se->elide)
...@@ -129,12 +128,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) ...@@ -129,12 +128,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
col_idx = 0; col_idx = 0;
for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { perf_hpp__for_each_format(fmt) {
if (!perf_hpp__format[i].cond) fmt->header(&hpp);
continue;
perf_hpp__format[i].header(&hpp);
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
-1, s, -1, s,
renderer, "markup", renderer, "markup",
...@@ -166,14 +161,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) ...@@ -166,14 +161,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
col_idx = 0; col_idx = 0;
for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { perf_hpp__for_each_format(fmt) {
if (!perf_hpp__format[i].cond) if (fmt->color)
continue; fmt->color(&hpp, h);
if (perf_hpp__format[i].color)
perf_hpp__format[i].color(&hpp, h);
else else
perf_hpp__format[i].entry(&hpp, h); fmt->entry(&hpp, h);
gtk_list_store_set(store, &iter, col_idx++, s, -1); gtk_list_store_set(store, &iter, col_idx++, s, -1);
} }
......
...@@ -24,17 +24,7 @@ static void gtk_helpline_push(const char *msg) ...@@ -24,17 +24,7 @@ static void gtk_helpline_push(const char *msg)
pgctx->statbar_ctx_id, msg); pgctx->statbar_ctx_id, msg);
} }
static struct ui_helpline gtk_helpline_fns = { static int gtk_helpline_show(const char *fmt, va_list ap)
.pop = gtk_helpline_pop,
.push = gtk_helpline_push,
};
void perf_gtk__init_helpline(void)
{
helpline_fns = &gtk_helpline_fns;
}
int perf_gtk__show_helpline(const char *fmt, va_list ap)
{ {
int ret; int ret;
char *ptr; char *ptr;
...@@ -54,3 +44,14 @@ int perf_gtk__show_helpline(const char *fmt, va_list ap) ...@@ -54,3 +44,14 @@ int perf_gtk__show_helpline(const char *fmt, va_list ap)
return ret; return ret;
} }
static struct ui_helpline gtk_helpline_fns = {
.pop = gtk_helpline_pop,
.push = gtk_helpline_push,
.show = gtk_helpline_show,
};
void perf_gtk__init_helpline(void)
{
helpline_fns = &gtk_helpline_fns;
}
...@@ -16,9 +16,16 @@ static void nop_helpline__push(const char *msg __maybe_unused) ...@@ -16,9 +16,16 @@ static void nop_helpline__push(const char *msg __maybe_unused)
{ {
} }
static int nop_helpline__show(const char *fmt __maybe_unused,
va_list ap __maybe_unused)
{
return 0;
}
static struct ui_helpline default_helpline_fns = { static struct ui_helpline default_helpline_fns = {
.pop = nop_helpline__pop, .pop = nop_helpline__pop,
.push = nop_helpline__push, .push = nop_helpline__push,
.show = nop_helpline__show,
}; };
struct ui_helpline *helpline_fns = &default_helpline_fns; struct ui_helpline *helpline_fns = &default_helpline_fns;
...@@ -59,3 +66,8 @@ void ui_helpline__puts(const char *msg) ...@@ -59,3 +66,8 @@ void ui_helpline__puts(const char *msg)
ui_helpline__pop(); ui_helpline__pop();
ui_helpline__push(msg); ui_helpline__push(msg);
} }
int ui_helpline__vshow(const char *fmt, va_list ap)
{
return helpline_fns->show(fmt, ap);
}
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
struct ui_helpline { struct ui_helpline {
void (*pop)(void); void (*pop)(void);
void (*push)(const char *msg); void (*push)(const char *msg);
int (*show)(const char *fmt, va_list ap);
}; };
extern struct ui_helpline *helpline_fns; extern struct ui_helpline *helpline_fns;
...@@ -20,28 +21,9 @@ void ui_helpline__push(const char *msg); ...@@ -20,28 +21,9 @@ void ui_helpline__push(const char *msg);
void ui_helpline__vpush(const char *fmt, va_list ap); void ui_helpline__vpush(const char *fmt, va_list ap);
void ui_helpline__fpush(const char *fmt, ...); void ui_helpline__fpush(const char *fmt, ...);
void ui_helpline__puts(const char *msg); void ui_helpline__puts(const char *msg);
int ui_helpline__vshow(const char *fmt, va_list ap);
extern char ui_helpline__current[512]; extern char ui_helpline__current[512];
#ifdef NEWT_SUPPORT
extern char ui_helpline__last_msg[]; extern char ui_helpline__last_msg[];
int ui_helpline__show_help(const char *format, va_list ap);
#else
static inline int ui_helpline__show_help(const char *format __maybe_unused,
va_list ap __maybe_unused)
{
return 0;
}
#endif /* NEWT_SUPPORT */
#ifdef GTK2_SUPPORT
int perf_gtk__show_helpline(const char *format, va_list ap);
#else
static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
va_list ap __maybe_unused)
{
return 0;
}
#endif /* GTK2_SUPPORT */
#endif /* _PERF_UI_HELPLINE_H_ */ #endif /* _PERF_UI_HELPLINE_H_ */
...@@ -268,14 +268,18 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) ...@@ -268,14 +268,18 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
char buf[32] = " "; char buf[32] = " ";
double diff; double diff = 0.0;
if (he->diff.computed) if (pair) {
diff = he->diff.period_ratio_delta; if (he->diff.computed)
else diff = he->diff.period_ratio_delta;
diff = perf_diff__compute_delta(he); else
diff = perf_diff__compute_delta(he, pair);
} else
diff = perf_diff__period_percent(he, he->stat.period);
if (fabs(diff) >= 0.01) if (fabs(diff) >= 0.01)
scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
...@@ -297,14 +301,17 @@ static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused) ...@@ -297,14 +301,17 @@ static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he) static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
char buf[32] = " "; char buf[32] = " ";
double ratio; double ratio = 0.0;
if (he->diff.computed) if (pair) {
ratio = he->diff.period_ratio; if (he->diff.computed)
else ratio = he->diff.period_ratio;
ratio = perf_diff__compute_ratio(he); else
ratio = perf_diff__compute_ratio(he, pair);
}
if (ratio > 0.0) if (ratio > 0.0)
scnprintf(buf, sizeof(buf), "%+14.6F", ratio); scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
...@@ -326,14 +333,17 @@ static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused) ...@@ -326,14 +333,17 @@ static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he) static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
char buf[32] = " "; char buf[32] = " ";
s64 wdiff; s64 wdiff = 0;
if (he->diff.computed) if (pair) {
wdiff = he->diff.wdiff; if (he->diff.computed)
else wdiff = he->diff.wdiff;
wdiff = perf_diff__compute_wdiff(he); else
wdiff = perf_diff__compute_wdiff(he, pair);
}
if (wdiff != 0) if (wdiff != 0)
scnprintf(buf, sizeof(buf), "%14ld", wdiff); scnprintf(buf, sizeof(buf), "%14ld", wdiff);
...@@ -341,30 +351,6 @@ static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he) ...@@ -341,30 +351,6 @@ static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
return scnprintf(hpp->buf, hpp->size, fmt, buf); return scnprintf(hpp->buf, hpp->size, fmt, buf);
} }
static int hpp__header_displ(struct perf_hpp *hpp)
{
return scnprintf(hpp->buf, hpp->size, "Displ.");
}
static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
{
return 6;
}
static int hpp__entry_displ(struct perf_hpp *hpp,
struct hist_entry *he)
{
struct hist_entry *pair = hist_entry__next_pair(he);
long displacement = pair ? pair->position - he->position : 0;
const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
char buf[32] = " ";
if (displacement)
scnprintf(buf, sizeof(buf), "%+4ld", displacement);
return scnprintf(hpp->buf, hpp->size, fmt, buf);
}
static int hpp__header_formula(struct perf_hpp *hpp) static int hpp__header_formula(struct perf_hpp *hpp)
{ {
const char *fmt = symbol_conf.field_sep ? "%s" : "%70s"; const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
...@@ -379,67 +365,80 @@ static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused) ...@@ -379,67 +365,80 @@ static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he) static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
{ {
struct hist_entry *pair = hist_entry__next_pair(he);
const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s"; const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
char buf[96] = " "; char buf[96] = " ";
perf_diff__formula(buf, sizeof(buf), he); if (pair)
perf_diff__formula(he, pair, buf, sizeof(buf));
return scnprintf(hpp->buf, hpp->size, fmt, buf); return scnprintf(hpp->buf, hpp->size, fmt, buf);
} }
#define HPP__COLOR_PRINT_FNS(_name) \ #define HPP__COLOR_PRINT_FNS(_name) \
.header = hpp__header_ ## _name, \ { \
.width = hpp__width_ ## _name, \ .header = hpp__header_ ## _name, \
.color = hpp__color_ ## _name, \ .width = hpp__width_ ## _name, \
.entry = hpp__entry_ ## _name .color = hpp__color_ ## _name, \
.entry = hpp__entry_ ## _name \
}
#define HPP__PRINT_FNS(_name) \ #define HPP__PRINT_FNS(_name) \
.header = hpp__header_ ## _name, \ { \
.width = hpp__width_ ## _name, \ .header = hpp__header_ ## _name, \
.entry = hpp__entry_ ## _name .width = hpp__width_ ## _name, \
.entry = hpp__entry_ ## _name \
}
struct perf_hpp_fmt perf_hpp__format[] = { struct perf_hpp_fmt perf_hpp__format[] = {
{ .cond = false, HPP__COLOR_PRINT_FNS(baseline) }, HPP__COLOR_PRINT_FNS(baseline),
{ .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, HPP__COLOR_PRINT_FNS(overhead),
{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, HPP__COLOR_PRINT_FNS(overhead_sys),
{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, HPP__COLOR_PRINT_FNS(overhead_us),
{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) }, HPP__COLOR_PRINT_FNS(overhead_guest_sys),
{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) }, HPP__COLOR_PRINT_FNS(overhead_guest_us),
{ .cond = false, HPP__PRINT_FNS(samples) }, HPP__PRINT_FNS(samples),
{ .cond = false, HPP__PRINT_FNS(period) }, HPP__PRINT_FNS(period),
{ .cond = false, HPP__PRINT_FNS(period_baseline) }, HPP__PRINT_FNS(period_baseline),
{ .cond = false, HPP__PRINT_FNS(delta) }, HPP__PRINT_FNS(delta),
{ .cond = false, HPP__PRINT_FNS(ratio) }, HPP__PRINT_FNS(ratio),
{ .cond = false, HPP__PRINT_FNS(wdiff) }, HPP__PRINT_FNS(wdiff),
{ .cond = false, HPP__PRINT_FNS(displ) }, HPP__PRINT_FNS(formula)
{ .cond = false, HPP__PRINT_FNS(formula) }
}; };
LIST_HEAD(perf_hpp__list);
#undef HPP__COLOR_PRINT_FNS #undef HPP__COLOR_PRINT_FNS
#undef HPP__PRINT_FNS #undef HPP__PRINT_FNS
void perf_hpp__init(void) void perf_hpp__init(void)
{ {
if (symbol_conf.show_cpu_utilization) { if (symbol_conf.show_cpu_utilization) {
perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS);
perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true; perf_hpp__column_enable(PERF_HPP__OVERHEAD_US);
if (perf_guest) { if (perf_guest) {
perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true; perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS);
perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true; perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US);
} }
} }
if (symbol_conf.show_nr_samples) if (symbol_conf.show_nr_samples)
perf_hpp__format[PERF_HPP__SAMPLES].cond = true; perf_hpp__column_enable(PERF_HPP__SAMPLES);
if (symbol_conf.show_total_period) if (symbol_conf.show_total_period)
perf_hpp__format[PERF_HPP__PERIOD].cond = true; perf_hpp__column_enable(PERF_HPP__PERIOD);
}
void perf_hpp__column_register(struct perf_hpp_fmt *format)
{
list_add_tail(&format->list, &perf_hpp__list);
} }
void perf_hpp__column_enable(unsigned col, bool enable) void perf_hpp__column_enable(unsigned col)
{ {
BUG_ON(col >= PERF_HPP__MAX_INDEX); BUG_ON(col >= PERF_HPP__MAX_INDEX);
perf_hpp__format[col].cond = enable; perf_hpp__column_register(&perf_hpp__format[col]);
} }
static inline void advance_hpp(struct perf_hpp *hpp, int inc) static inline void advance_hpp(struct perf_hpp *hpp, int inc)
...@@ -452,27 +451,29 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, ...@@ -452,27 +451,29 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
bool color) bool color)
{ {
const char *sep = symbol_conf.field_sep; const char *sep = symbol_conf.field_sep;
struct perf_hpp_fmt *fmt;
char *start = hpp->buf; char *start = hpp->buf;
int i, ret; int ret;
bool first = true; bool first = true;
if (symbol_conf.exclude_other && !he->parent) if (symbol_conf.exclude_other && !he->parent)
return 0; return 0;
for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { perf_hpp__for_each_format(fmt) {
if (!perf_hpp__format[i].cond) /*
continue; * If there's no field_sep, we still need
* to display initial ' '.
*/
if (!sep || !first) { if (!sep || !first) {
ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
advance_hpp(hpp, ret); advance_hpp(hpp, ret);
} else
first = false; first = false;
}
if (color && perf_hpp__format[i].color) if (color && fmt->color)
ret = perf_hpp__format[i].color(hpp, he); ret = fmt->color(hpp, he);
else else
ret = perf_hpp__format[i].entry(hpp, he); ret = fmt->entry(hpp, he);
advance_hpp(hpp, ret); advance_hpp(hpp, ret);
} }
...@@ -504,16 +505,15 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, ...@@ -504,16 +505,15 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
*/ */
unsigned int hists__sort_list_width(struct hists *hists) unsigned int hists__sort_list_width(struct hists *hists)
{ {
struct perf_hpp_fmt *fmt;
struct sort_entry *se; struct sort_entry *se;
int i, ret = 0; int i = 0, ret = 0;
for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { perf_hpp__for_each_format(fmt) {
if (!perf_hpp__format[i].cond)
continue;
if (i) if (i)
ret += 2; ret += 2;
ret += perf_hpp__format[i].width(NULL); ret += fmt->width(NULL);
} }
list_for_each_entry(se, &hist_entry__sort_list, list) list_for_each_entry(se, &hist_entry__sort_list, list)
......
...@@ -30,6 +30,7 @@ void setup_browser(bool fallback_to_pager) ...@@ -30,6 +30,7 @@ void setup_browser(bool fallback_to_pager)
if (fallback_to_pager) if (fallback_to_pager)
setup_pager(); setup_pager();
perf_hpp__column_enable(PERF_HPP__OVERHEAD);
perf_hpp__init(); perf_hpp__init();
break; break;
} }
......
...@@ -335,13 +335,14 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, ...@@ -335,13 +335,14 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
int max_cols, FILE *fp) int max_cols, FILE *fp)
{ {
struct perf_hpp_fmt *fmt;
struct sort_entry *se; struct sort_entry *se;
struct rb_node *nd; struct rb_node *nd;
size_t ret = 0; size_t ret = 0;
unsigned int width; unsigned int width;
const char *sep = symbol_conf.field_sep; const char *sep = symbol_conf.field_sep;
const char *col_width = symbol_conf.col_width_list_str; const char *col_width = symbol_conf.col_width_list_str;
int idx, nr_rows = 0; int nr_rows = 0;
char bf[96]; char bf[96];
struct perf_hpp dummy_hpp = { struct perf_hpp dummy_hpp = {
.buf = bf, .buf = bf,
...@@ -355,16 +356,14 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, ...@@ -355,16 +356,14 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
goto print_entries; goto print_entries;
fprintf(fp, "# "); fprintf(fp, "# ");
for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
if (!perf_hpp__format[idx].cond)
continue;
perf_hpp__for_each_format(fmt) {
if (!first) if (!first)
fprintf(fp, "%s", sep ?: " "); fprintf(fp, "%s", sep ?: " ");
else else
first = false; first = false;
perf_hpp__format[idx].header(&dummy_hpp); fmt->header(&dummy_hpp);
fprintf(fp, "%s", bf); fprintf(fp, "%s", bf);
} }
...@@ -400,18 +399,16 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, ...@@ -400,18 +399,16 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
first = true; first = true;
fprintf(fp, "# "); fprintf(fp, "# ");
for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
unsigned int i;
if (!perf_hpp__format[idx].cond) perf_hpp__for_each_format(fmt) {
continue; unsigned int i;
if (!first) if (!first)
fprintf(fp, "%s", sep ?: " "); fprintf(fp, "%s", sep ?: " ");
else else
first = false; first = false;
width = perf_hpp__format[idx].width(&dummy_hpp); width = fmt->width(&dummy_hpp);
for (i = 0; i < width; i++) for (i = 0; i < width; i++)
fprintf(fp, "."); fprintf(fp, ".");
} }
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "../ui.h" #include "../ui.h"
#include "../libslang.h" #include "../libslang.h"
char ui_helpline__last_msg[1024];
static void tui_helpline__pop(void) static void tui_helpline__pop(void)
{ {
} }
...@@ -23,20 +25,7 @@ static void tui_helpline__push(const char *msg) ...@@ -23,20 +25,7 @@ static void tui_helpline__push(const char *msg)
strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0';
} }
struct ui_helpline tui_helpline_fns = { static int tui_helpline__show(const char *format, va_list ap)
.pop = tui_helpline__pop,
.push = tui_helpline__push,
};
void ui_helpline__init(void)
{
helpline_fns = &tui_helpline_fns;
ui_helpline__puts(" ");
}
char ui_helpline__last_msg[1024];
int ui_helpline__show_help(const char *format, va_list ap)
{ {
int ret; int ret;
static int backlog; static int backlog;
...@@ -55,3 +44,15 @@ int ui_helpline__show_help(const char *format, va_list ap) ...@@ -55,3 +44,15 @@ int ui_helpline__show_help(const char *format, va_list ap)
return ret; return ret;
} }
struct ui_helpline tui_helpline_fns = {
.pop = tui_helpline__pop,
.push = tui_helpline__push,
.show = tui_helpline__show,
};
void ui_helpline__init(void)
{
helpline_fns = &tui_helpline_fns;
ui_helpline__puts(" ");
}
...@@ -52,6 +52,16 @@ int ui__warning(const char *format, ...) ...@@ -52,6 +52,16 @@ int ui__warning(const char *format, ...)
return ret; return ret;
} }
int ui__error_paranoid(void)
{
return ui__error("Permission error - are you root?\n"
"Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
" -1 - Not paranoid at all\n"
" 0 - Disallow raw tracepoint access for unpriv\n"
" 1 - Disallow cpu events for unpriv\n"
" 2 - Disallow kernel profiling for unpriv\n");
}
/** /**
* perf_error__register - Register error logging functions * perf_error__register - Register error logging functions
......
...@@ -143,4 +143,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor) ...@@ -143,4 +143,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
cursor->curr = cursor->curr->next; cursor->curr = cursor->curr->next;
cursor->pos++; cursor->pos++;
} }
struct option;
int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
extern const char record_callchain_help[];
#endif /* __PERF_CALLCHAIN_H */ #endif /* __PERF_CALLCHAIN_H */
...@@ -23,10 +23,8 @@ int eprintf(int level, const char *fmt, ...) ...@@ -23,10 +23,8 @@ int eprintf(int level, const char *fmt, ...)
if (verbose >= level) { if (verbose >= level) {
va_start(args, fmt); va_start(args, fmt);
if (use_browser == 1) if (use_browser >= 1)
ret = ui_helpline__show_help(fmt, args); ui_helpline__vshow(fmt, args);
else if (use_browser == 2)
ret = perf_gtk__show_helpline(fmt, args);
else else
ret = vfprintf(stderr, fmt, args); ret = vfprintf(stderr, fmt, args);
va_end(args); va_end(args);
...@@ -49,28 +47,6 @@ int dump_printf(const char *fmt, ...) ...@@ -49,28 +47,6 @@ int dump_printf(const char *fmt, ...)
return ret; return ret;
} }
#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
int ui__warning(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
return 0;
}
#endif
int ui__error_paranoid(void)
{
return ui__error("Permission error - are you root?\n"
"Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
" -1 - Not paranoid at all\n"
" 0 - Disallow raw tracepoint access for unpriv\n"
" 1 - Disallow cpu events for unpriv\n"
" 2 - Disallow kernel profiling for unpriv\n");
}
void trace_event(union perf_event *event) void trace_event(union perf_event *event)
{ {
unsigned char *raw_event = (void *)event; unsigned char *raw_event = (void *)event;
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <stdbool.h> #include <stdbool.h>
#include "event.h" #include "event.h"
#include "../ui/helpline.h" #include "../ui/helpline.h"
#include "../ui/progress.h"
#include "../ui/util.h"
extern int verbose; extern int verbose;
extern bool quiet, dump_trace; extern bool quiet, dump_trace;
...@@ -12,38 +14,7 @@ extern bool quiet, dump_trace; ...@@ -12,38 +14,7 @@ extern bool quiet, dump_trace;
int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void trace_event(union perf_event *event); void trace_event(union perf_event *event);
struct ui_progress;
struct perf_error_ops;
#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
#include "../ui/progress.h"
int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
#include "../ui/util.h"
#else
static inline void ui_progress__update(u64 curr __maybe_unused,
u64 total __maybe_unused,
const char *title __maybe_unused) {}
static inline void ui_progress__finish(void) {}
#define ui__error(format, arg...) ui__warning(format, ##arg)
static inline int
perf_error__register(struct perf_error_ops *eops __maybe_unused)
{
return 0;
}
static inline int
perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
{
return 0;
}
#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
int ui__error_paranoid(void); int ui__error_paranoid(void);
......
...@@ -539,13 +539,13 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name) ...@@ -539,13 +539,13 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name)
} }
size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
bool with_hits) bool (skip)(struct dso *dso, int parm), int parm)
{ {
struct dso *pos; struct dso *pos;
size_t ret = 0; size_t ret = 0;
list_for_each_entry(pos, head, node) { list_for_each_entry(pos, head, node) {
if (with_hits && !pos->hit) if (skip && skip(pos, parm))
continue; continue;
ret += dso__fprintf_buildid(pos, fp); ret += dso__fprintf_buildid(pos, fp);
ret += fprintf(fp, " %s\n", pos->long_name); ret += fprintf(fp, " %s\n", pos->long_name);
...@@ -583,7 +583,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) ...@@ -583,7 +583,7 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
if (dso->short_name != dso->long_name) if (dso->short_name != dso->long_name)
ret += fprintf(fp, "%s, ", dso->long_name); ret += fprintf(fp, "%s, ", dso->long_name);
ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type], ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
dso->loaded ? "" : "NOT "); dso__loaded(dso, type) ? "" : "NOT ");
ret += dso__fprintf_buildid(dso, fp); ret += dso__fprintf_buildid(dso, fp);
ret += fprintf(fp, ")\n"); ret += fprintf(fp, ")\n");
for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) { for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
......
...@@ -138,7 +138,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name); ...@@ -138,7 +138,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name);
bool __dsos__read_build_ids(struct list_head *head, bool with_hits); bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
bool with_hits); bool (skip)(struct dso *dso, int parm), int parm);
size_t __dsos__fprintf(struct list_head *head, FILE *fp); size_t __dsos__fprintf(struct list_head *head, FILE *fp);
size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
......
...@@ -49,10 +49,16 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, ...@@ -49,10 +49,16 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
return evlist; return evlist;
} }
void perf_evlist__config_attrs(struct perf_evlist *evlist, void perf_evlist__config(struct perf_evlist *evlist,
struct perf_record_opts *opts) struct perf_record_opts *opts)
{ {
struct perf_evsel *evsel; struct perf_evsel *evsel;
/*
* Set the evsel leader links before we configure attributes,
* since some might depend on this info.
*/
if (opts->group)
perf_evlist__set_leader(evlist);
if (evlist->cpus->map[0] < 0) if (evlist->cpus->map[0] < 0)
opts->no_inherit = true; opts->no_inherit = true;
...@@ -61,7 +67,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist, ...@@ -61,7 +67,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist,
perf_evsel__config(evsel, opts); perf_evsel__config(evsel, opts);
if (evlist->nr_entries > 1) if (evlist->nr_entries > 1)
evsel->attr.sample_type |= PERF_SAMPLE_ID; perf_evsel__set_sample_id(evsel);
} }
} }
...@@ -111,7 +117,6 @@ void __perf_evlist__set_leader(struct list_head *list) ...@@ -111,7 +117,6 @@ void __perf_evlist__set_leader(struct list_head *list)
struct perf_evsel *evsel, *leader; struct perf_evsel *evsel, *leader;
leader = list_entry(list->next, struct perf_evsel, node); leader = list_entry(list->next, struct perf_evsel, node);
leader->leader = NULL;
list_for_each_entry(evsel, list, node) { list_for_each_entry(evsel, list, node) {
if (evsel != leader) if (evsel != leader)
...@@ -222,7 +227,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) ...@@ -222,7 +227,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) { list_for_each_entry(pos, &evlist->entries, node) {
if (perf_evsel__is_group_member(pos)) if (!perf_evsel__is_group_leader(pos))
continue; continue;
for (thread = 0; thread < evlist->threads->nr; thread++) for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread), ioctl(FD(pos, cpu, thread),
...@@ -238,7 +243,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) ...@@ -238,7 +243,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) { for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
list_for_each_entry(pos, &evlist->entries, node) { list_for_each_entry(pos, &evlist->entries, node) {
if (perf_evsel__is_group_member(pos)) if (!perf_evsel__is_group_leader(pos))
continue; continue;
for (thread = 0; thread < evlist->threads->nr; thread++) for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread), ioctl(FD(pos, cpu, thread),
......
...@@ -76,8 +76,8 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); ...@@ -76,8 +76,8 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
int perf_evlist__open(struct perf_evlist *evlist); int perf_evlist__open(struct perf_evlist *evlist);
void perf_evlist__config_attrs(struct perf_evlist *evlist, void perf_evlist__config(struct perf_evlist *evlist,
struct perf_record_opts *opts); struct perf_record_opts *opts);
int perf_evlist__prepare_workload(struct perf_evlist *evlist, int perf_evlist__prepare_workload(struct perf_evlist *evlist,
struct perf_record_opts *opts, struct perf_record_opts *opts,
......
...@@ -50,11 +50,36 @@ void hists__init(struct hists *hists) ...@@ -50,11 +50,36 @@ void hists__init(struct hists *hists)
pthread_mutex_init(&hists->lock, NULL); pthread_mutex_init(&hists->lock, NULL);
} }
void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
enum perf_event_sample_format bit)
{
if (!(evsel->attr.sample_type & bit)) {
evsel->attr.sample_type |= bit;
evsel->sample_size += sizeof(u64);
}
}
void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
enum perf_event_sample_format bit)
{
if (evsel->attr.sample_type & bit) {
evsel->attr.sample_type &= ~bit;
evsel->sample_size -= sizeof(u64);
}
}
void perf_evsel__set_sample_id(struct perf_evsel *evsel)
{
perf_evsel__set_sample_bit(evsel, ID);
evsel->attr.read_format |= PERF_FORMAT_ID;
}
void perf_evsel__init(struct perf_evsel *evsel, void perf_evsel__init(struct perf_evsel *evsel,
struct perf_event_attr *attr, int idx) struct perf_event_attr *attr, int idx)
{ {
evsel->idx = idx; evsel->idx = idx;
evsel->attr = *attr; evsel->attr = *attr;
evsel->leader = evsel;
INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->node);
hists__init(&evsel->hists); hists__init(&evsel->hists);
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
...@@ -440,11 +465,9 @@ void perf_evsel__config(struct perf_evsel *evsel, ...@@ -440,11 +465,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
attr->inherit = !opts->no_inherit; attr->inherit = !opts->no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING |
PERF_FORMAT_ID;
attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; perf_evsel__set_sample_bit(evsel, IP);
perf_evsel__set_sample_bit(evsel, TID);
/* /*
* We default some events to a 1 default interval. But keep * We default some events to a 1 default interval. But keep
...@@ -453,7 +476,7 @@ void perf_evsel__config(struct perf_evsel *evsel, ...@@ -453,7 +476,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
if (!attr->sample_period || (opts->user_freq != UINT_MAX && if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
opts->user_interval != ULLONG_MAX)) { opts->user_interval != ULLONG_MAX)) {
if (opts->freq) { if (opts->freq) {
attr->sample_type |= PERF_SAMPLE_PERIOD; perf_evsel__set_sample_bit(evsel, PERIOD);
attr->freq = 1; attr->freq = 1;
attr->sample_freq = opts->freq; attr->sample_freq = opts->freq;
} else { } else {
...@@ -468,16 +491,16 @@ void perf_evsel__config(struct perf_evsel *evsel, ...@@ -468,16 +491,16 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->inherit_stat = 1; attr->inherit_stat = 1;
if (opts->sample_address) { if (opts->sample_address) {
attr->sample_type |= PERF_SAMPLE_ADDR; perf_evsel__set_sample_bit(evsel, ADDR);
attr->mmap_data = track; attr->mmap_data = track;
} }
if (opts->call_graph) { if (opts->call_graph) {
attr->sample_type |= PERF_SAMPLE_CALLCHAIN; perf_evsel__set_sample_bit(evsel, CALLCHAIN);
if (opts->call_graph == CALLCHAIN_DWARF) { if (opts->call_graph == CALLCHAIN_DWARF) {
attr->sample_type |= PERF_SAMPLE_REGS_USER | perf_evsel__set_sample_bit(evsel, REGS_USER);
PERF_SAMPLE_STACK_USER; perf_evsel__set_sample_bit(evsel, STACK_USER);
attr->sample_regs_user = PERF_REGS_MASK; attr->sample_regs_user = PERF_REGS_MASK;
attr->sample_stack_user = opts->stack_dump_size; attr->sample_stack_user = opts->stack_dump_size;
attr->exclude_callchain_user = 1; attr->exclude_callchain_user = 1;
...@@ -485,20 +508,20 @@ void perf_evsel__config(struct perf_evsel *evsel, ...@@ -485,20 +508,20 @@ void perf_evsel__config(struct perf_evsel *evsel,
} }
if (perf_target__has_cpu(&opts->target)) if (perf_target__has_cpu(&opts->target))
attr->sample_type |= PERF_SAMPLE_CPU; perf_evsel__set_sample_bit(evsel, CPU);
if (opts->period) if (opts->period)
attr->sample_type |= PERF_SAMPLE_PERIOD; perf_evsel__set_sample_bit(evsel, PERIOD);
if (!opts->sample_id_all_missing && if (!opts->sample_id_all_missing &&
(opts->sample_time || !opts->no_inherit || (opts->sample_time || !opts->no_inherit ||
perf_target__has_cpu(&opts->target))) perf_target__has_cpu(&opts->target)))
attr->sample_type |= PERF_SAMPLE_TIME; perf_evsel__set_sample_bit(evsel, TIME);
if (opts->raw_samples) { if (opts->raw_samples) {
attr->sample_type |= PERF_SAMPLE_TIME; perf_evsel__set_sample_bit(evsel, TIME);
attr->sample_type |= PERF_SAMPLE_RAW; perf_evsel__set_sample_bit(evsel, RAW);
attr->sample_type |= PERF_SAMPLE_CPU; perf_evsel__set_sample_bit(evsel, CPU);
} }
if (opts->no_delay) { if (opts->no_delay) {
...@@ -506,7 +529,7 @@ void perf_evsel__config(struct perf_evsel *evsel, ...@@ -506,7 +529,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
attr->wakeup_events = 1; attr->wakeup_events = 1;
} }
if (opts->branch_stack) { if (opts->branch_stack) {
attr->sample_type |= PERF_SAMPLE_BRANCH_STACK; perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
attr->branch_sample_type = opts->branch_stack; attr->branch_sample_type = opts->branch_stack;
} }
...@@ -519,14 +542,14 @@ void perf_evsel__config(struct perf_evsel *evsel, ...@@ -519,14 +542,14 @@ void perf_evsel__config(struct perf_evsel *evsel,
* Disabling only independent events or group leaders, * Disabling only independent events or group leaders,
* keeping group members enabled. * keeping group members enabled.
*/ */
if (!perf_evsel__is_group_member(evsel)) if (perf_evsel__is_group_leader(evsel))
attr->disabled = 1; attr->disabled = 1;
/* /*
* Setting enable_on_exec for independent events and * Setting enable_on_exec for independent events and
* group leaders for traced executed by perf. * group leaders for traced executed by perf.
*/ */
if (perf_target__none(&opts->target) && !perf_evsel__is_group_member(evsel)) if (perf_target__none(&opts->target) && perf_evsel__is_group_leader(evsel))
attr->enable_on_exec = 1; attr->enable_on_exec = 1;
} }
...@@ -707,7 +730,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) ...@@ -707,7 +730,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
struct perf_evsel *leader = evsel->leader; struct perf_evsel *leader = evsel->leader;
int fd; int fd;
if (!perf_evsel__is_group_member(evsel)) if (perf_evsel__is_group_leader(evsel))
return -1; return -1;
/* /*
...@@ -1205,3 +1228,128 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, ...@@ -1205,3 +1228,128 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
return 0; return 0;
} }
static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
{
va_list args;
int ret = 0;
if (!*first) {
ret += fprintf(fp, ",");
} else {
ret += fprintf(fp, ":");
*first = false;
}
va_start(args, fmt);
ret += vfprintf(fp, fmt, args);
va_end(args);
return ret;
}
static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value)
{
if (value == 0)
return 0;
return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
}
#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
struct bit_names {
int bit;
const char *name;
};
static int bits__fprintf(FILE *fp, const char *field, u64 value,
struct bit_names *bits, bool *first)
{
int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
bool first_bit = true;
do {
if (value & bits[i].bit) {
printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
first_bit = false;
}
} while (bits[++i].name != NULL);
return printed;
}
static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
{
#define bit_name(n) { PERF_SAMPLE_##n, #n }
struct bit_names bits[] = {
bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
{ .name = NULL, }
};
#undef bit_name
return bits__fprintf(fp, "sample_type", value, bits, first);
}
static int read_format__fprintf(FILE *fp, bool *first, u64 value)
{
#define bit_name(n) { PERF_FORMAT_##n, #n }
struct bit_names bits[] = {
bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
bit_name(ID), bit_name(GROUP),
{ .name = NULL, }
};
#undef bit_name
return bits__fprintf(fp, "read_format", value, bits, first);
}
int perf_evsel__fprintf(struct perf_evsel *evsel,
struct perf_attr_details *details, FILE *fp)
{
bool first = true;
int printed = fprintf(fp, "%s", perf_evsel__name(evsel));
if (details->verbose || details->freq) {
printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
(u64)evsel->attr.sample_freq);
}
if (details->verbose) {
if_print(type);
if_print(config);
if_print(config1);
if_print(config2);
if_print(size);
printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
if (evsel->attr.read_format)
printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
if_print(disabled);
if_print(inherit);
if_print(pinned);
if_print(exclusive);
if_print(exclude_user);
if_print(exclude_kernel);
if_print(exclude_hv);
if_print(exclude_idle);
if_print(mmap);
if_print(comm);
if_print(freq);
if_print(inherit_stat);
if_print(enable_on_exec);
if_print(task);
if_print(watermark);
if_print(precise_ip);
if_print(mmap_data);
if_print(sample_id_all);
if_print(exclude_host);
if_print(exclude_guest);
if_print(__reserved_1);
if_print(wakeup_events);
if_print(bp_type);
if_print(branch_sample_type);
}
fputc('\n', fp);
return ++printed;
}
...@@ -118,6 +118,19 @@ void perf_evsel__free_fd(struct perf_evsel *evsel); ...@@ -118,6 +118,19 @@ void perf_evsel__free_fd(struct perf_evsel *evsel);
void perf_evsel__free_id(struct perf_evsel *evsel); void perf_evsel__free_id(struct perf_evsel *evsel);
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
enum perf_event_sample_format bit);
void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel,
enum perf_event_sample_format bit);
#define perf_evsel__set_sample_bit(evsel, bit) \
__perf_evsel__set_sample_bit(evsel, PERF_SAMPLE_##bit)
#define perf_evsel__reset_sample_bit(evsel, bit) \
__perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit)
void perf_evsel__set_sample_id(struct perf_evsel *evsel);
int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter); const char *filter);
...@@ -226,8 +239,16 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) ...@@ -226,8 +239,16 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
return list_entry(evsel->node.next, struct perf_evsel, node); return list_entry(evsel->node.next, struct perf_evsel, node);
} }
static inline bool perf_evsel__is_group_member(const struct perf_evsel *evsel) static inline bool perf_evsel__is_group_leader(const struct perf_evsel *evsel)
{ {
return evsel->leader != NULL; return evsel->leader == evsel;
} }
struct perf_attr_details {
bool freq;
bool verbose;
};
int perf_evsel__fprintf(struct perf_evsel *evsel,
struct perf_attr_details *details, FILE *fp);
#endif /* __PERF_EVSEL_H */ #endif /* __PERF_EVSEL_H */
...@@ -785,7 +785,7 @@ void hists__match(struct hists *leader, struct hists *other) ...@@ -785,7 +785,7 @@ void hists__match(struct hists *leader, struct hists *other)
pair = hists__find_entry(other, pos); pair = hists__find_entry(other, pos);
if (pair) if (pair)
hist__entry_add_pair(pos, pair); hist_entry__add_pair(pair, pos);
} }
} }
...@@ -806,7 +806,7 @@ int hists__link(struct hists *leader, struct hists *other) ...@@ -806,7 +806,7 @@ int hists__link(struct hists *leader, struct hists *other)
pair = hists__add_dummy_entry(leader, pos); pair = hists__add_dummy_entry(leader, pos);
if (pair == NULL) if (pair == NULL)
return -1; return -1;
hist__entry_add_pair(pair, pos); hist_entry__add_pair(pos, pair);
} }
} }
......
...@@ -126,13 +126,19 @@ struct perf_hpp { ...@@ -126,13 +126,19 @@ struct perf_hpp {
}; };
struct perf_hpp_fmt { struct perf_hpp_fmt {
bool cond;
int (*header)(struct perf_hpp *hpp); int (*header)(struct perf_hpp *hpp);
int (*width)(struct perf_hpp *hpp); int (*width)(struct perf_hpp *hpp);
int (*color)(struct perf_hpp *hpp, struct hist_entry *he); int (*color)(struct perf_hpp *hpp, struct hist_entry *he);
int (*entry)(struct perf_hpp *hpp, struct hist_entry *he); int (*entry)(struct perf_hpp *hpp, struct hist_entry *he);
struct list_head list;
}; };
extern struct list_head perf_hpp__list;
#define perf_hpp__for_each_format(format) \
list_for_each_entry(format, &perf_hpp__list, list)
extern struct perf_hpp_fmt perf_hpp__format[]; extern struct perf_hpp_fmt perf_hpp__format[];
enum { enum {
...@@ -148,14 +154,14 @@ enum { ...@@ -148,14 +154,14 @@ enum {
PERF_HPP__DELTA, PERF_HPP__DELTA,
PERF_HPP__RATIO, PERF_HPP__RATIO,
PERF_HPP__WEIGHTED_DIFF, PERF_HPP__WEIGHTED_DIFF,
PERF_HPP__DISPL,
PERF_HPP__FORMULA, PERF_HPP__FORMULA,
PERF_HPP__MAX_INDEX PERF_HPP__MAX_INDEX
}; };
void perf_hpp__init(void); void perf_hpp__init(void);
void perf_hpp__column_enable(unsigned col, bool enable); void perf_hpp__column_register(struct perf_hpp_fmt *format);
void perf_hpp__column_enable(unsigned col);
int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
bool color); bool color);
...@@ -219,8 +225,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, ...@@ -219,8 +225,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
unsigned int hists__sort_list_width(struct hists *self); unsigned int hists__sort_list_width(struct hists *self);
double perf_diff__compute_delta(struct hist_entry *he); double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair);
double perf_diff__compute_ratio(struct hist_entry *he); double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair);
s64 perf_diff__compute_wdiff(struct hist_entry *he); s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair);
int perf_diff__formula(char *buf, size_t size, struct hist_entry *he); int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair,
char *buf, size_t size);
double perf_diff__period_percent(struct hist_entry *he, u64 period);
#endif /* __PERF_HIST_H */ #endif /* __PERF_HIST_H */
This diff is collapsed.
...@@ -61,9 +61,10 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size); ...@@ -61,9 +61,10 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
int machine__init(struct machine *machine, const char *root_dir, pid_t pid); int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
void machine__exit(struct machine *machine); void machine__exit(struct machine *machine);
void machine__delete_dead_threads(struct machine *machine);
void machine__delete_threads(struct machine *machine);
void machine__delete(struct machine *machine); void machine__delete(struct machine *machine);
struct branch_info *machine__resolve_bstack(struct machine *machine, struct branch_info *machine__resolve_bstack(struct machine *machine,
struct thread *thread, struct thread *thread,
struct branch_stack *bs); struct branch_stack *bs);
...@@ -129,11 +130,11 @@ int machine__load_kallsyms(struct machine *machine, const char *filename, ...@@ -129,11 +130,11 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
int machine__load_vmlinux_path(struct machine *machine, enum map_type type, int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
symbol_filter_t filter); symbol_filter_t filter);
size_t machine__fprintf_dsos_buildid(struct machine *machine, size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
FILE *fp, bool with_hits); bool (skip)(struct dso *dso, int parm), int parm);
size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
size_t machines__fprintf_dsos_buildid(struct rb_root *machines, size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
FILE *fp, bool with_hits); bool (skip)(struct dso *dso, int parm), int parm);
void machine__destroy_kernel_maps(struct machine *machine); void machine__destroy_kernel_maps(struct machine *machine);
int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "cpumap.h" #include "cpumap.h"
#include "event-parse.h" #include "event-parse.h"
#include "perf_regs.h" #include "perf_regs.h"
#include "unwind.h"
#include "vdso.h" #include "vdso.h"
static int perf_session__open(struct perf_session *self, bool force) static int perf_session__open(struct perf_session *self, bool force)
...@@ -128,15 +127,6 @@ struct perf_session *perf_session__new(const char *filename, int mode, ...@@ -128,15 +127,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
goto out; goto out;
memcpy(self->filename, filename, len); memcpy(self->filename, filename, len);
/*
* On 64bit we can mmap the data file in one go. No need for tiny mmap
* slices. On 32bit we use 32MB.
*/
#if BITS_PER_LONG == 64
self->mmap_window = ULLONG_MAX;
#else
self->mmap_window = 32 * 1024 * 1024ULL;
#endif
self->machines = RB_ROOT; self->machines = RB_ROOT;
self->repipe = repipe; self->repipe = repipe;
INIT_LIST_HEAD(&self->ordered_samples.samples); INIT_LIST_HEAD(&self->ordered_samples.samples);
...@@ -171,37 +161,30 @@ struct perf_session *perf_session__new(const char *filename, int mode, ...@@ -171,37 +161,30 @@ struct perf_session *perf_session__new(const char *filename, int mode,
return NULL; return NULL;
} }
static void machine__delete_dead_threads(struct machine *machine)
{
struct thread *n, *t;
list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
list_del(&t->node);
thread__delete(t);
}
}
static void perf_session__delete_dead_threads(struct perf_session *session) static void perf_session__delete_dead_threads(struct perf_session *session)
{ {
machine__delete_dead_threads(&session->host_machine); machine__delete_dead_threads(&session->host_machine);
} }
static void machine__delete_threads(struct machine *self) static void perf_session__delete_threads(struct perf_session *session)
{ {
struct rb_node *nd = rb_first(&self->threads); machine__delete_threads(&session->host_machine);
while (nd) {
struct thread *t = rb_entry(nd, struct thread, rb_node);
rb_erase(&t->rb_node, &self->threads);
nd = rb_next(nd);
thread__delete(t);
}
} }
static void perf_session__delete_threads(struct perf_session *session) static void perf_session_env__delete(struct perf_session_env *env)
{ {
machine__delete_threads(&session->host_machine); free(env->hostname);
free(env->os_release);
free(env->version);
free(env->arch);
free(env->cpu_desc);
free(env->cpuid);
free(env->cmdline);
free(env->sibling_cores);
free(env->sibling_threads);
free(env->numa_nodes);
free(env->pmu_mappings);
} }
void perf_session__delete(struct perf_session *self) void perf_session__delete(struct perf_session *self)
...@@ -209,198 +192,13 @@ void perf_session__delete(struct perf_session *self) ...@@ -209,198 +192,13 @@ void perf_session__delete(struct perf_session *self)
perf_session__destroy_kernel_maps(self); perf_session__destroy_kernel_maps(self);
perf_session__delete_dead_threads(self); perf_session__delete_dead_threads(self);
perf_session__delete_threads(self); perf_session__delete_threads(self);
perf_session_env__delete(&self->header.env);
machine__exit(&self->host_machine); machine__exit(&self->host_machine);
close(self->fd); close(self->fd);
free(self); free(self);
vdso__exit(); vdso__exit();
} }
void machine__remove_thread(struct machine *self, struct thread *th)
{
self->last_match = NULL;
rb_erase(&th->rb_node, &self->threads);
/*
* We may have references to this thread, for instance in some hist_entry
* instances, so just move them to a separate list.
*/
list_add_tail(&th->node, &self->dead_threads);
}
static bool symbol__match_parent_regex(struct symbol *sym)
{
if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
return 1;
return 0;
}
static const u8 cpumodes[] = {
PERF_RECORD_MISC_USER,
PERF_RECORD_MISC_KERNEL,
PERF_RECORD_MISC_GUEST_USER,
PERF_RECORD_MISC_GUEST_KERNEL
};
#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
static void ip__resolve_ams(struct machine *self, struct thread *thread,
struct addr_map_symbol *ams,
u64 ip)
{
struct addr_location al;
size_t i;
u8 m;
memset(&al, 0, sizeof(al));
for (i = 0; i < NCPUMODES; i++) {
m = cpumodes[i];
/*
* We cannot use the header.misc hint to determine whether a
* branch stack address is user, kernel, guest, hypervisor.
* Branches may straddle the kernel/user/hypervisor boundaries.
* Thus, we have to try consecutively until we find a match
* or else, the symbol is unknown
*/
thread__find_addr_location(thread, self, m, MAP__FUNCTION,
ip, &al, NULL);
if (al.sym)
goto found;
}
found:
ams->addr = ip;
ams->al_addr = al.addr;
ams->sym = al.sym;
ams->map = al.map;
}
struct branch_info *machine__resolve_bstack(struct machine *self,
struct thread *thr,
struct branch_stack *bs)
{
struct branch_info *bi;
unsigned int i;
bi = calloc(bs->nr, sizeof(struct branch_info));
if (!bi)
return NULL;
for (i = 0; i < bs->nr; i++) {
ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to);
ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from);
bi[i].flags = bs->entries[i].flags;
}
return bi;
}
static int machine__resolve_callchain_sample(struct machine *machine,
struct thread *thread,
struct ip_callchain *chain,
struct symbol **parent)
{
u8 cpumode = PERF_RECORD_MISC_USER;
unsigned int i;
int err;
callchain_cursor_reset(&callchain_cursor);
if (chain->nr > PERF_MAX_STACK_DEPTH) {
pr_warning("corrupted callchain. skipping...\n");
return 0;
}
for (i = 0; i < chain->nr; i++) {
u64 ip;
struct addr_location al;
if (callchain_param.order == ORDER_CALLEE)
ip = chain->ips[i];
else
ip = chain->ips[chain->nr - i - 1];
if (ip >= PERF_CONTEXT_MAX) {
switch (ip) {
case PERF_CONTEXT_HV:
cpumode = PERF_RECORD_MISC_HYPERVISOR;
break;
case PERF_CONTEXT_KERNEL:
cpumode = PERF_RECORD_MISC_KERNEL;
break;
case PERF_CONTEXT_USER:
cpumode = PERF_RECORD_MISC_USER;
break;
default:
pr_debug("invalid callchain context: "
"%"PRId64"\n", (s64) ip);
/*
* It seems the callchain is corrupted.
* Discard all.
*/
callchain_cursor_reset(&callchain_cursor);
return 0;
}
continue;
}
al.filtered = false;
thread__find_addr_location(thread, machine, cpumode,
MAP__FUNCTION, ip, &al, NULL);
if (al.sym != NULL) {
if (sort__has_parent && !*parent &&
symbol__match_parent_regex(al.sym))
*parent = al.sym;
if (!symbol_conf.use_callchain)
break;
}
err = callchain_cursor_append(&callchain_cursor,
ip, al.map, al.sym);
if (err)
return err;
}
return 0;
}
static int unwind_entry(struct unwind_entry *entry, void *arg)
{
struct callchain_cursor *cursor = arg;
return callchain_cursor_append(cursor, entry->ip,
entry->map, entry->sym);
}
int machine__resolve_callchain(struct machine *machine,
struct perf_evsel *evsel,
struct thread *thread,
struct perf_sample *sample,
struct symbol **parent)
{
int ret;
callchain_cursor_reset(&callchain_cursor);
ret = machine__resolve_callchain_sample(machine, thread,
sample->callchain, parent);
if (ret)
return ret;
/* Can we do dwarf post unwind? */
if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
(evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
return 0;
/* Bail out if nothing was captured. */
if ((!sample->user_regs.regs) ||
(!sample->user_stack.size))
return 0;
return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
thread, evsel->attr.sample_regs_user,
sample);
}
static int process_event_synth_tracing_data_stub(union perf_event *event static int process_event_synth_tracing_data_stub(union perf_event *event
__maybe_unused, __maybe_unused,
struct perf_session *session struct perf_session *session
...@@ -1369,6 +1167,18 @@ fetch_mmaped_event(struct perf_session *session, ...@@ -1369,6 +1167,18 @@ fetch_mmaped_event(struct perf_session *session,
return event; return event;
} }
/*
* On 64bit we can mmap the data file in one go. No need for tiny mmap
* slices. On 32bit we use 32MB.
*/
#if BITS_PER_LONG == 64
#define MMAP_SIZE ULLONG_MAX
#define NUM_MMAPS 1
#else
#define MMAP_SIZE (32 * 1024 * 1024ULL)
#define NUM_MMAPS 128
#endif
int __perf_session__process_events(struct perf_session *session, int __perf_session__process_events(struct perf_session *session,
u64 data_offset, u64 data_size, u64 data_offset, u64 data_size,
u64 file_size, struct perf_tool *tool) u64 file_size, struct perf_tool *tool)
...@@ -1376,7 +1186,7 @@ int __perf_session__process_events(struct perf_session *session, ...@@ -1376,7 +1186,7 @@ int __perf_session__process_events(struct perf_session *session,
u64 head, page_offset, file_offset, file_pos, progress_next; u64 head, page_offset, file_offset, file_pos, progress_next;
int err, mmap_prot, mmap_flags, map_idx = 0; int err, mmap_prot, mmap_flags, map_idx = 0;
size_t mmap_size; size_t mmap_size;
char *buf, *mmaps[8]; char *buf, *mmaps[NUM_MMAPS];
union perf_event *event; union perf_event *event;
uint32_t size; uint32_t size;
...@@ -1391,7 +1201,7 @@ int __perf_session__process_events(struct perf_session *session, ...@@ -1391,7 +1201,7 @@ int __perf_session__process_events(struct perf_session *session,
progress_next = file_size / 16; progress_next = file_size / 16;
mmap_size = session->mmap_window; mmap_size = MMAP_SIZE;
if (mmap_size > file_size) if (mmap_size > file_size)
mmap_size = file_size; mmap_size = file_size;
...@@ -1532,10 +1342,10 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) ...@@ -1532,10 +1342,10 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp)
} }
size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
bool with_hits) bool (skip)(struct dso *dso, int parm), int parm)
{ {
size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits); size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, skip, parm);
return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); return ret + machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm);
} }
size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
......
...@@ -30,7 +30,6 @@ struct ordered_samples { ...@@ -30,7 +30,6 @@ struct ordered_samples {
struct perf_session { struct perf_session {
struct perf_header header; struct perf_header header;
unsigned long size; unsigned long size;
unsigned long mmap_window;
struct machine host_machine; struct machine host_machine;
struct rb_root machines; struct rb_root machines;
struct perf_evlist *evlist; struct perf_evlist *evlist;
...@@ -116,8 +115,8 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp); ...@@ -116,8 +115,8 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
FILE *fp, bool with_hits); bool (fn)(struct dso *dso, int parm), int parm);
size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
......
...@@ -55,9 +55,6 @@ struct he_stat { ...@@ -55,9 +55,6 @@ struct he_stat {
struct hist_entry_diff { struct hist_entry_diff {
bool computed; bool computed;
/* PERF_HPP__DISPL */
int displacement;
/* PERF_HPP__DELTA */ /* PERF_HPP__DELTA */
double period_ratio_delta; double period_ratio_delta;
...@@ -118,7 +115,7 @@ static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he) ...@@ -118,7 +115,7 @@ static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he)
return NULL; return NULL;
} }
static inline void hist__entry_add_pair(struct hist_entry *he, static inline void hist_entry__add_pair(struct hist_entry *he,
struct hist_entry *pair) struct hist_entry *pair)
{ {
list_add_tail(&he->pairs.head, &pair->pairs.node); list_add_tail(&he->pairs.head, &pair->pairs.node);
......
...@@ -718,6 +718,17 @@ int dso__load_sym(struct dso *dso, struct map *map, ...@@ -718,6 +718,17 @@ int dso__load_sym(struct dso *dso, struct map *map,
sym.st_value); sym.st_value);
used_opd = true; used_opd = true;
} }
/*
* When loading symbols in a data mapping, ABS symbols (which
* has a value of SHN_ABS in its st_shndx) failed at
* elf_getscn(). And it marks the loading as a failure so
* already loaded symbols cannot be fixed up.
*
* I'm not sure what should be done. Just ignore them for now.
* - Namhyung Kim
*/
if (sym.st_shndx == SHN_ABS)
continue;
sec = elf_getscn(runtime_ss->elf, sym.st_shndx); sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
if (!sec) if (!sec)
......
This diff is collapsed.
...@@ -120,6 +120,8 @@ struct symbol_conf { ...@@ -120,6 +120,8 @@ struct symbol_conf {
}; };
extern struct symbol_conf symbol_conf; extern struct symbol_conf symbol_conf;
extern int vmlinux_path__nr_entries;
extern char **vmlinux_path;
static inline void *symbol__priv(struct symbol *sym) static inline void *symbol__priv(struct symbol *sym)
{ {
...@@ -223,6 +225,8 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym, ...@@ -223,6 +225,8 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym,
size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
size_t symbol__fprintf(struct symbol *sym, FILE *fp); size_t symbol__fprintf(struct symbol *sym, FILE *fp);
bool symbol_type__is_a(char symbol_type, enum map_type map_type); bool symbol_type__is_a(char symbol_type, enum map_type map_type);
bool symbol__restricted_filename(const char *filename,
const char *restricted_filename);
int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
struct symsrc *runtime_ss, symbol_filter_t filter, struct symsrc *runtime_ss, symbol_filter_t filter,
......
...@@ -54,10 +54,10 @@ int thread__comm_len(struct thread *self) ...@@ -54,10 +54,10 @@ int thread__comm_len(struct thread *self)
return self->comm_len; return self->comm_len;
} }
static size_t thread__fprintf(struct thread *self, FILE *fp) size_t thread__fprintf(struct thread *thread, FILE *fp)
{ {
return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) + return fprintf(fp, "Thread %d %s\n", thread->pid, thread->comm) +
map_groups__fprintf(&self->mg, verbose, fp); map_groups__fprintf(&thread->mg, verbose, fp);
} }
void thread__insert_map(struct thread *self, struct map *map) void thread__insert_map(struct thread *self, struct map *map)
...@@ -84,17 +84,3 @@ int thread__fork(struct thread *self, struct thread *parent) ...@@ -84,17 +84,3 @@ int thread__fork(struct thread *self, struct thread *parent)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
} }
size_t machine__fprintf(struct machine *machine, FILE *fp)
{
size_t ret = 0;
struct rb_node *nd;
for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
struct thread *pos = rb_entry(nd, struct thread, rb_node);
ret += thread__fprintf(pos, fp);
}
return ret;
}
...@@ -30,6 +30,7 @@ int thread__set_comm(struct thread *self, const char *comm); ...@@ -30,6 +30,7 @@ int thread__set_comm(struct thread *self, const char *comm);
int thread__comm_len(struct thread *self); int thread__comm_len(struct thread *self);
void thread__insert_map(struct thread *self, struct map *map); void thread__insert_map(struct thread *self, struct map *map);
int thread__fork(struct thread *self, struct thread *parent); int thread__fork(struct thread *self, struct thread *parent);
size_t thread__fprintf(struct thread *thread, FILE *fp);
static inline struct map *thread__find_map(struct thread *self, static inline struct map *thread__find_map(struct thread *self,
enum map_type type, u64 addr) enum map_type type, u64 addr)
......
...@@ -26,6 +26,8 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) ...@@ -26,6 +26,8 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
float samples_per_sec = top->samples / top->delay_secs; float samples_per_sec = top->samples / top->delay_secs;
float ksamples_per_sec = top->kernel_samples / top->delay_secs; float ksamples_per_sec = top->kernel_samples / top->delay_secs;
float esamples_percent = (100.0 * top->exact_samples) / top->samples; float esamples_percent = (100.0 * top->exact_samples) / top->samples;
struct perf_record_opts *opts = &top->record_opts;
struct perf_target *target = &opts->target;
size_t ret = 0; size_t ret = 0;
if (!perf_guest) { if (!perf_guest) {
...@@ -61,31 +63,31 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) ...@@ -61,31 +63,31 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
struct perf_evsel *first = perf_evlist__first(top->evlist); struct perf_evsel *first = perf_evlist__first(top->evlist);
ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ", ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
(uint64_t)first->attr.sample_period, (uint64_t)first->attr.sample_period,
top->freq ? "Hz" : ""); opts->freq ? "Hz" : "");
} }
ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel)); ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));
ret += SNPRINTF(bf + ret, size - ret, "], "); ret += SNPRINTF(bf + ret, size - ret, "], ");
if (top->target.pid) if (target->pid)
ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s", ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
top->target.pid); target->pid);
else if (top->target.tid) else if (target->tid)
ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s", ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
top->target.tid); target->tid);
else if (top->target.uid_str != NULL) else if (target->uid_str != NULL)
ret += SNPRINTF(bf + ret, size - ret, " (uid: %s", ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
top->target.uid_str); target->uid_str);
else else
ret += SNPRINTF(bf + ret, size - ret, " (all"); ret += SNPRINTF(bf + ret, size - ret, " (all");
if (top->target.cpu_list) if (target->cpu_list)
ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
top->evlist->cpus->nr > 1 ? "s" : "", top->evlist->cpus->nr > 1 ? "s" : "",
top->target.cpu_list); target->cpu_list);
else { else {
if (top->target.tid) if (target->tid)
ret += SNPRINTF(bf + ret, size - ret, ")"); ret += SNPRINTF(bf + ret, size - ret, ")");
else else
ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
......
...@@ -14,7 +14,7 @@ struct perf_session; ...@@ -14,7 +14,7 @@ struct perf_session;
struct perf_top { struct perf_top {
struct perf_tool tool; struct perf_tool tool;
struct perf_evlist *evlist; struct perf_evlist *evlist;
struct perf_target target; struct perf_record_opts record_opts;
/* /*
* Symbols will be added here in perf_event__process_sample and will * Symbols will be added here in perf_event__process_sample and will
* get out after decayed. * get out after decayed.
...@@ -24,15 +24,11 @@ struct perf_top { ...@@ -24,15 +24,11 @@ struct perf_top {
u64 exact_samples; u64 exact_samples;
u64 guest_us_samples, guest_kernel_samples; u64 guest_us_samples, guest_kernel_samples;
int print_entries, count_filter, delay_secs; int print_entries, count_filter, delay_secs;
int freq;
bool hide_kernel_symbols, hide_user_symbols, zero; bool hide_kernel_symbols, hide_user_symbols, zero;
bool use_tui, use_stdio; bool use_tui, use_stdio;
bool sort_has_symbols; bool sort_has_symbols;
bool dont_use_callchains;
bool kptr_restrict_warned; bool kptr_restrict_warned;
bool vmlinux_warned; bool vmlinux_warned;
bool inherit;
bool group;
bool sample_id_all_missing; bool sample_id_all_missing;
bool exclude_guest_missing; bool exclude_guest_missing;
bool dump_symtab; bool dump_symtab;
...@@ -40,8 +36,6 @@ struct perf_top { ...@@ -40,8 +36,6 @@ struct perf_top {
struct perf_evsel *sym_evsel; struct perf_evsel *sym_evsel;
struct perf_session *session; struct perf_session *session;
struct winsize winsize; struct winsize winsize;
unsigned int mmap_pages;
int default_interval;
int realtime_prio; int realtime_prio;
int sym_pcnt_filter; int sym_pcnt_filter;
const char *sym_filter; const char *sym_filter;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment