aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 09:58:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 09:58:15 -0400
commit9d9420f1209a1facea7110d549ac695f5aeeb503 (patch)
tree7956d1c40420644830decbbc90b8bbdfeb194364 /tools
parent6d5f0ebfc0be9cbfeaafdd9258d5fa24b7975a36 (diff)
parentcc6cd47e7395bc05c5077009808b820633eb3f18 (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "Kernel side updates: - Fix and enhance poll support (Jiri Olsa) - Re-enable inheritance optimization (Jiri Olsa) - Enhance Intel memory events support (Stephane Eranian) - Refactor the Intel uncore driver to be more maintainable (Zheng Yan) - Enhance and fix Intel CPU and uncore PMU drivers (Peter Zijlstra, Andi Kleen) - [ plus various smaller fixes/cleanups ] User visible tooling updates: - Add +field argument support for --field option, so that one can add fields to the default list of fields to show, ie now one can just do: perf report --fields +pid And the pid will appear in addition to the default fields (Jiri Olsa) - Add +field argument support for --sort option (Jiri Olsa) - Honour -w in the report tools (report, top), allowing to specify the widths for the histogram entries columns (Namhyung Kim) - Properly show submicrosecond times in 'perf kvm stat' (Christian Borntraeger) - Add beautifier for mremap flags param in 'trace' (Alex Snast) - perf script: Allow callchains if any event samples them - Don't truncate Intel style addresses in 'annotate' (Alex Converse) - Allow profiling when kptr_restrict == 1 for non root users, kernel samples will just remain unresolved (Andi Kleen) - Allow configuring default options for callchains in config file (Namhyung Kim) - Support operations for shared futexes. (Davidlohr Bueso) - "perf kvm stat report" improvements by Alexander Yarygin: - Save pid string in opts.target.pid - Enable the target.system_wide flag - Unify the title bar output - [ plus lots of other fixes and small improvements. ] Tooling infrastructure changes: - Refactor unit and scale function parameters for PMU parsing routines (Matt Fleming) - Improve DSO long names lookup with rbtree, resulting in great speedup for workloads with lots of DSOs (Waiman Long) - We were not handling POLLHUP notifications for event file descriptors Fix it by filtering entries in the events file descriptor array after poll() returns, refcounting mmaps so that when the last fd pointing to a perf mmap goes away we do the unmap (Arnaldo Carvalho de Melo) - Intel PT prep work, from Adrian Hunter, including: - Let a user specify a PMU event without any config terms - Add perf-with-kcore script - Let default config be defined for a PMU - Add perf_pmu__scan_file() - Add a 'perf test' for tracking with sched_switch - Add 'flush' callback to scripting API - Use ring buffer consume method to look like other tools (Arnaldo Carvalho de Melo) - hists browser (used in top and report) refactorings, getting rid of unused variables and reducing source code size by handling similar cases in a fewer functions (Namhyung Kim). - Replace thread unsafe strerror() with strerror_r() accross the whole tools/perf/ tree (Masami Hiramatsu) - Rename ordered_samples to ordered_events and allow setting a queue size for ordering events (Jiri Olsa) - [ plus lots of fixes, cleanups and other improvements ]" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (198 commits) perf/x86: Tone down kernel messages when the PMU check fails in a virtual environment perf/x86/intel/uncore: Fix minor race in box set up perf record: Fix error message for --filter option not coming after tracepoint perf tools: Fix build breakage on arm64 targets perf symbols: Improve DSO long names lookup speed with rbtree perf symbols: Encapsulate dsos list head into struct dsos perf bench futex: Sanitize -q option in requeue perf bench futex: Support operations for shared futexes perf trace: Fix mmap return address truncation to 32-bit perf tools: Refactor unit and scale function parameters perf tools: Fix line number in the config file error message perf tools: Convert {record,top}.call-graph option to call-graph.record-mode perf tools: Introduce perf_callchain_config() perf callchain: Move some parser functions to callchain.c perf tools: Move callchain config from record_opts to callchain_param perf hists browser: Fix callchain print bug on TUI perf tools: Use ACCESS_ONCE() instead of volatile cast perf tools: Modify error code for when perf_session__new() fails perf tools: Fix perf record as non root with kptr_restrict == 1 perf stat: Fix --per-core on multi socket systems ...
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/api/Makefile7
-rw-r--r--tools/lib/api/fd/array.c127
-rw-r--r--tools/lib/api/fd/array.h46
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/perf-probe.txt3
-rw-r--r--tools/perf/Documentation/perf-report.txt5
-rw-r--r--tools/perf/Documentation/perf-top.txt9
-rw-r--r--tools/perf/Makefile.perf11
-rw-r--r--tools/perf/arch/arm/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/arm/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/arm64/include/perf_regs.h2
-rw-r--r--tools/perf/arch/arm64/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/common.c9
-rw-r--r--tools/perf/arch/powerpc/Makefile2
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c1
-rw-r--r--tools/perf/bench/futex-hash.c7
-rw-r--r--tools/perf/bench/futex-requeue.c28
-rw-r--r--tools/perf/bench/futex-wake.c15
-rw-r--r--tools/perf/bench/sched-messaging.c2
-rw-r--r--tools/perf/builtin-annotate.c77
-rw-r--r--tools/perf/builtin-buildid-cache.c44
-rw-r--r--tools/perf/builtin-diff.c6
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c20
-rw-r--r--tools/perf/builtin-inject.c33
-rw-r--r--tools/perf/builtin-kmem.c56
-rw-r--r--tools/perf/builtin-kvm.c98
-rw-r--r--tools/perf/builtin-lock.c7
-rw-r--r--tools/perf/builtin-mem.c6
-rw-r--r--tools/perf/builtin-probe.c10
-rw-r--r--tools/perf/builtin-record.c146
-rw-r--r--tools/perf/builtin-report.c23
-rw-r--r--tools/perf/builtin-sched.c9
-rw-r--r--tools/perf/builtin-script.c74
-rw-r--r--tools/perf/builtin-stat.c11
-rw-r--r--tools/perf/builtin-timechart.c8
-rw-r--r--tools/perf/builtin-top.c87
-rw-r--r--tools/perf/builtin-trace.c57
-rw-r--r--tools/perf/config/Makefile52
-rw-r--r--tools/perf/config/feature-checks/Makefile18
-rw-r--r--tools/perf/config/utilities.mak2
-rw-r--r--tools/perf/perf-with-kcore.sh259
-rw-r--r--tools/perf/perf.c10
-rw-r--r--tools/perf/perf.h3
-rw-r--r--tools/perf/tests/builtin-test.c18
-rw-r--r--tools/perf/tests/fdarray.c174
-rw-r--r--tools/perf/tests/mmap-basic.c7
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c5
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c9
-rw-r--r--tools/perf/tests/open-syscall.c3
-rw-r--r--tools/perf/tests/perf-record.c15
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/rdpmc.c6
-rw-r--r--tools/perf/tests/sw-clock.c6
-rw-r--r--tools/perf/tests/switch-tracking.c572
-rw-r--r--tools/perf/tests/task-exit.c8
-rw-r--r--tools/perf/tests/tests.h3
-rw-r--r--tools/perf/ui/browsers/hists.c384
-rw-r--r--tools/perf/ui/gtk/hists.c18
-rw-r--r--tools/perf/ui/hist.c284
-rw-r--r--tools/perf/ui/stdio/hist.c4
-rw-r--r--tools/perf/util/annotate.c21
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c240
-rw-r--r--tools/perf/util/callchain.h6
-rw-r--r--tools/perf/util/cloexec.c35
-rw-r--r--tools/perf/util/color.c16
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c7
-rw-r--r--tools/perf/util/comm.h6
-rw-r--r--tools/perf/util/config.c40
-rw-r--r--tools/perf/util/data.c8
-rw-r--r--tools/perf/util/debug.c36
-rw-r--r--tools/perf/util/debug.h11
-rw-r--r--tools/perf/util/dso.c121
-rw-r--r--tools/perf/util/dso.h16
-rw-r--r--tools/perf/util/event.c14
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/evlist.c236
-rw-r--r--tools/perf/util/evlist.h21
-rw-r--r--tools/perf/util/evsel.c67
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/header.c32
-rw-r--r--tools/perf/util/hist.c22
-rw-r--r--tools/perf/util/hist.h18
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/machine.c96
-rw-r--r--tools/perf/util/machine.h26
-rw-r--r--tools/perf/util/map.c1
-rw-r--r--tools/perf/util/ordered-events.c245
-rw-r--r--tools/perf/util/ordered-events.h51
-rw-r--r--tools/perf/util/parse-events.c29
-rw-r--r--tools/perf/util/parse-events.y10
-rw-r--r--tools/perf/util/pmu.c121
-rw-r--r--tools/perf/util/pmu.h25
-rw-r--r--tools/perf/util/probe-event.c181
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-finder.c23
-rw-r--r--tools/perf/util/python.c6
-rw-r--r--tools/perf/util/record.c40
-rw-r--r--tools/perf/util/run-command.c9
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c120
-rw-r--r--tools/perf/util/session.c300
-rw-r--r--tools/perf/util/session.h32
-rw-r--r--tools/perf/util/sort.c119
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/symbol-elf.c31
-rw-r--r--tools/perf/util/symbol.c43
-rw-r--r--tools/perf/util/symbol.h14
-rw-r--r--tools/perf/util/thread.c24
-rw-r--r--tools/perf/util/thread.h10
-rw-r--r--tools/perf/util/tool.h2
-rw-r--r--tools/perf/util/trace-event-scripting.c7
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/util.c54
-rw-r--r--tools/perf/util/util.h23
117 files changed, 4085 insertions, 1462 deletions
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index ce00f7ee6455..36c08b1f4afb 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -10,9 +10,14 @@ LIB_OBJS=
10 10
11LIB_H += fs/debugfs.h 11LIB_H += fs/debugfs.h
12LIB_H += fs/fs.h 12LIB_H += fs/fs.h
13# See comment below about piggybacking...
14LIB_H += fd/array.h
13 15
14LIB_OBJS += $(OUTPUT)fs/debugfs.o 16LIB_OBJS += $(OUTPUT)fs/debugfs.o
15LIB_OBJS += $(OUTPUT)fs/fs.o 17LIB_OBJS += $(OUTPUT)fs/fs.o
18# XXX piggybacking here, need to introduce libapikfd, or rename this
19# to plain libapik.a and make it have it all api goodies
20LIB_OBJS += $(OUTPUT)fd/array.o
16 21
17LIBFILE = libapikfs.a 22LIBFILE = libapikfs.a
18 23
@@ -29,7 +34,7 @@ $(LIBFILE): $(LIB_OBJS)
29$(LIB_OBJS): $(LIB_H) 34$(LIB_OBJS): $(LIB_H)
30 35
31libapi_dirs: 36libapi_dirs:
32 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/ 37 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
33 38
34$(OUTPUT)%.o: %.c libapi_dirs 39$(OUTPUT)%.o: %.c libapi_dirs
35 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 40 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
diff --git a/tools/lib/api/fd/array.c b/tools/lib/api/fd/array.c
new file mode 100644
index 000000000000..0e636c4339b8
--- /dev/null
+++ b/tools/lib/api/fd/array.c
@@ -0,0 +1,127 @@
1/*
2 * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Released under the GPL v2. (and only v2, not any later version)
5 */
6#include "array.h"
7#include <errno.h>
8#include <fcntl.h>
9#include <poll.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13void fdarray__init(struct fdarray *fda, int nr_autogrow)
14{
15 fda->entries = NULL;
16 fda->priv = NULL;
17 fda->nr = fda->nr_alloc = 0;
18 fda->nr_autogrow = nr_autogrow;
19}
20
21int fdarray__grow(struct fdarray *fda, int nr)
22{
23 void *priv;
24 int nr_alloc = fda->nr_alloc + nr;
25 size_t psize = sizeof(fda->priv[0]) * nr_alloc;
26 size_t size = sizeof(struct pollfd) * nr_alloc;
27 struct pollfd *entries = realloc(fda->entries, size);
28
29 if (entries == NULL)
30 return -ENOMEM;
31
32 priv = realloc(fda->priv, psize);
33 if (priv == NULL) {
34 free(entries);
35 return -ENOMEM;
36 }
37
38 fda->nr_alloc = nr_alloc;
39 fda->entries = entries;
40 fda->priv = priv;
41 return 0;
42}
43
44struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow)
45{
46 struct fdarray *fda = calloc(1, sizeof(*fda));
47
48 if (fda != NULL) {
49 if (fdarray__grow(fda, nr_alloc)) {
50 free(fda);
51 fda = NULL;
52 } else {
53 fda->nr_autogrow = nr_autogrow;
54 }
55 }
56
57 return fda;
58}
59
60void fdarray__exit(struct fdarray *fda)
61{
62 free(fda->entries);
63 free(fda->priv);
64 fdarray__init(fda, 0);
65}
66
67void fdarray__delete(struct fdarray *fda)
68{
69 fdarray__exit(fda);
70 free(fda);
71}
72
73int fdarray__add(struct fdarray *fda, int fd, short revents)
74{
75 int pos = fda->nr;
76
77 if (fda->nr == fda->nr_alloc &&
78 fdarray__grow(fda, fda->nr_autogrow) < 0)
79 return -ENOMEM;
80
81 fda->entries[fda->nr].fd = fd;
82 fda->entries[fda->nr].events = revents;
83 fda->nr++;
84 return pos;
85}
86
87int fdarray__filter(struct fdarray *fda, short revents,
88 void (*entry_destructor)(struct fdarray *fda, int fd))
89{
90 int fd, nr = 0;
91
92 if (fda->nr == 0)
93 return 0;
94
95 for (fd = 0; fd < fda->nr; ++fd) {
96 if (fda->entries[fd].revents & revents) {
97 if (entry_destructor)
98 entry_destructor(fda, fd);
99
100 continue;
101 }
102
103 if (fd != nr) {
104 fda->entries[nr] = fda->entries[fd];
105 fda->priv[nr] = fda->priv[fd];
106 }
107
108 ++nr;
109 }
110
111 return fda->nr = nr;
112}
113
114int fdarray__poll(struct fdarray *fda, int timeout)
115{
116 return poll(fda->entries, fda->nr, timeout);
117}
118
119int fdarray__fprintf(struct fdarray *fda, FILE *fp)
120{
121 int fd, printed = fprintf(fp, "%d [ ", fda->nr);
122
123 for (fd = 0; fd < fda->nr; ++fd)
124 printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd);
125
126 return printed + fprintf(fp, " ]");
127}
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h
new file mode 100644
index 000000000000..45db01818f45
--- /dev/null
+++ b/tools/lib/api/fd/array.h
@@ -0,0 +1,46 @@
1#ifndef __API_FD_ARRAY__
2#define __API_FD_ARRAY__
3
4#include <stdio.h>
5
6struct pollfd;
7
8/**
9 * struct fdarray: Array of file descriptors
10 *
11 * @priv: Per array entry priv area, users should access just its contents,
12 * not set it to anything, as it is kept in synch with @entries, being
13 * realloc'ed, * for instance, in fdarray__{grow,filter}.
14 *
15 * I.e. using 'fda->priv[N].idx = * value' where N < fda->nr is ok,
16 * but doing 'fda->priv = malloc(M)' is not allowed.
17 */
18struct fdarray {
19 int nr;
20 int nr_alloc;
21 int nr_autogrow;
22 struct pollfd *entries;
23 union {
24 int idx;
25 } *priv;
26};
27
28void fdarray__init(struct fdarray *fda, int nr_autogrow);
29void fdarray__exit(struct fdarray *fda);
30
31struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow);
32void fdarray__delete(struct fdarray *fda);
33
34int fdarray__add(struct fdarray *fda, int fd, short revents);
35int fdarray__poll(struct fdarray *fda, int timeout);
36int fdarray__filter(struct fdarray *fda, short revents,
37 void (*entry_destructor)(struct fdarray *fda, int fd));
38int fdarray__grow(struct fdarray *fda, int extra);
39int fdarray__fprintf(struct fdarray *fda, FILE *fp);
40
41static inline int fdarray__available_entries(struct fdarray *fda)
42{
43 return fda->nr_alloc - fda->nr;
44}
45
46#endif /* __API_FD_ARRAY__ */
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 782d86e961b9..717221e98450 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -15,6 +15,7 @@ perf.data
15perf.data.old 15perf.data.old
16output.svg 16output.svg
17perf-archive 17perf-archive
18perf-with-kcore
18tags 19tags
19TAGS 20TAGS
20cscope* 21cscope*
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 1513935c399b..aaa869be3dc1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -104,6 +104,9 @@ OPTIONS
104 Specify path to the executable or shared library file for user 104 Specify path to the executable or shared library file for user
105 space tracing. Can also be used with --funcs option. 105 space tracing. Can also be used with --funcs option.
106 106
107--demangle-kernel::
108 Demangle kernel symbols.
109
107In absence of -m/-x options, perf probe checks if the first argument after 110In absence of -m/-x options, perf probe checks if the first argument after
108the options is an absolute path name. If its an absolute path, perf probe 111the options is an absolute path name. If its an absolute path, perf probe
109uses it as a target module/target user space binary to probe. 112uses it as a target module/target user space binary to probe.
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index d2b59af62bc0..0927bf4e6c2a 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -147,7 +147,7 @@ OPTIONS
147-w:: 147-w::
148--column-widths=<width[,width...]>:: 148--column-widths=<width[,width...]>::
149 Force each column width to the provided list, for large terminal 149 Force each column width to the provided list, for large terminal
150 readability. 150 readability. 0 means no limit (default behavior).
151 151
152-t:: 152-t::
153--field-separator=:: 153--field-separator=::
@@ -276,6 +276,9 @@ OPTIONS
276 Demangle symbol names to human readable form. It's enabled by default, 276 Demangle symbol names to human readable form. It's enabled by default,
277 disable with --no-demangle. 277 disable with --no-demangle.
278 278
279--demangle-kernel::
280 Demangle kernel symbol names to human readable form (for C++ kernels).
281
279--mem-mode:: 282--mem-mode::
280 Use the data addresses of samples in addition to instruction addresses 283 Use the data addresses of samples in addition to instruction addresses
281 to build the histograms. To generate meaningful output, the perf.data 284 to build the histograms. To generate meaningful output, the perf.data
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 180ae02137a5..3265b1070518 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -98,6 +98,9 @@ Default is to monitor all CPUS.
98--hide_user_symbols:: 98--hide_user_symbols::
99 Hide user symbols. 99 Hide user symbols.
100 100
101--demangle-kernel::
102 Demangle kernel symbols.
103
101-D:: 104-D::
102--dump-symtab:: 105--dump-symtab::
103 Dump the symbol table used for profiling. 106 Dump the symbol table used for profiling.
@@ -193,6 +196,12 @@ Default is to monitor all CPUS.
193 sum of shown entries will be always 100%. "absolute" means it retains 196 sum of shown entries will be always 100%. "absolute" means it retains
194 the original value before and after the filter is applied. 197 the original value before and after the filter is applied.
195 198
199-w::
200--column-widths=<width[,width...]>::
201 Force each column width to the provided list, for large terminal
202 readability. 0 means no limit (default behavior).
203
204
196INTERACTIVE PROMPTING KEYS 205INTERACTIVE PROMPTING KEYS
197-------------------------- 206--------------------------
198 207
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2240974b7745..262916f4a377 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -126,6 +126,7 @@ PYRF_OBJS =
126SCRIPT_SH = 126SCRIPT_SH =
127 127
128SCRIPT_SH += perf-archive.sh 128SCRIPT_SH += perf-archive.sh
129SCRIPT_SH += perf-with-kcore.sh
129 130
130grep-libs = $(filter -l%,$(1)) 131grep-libs = $(filter -l%,$(1))
131strip-libs = $(filter-out -l%,$(1)) 132strip-libs = $(filter-out -l%,$(1))
@@ -263,6 +264,7 @@ LIB_H += util/xyarray.h
263LIB_H += util/header.h 264LIB_H += util/header.h
264LIB_H += util/help.h 265LIB_H += util/help.h
265LIB_H += util/session.h 266LIB_H += util/session.h
267LIB_H += util/ordered-events.h
266LIB_H += util/strbuf.h 268LIB_H += util/strbuf.h
267LIB_H += util/strlist.h 269LIB_H += util/strlist.h
268LIB_H += util/strfilter.h 270LIB_H += util/strfilter.h
@@ -347,6 +349,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
347LIB_OBJS += $(OUTPUT)util/map.o 349LIB_OBJS += $(OUTPUT)util/map.o
348LIB_OBJS += $(OUTPUT)util/pstack.o 350LIB_OBJS += $(OUTPUT)util/pstack.o
349LIB_OBJS += $(OUTPUT)util/session.o 351LIB_OBJS += $(OUTPUT)util/session.o
352LIB_OBJS += $(OUTPUT)util/ordered-events.o
350LIB_OBJS += $(OUTPUT)util/comm.o 353LIB_OBJS += $(OUTPUT)util/comm.o
351LIB_OBJS += $(OUTPUT)util/thread.o 354LIB_OBJS += $(OUTPUT)util/thread.o
352LIB_OBJS += $(OUTPUT)util/thread_map.o 355LIB_OBJS += $(OUTPUT)util/thread_map.o
@@ -399,6 +402,7 @@ LIB_OBJS += $(OUTPUT)tests/perf-record.o
399LIB_OBJS += $(OUTPUT)tests/rdpmc.o 402LIB_OBJS += $(OUTPUT)tests/rdpmc.o
400LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o 403LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
401LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o 404LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
405LIB_OBJS += $(OUTPUT)tests/fdarray.o
402LIB_OBJS += $(OUTPUT)tests/pmu.o 406LIB_OBJS += $(OUTPUT)tests/pmu.o
403LIB_OBJS += $(OUTPUT)tests/hists_common.o 407LIB_OBJS += $(OUTPUT)tests/hists_common.o
404LIB_OBJS += $(OUTPUT)tests/hists_link.o 408LIB_OBJS += $(OUTPUT)tests/hists_link.o
@@ -423,6 +427,7 @@ endif
423endif 427endif
424LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o 428LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
425LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o 429LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
430LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
426 431
427BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 432BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
428BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 433BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -765,7 +770,7 @@ $(LIBTRACEEVENT)-clean:
765install-traceevent-plugins: $(LIBTRACEEVENT) 770install-traceevent-plugins: $(LIBTRACEEVENT)
766 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins 771 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
767 772
768LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch]) 773LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch])
769 774
770# if subdir is set, we've been called from above so target has been built 775# if subdir is set, we've been called from above so target has been built
771# already 776# already
@@ -875,6 +880,8 @@ install-bin: all install-gtk
875 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
876 $(call QUIET_INSTALL, perf-archive) \ 881 $(call QUIET_INSTALL, perf-archive) \
877 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 882 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
883 $(call QUIET_INSTALL, perf-with-kcore) \
884 $(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
878ifndef NO_LIBPERL 885ifndef NO_LIBPERL
879 $(call QUIET_INSTALL, perl-scripts) \ 886 $(call QUIET_INSTALL, perl-scripts) \
880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \ 887 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
@@ -920,7 +927,7 @@ config-clean:
920 @$(MAKE) -C config/feature-checks clean >/dev/null 927 @$(MAKE) -C config/feature-checks clean >/dev/null
921 928
922clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 929clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
923 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 930 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
924 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 931 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
925 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 932 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
926 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 933 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c
index 9f870d27cb39..62eff847f91c 100644
--- a/tools/perf/arch/arm/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm/tests/dwarf-unwind.c
@@ -3,6 +3,7 @@
3#include "thread.h" 3#include "thread.h"
4#include "map.h" 4#include "map.h"
5#include "event.h" 5#include "event.h"
6#include "debug.h"
6#include "tests/tests.h" 7#include "tests/tests.h"
7 8
8#define STACK_SIZE 8192 9#define STACK_SIZE 8192
diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c
index 729ed69a6664..62c397ed3d97 100644
--- a/tools/perf/arch/arm/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
index e9441b9e2a30..1d3f39c3aa56 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -6,6 +6,8 @@
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) 8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_ARM64_MAX
10
9#define PERF_REG_IP PERF_REG_ARM64_PC 11#define PERF_REG_IP PERF_REG_ARM64_PC
10#define PERF_REG_SP PERF_REG_ARM64_SP 12#define PERF_REG_SP PERF_REG_ARM64_SP
11 13
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c
index 436ee43859dc..a87afa91a99e 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 42faf369211c..49776f190abf 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -12,6 +12,11 @@ const char *const arm_triplets[] = {
12 NULL 12 NULL
13}; 13};
14 14
15const char *const arm64_triplets[] = {
16 "aarch64-linux-android-",
17 NULL
18};
19
15const char *const powerpc_triplets[] = { 20const char *const powerpc_triplets[] = {
16 "powerpc-unknown-linux-gnu-", 21 "powerpc-unknown-linux-gnu-",
17 "powerpc64-unknown-linux-gnu-", 22 "powerpc64-unknown-linux-gnu-",
@@ -105,6 +110,8 @@ static const char *normalize_arch(char *arch)
105 return "x86"; 110 return "x86";
106 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) 111 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5))
107 return "sparc"; 112 return "sparc";
113 if (!strcmp(arch, "aarch64") || !strcmp(arch, "arm64"))
114 return "arm64";
108 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) 115 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
109 return "arm"; 116 return "arm";
110 if (!strncmp(arch, "s390", 4)) 117 if (!strncmp(arch, "s390", 4))
@@ -159,6 +166,8 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
159 166
160 if (!strcmp(arch, "arm")) 167 if (!strcmp(arch, "arm"))
161 path_list = arm_triplets; 168 path_list = arm_triplets;
169 else if (!strcmp(arch, "arm64"))
170 path_list = arm64_triplets;
162 else if (!strcmp(arch, "powerpc")) 171 else if (!strcmp(arch, "powerpc"))
163 path_list = powerpc_triplets; 172 path_list = powerpc_triplets;
164 else if (!strcmp(arch, "sh")) 173 else if (!strcmp(arch, "sh"))
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index b92219b1900d..6f7782bea5dd 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,6 +1,6 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
4endif 5endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o 6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index a7c23a4b3778..d73ef8bb08c7 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -15,6 +15,7 @@
15 15
16#include "util/thread.h" 16#include "util/thread.h"
17#include "util/callchain.h" 17#include "util/callchain.h"
18#include "util/debug.h"
18 19
19/* 20/*
20 * When saving the callchain on Power, the kernel conservatively saves 21 * When saving the callchain on Power, the kernel conservatively saves
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index a84206e9c4aa..fc9bebd2cca0 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -26,6 +26,7 @@ static unsigned int nsecs = 10;
26/* amount of futexes per thread */ 26/* amount of futexes per thread */
27static unsigned int nfutexes = 1024; 27static unsigned int nfutexes = 1024;
28static bool fshared = false, done = false, silent = false; 28static bool fshared = false, done = false, silent = false;
29static int futex_flag = 0;
29 30
30struct timeval start, end, runtime; 31struct timeval start, end, runtime;
31static pthread_mutex_t thread_lock; 32static pthread_mutex_t thread_lock;
@@ -75,8 +76,7 @@ static void *workerfn(void *arg)
75 * such as internal waitqueue handling, thus enlarging 76 * such as internal waitqueue handling, thus enlarging
76 * the critical region protected by hb->lock. 77 * the critical region protected by hb->lock.
77 */ 78 */
78 ret = futex_wait(&w->futex[i], 1234, NULL, 79 ret = futex_wait(&w->futex[i], 1234, NULL, futex_flag);
79 fshared ? 0 : FUTEX_PRIVATE_FLAG);
80 if (!silent && 80 if (!silent &&
81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK)) 81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK))
82 warn("Non-expected futex return call"); 82 warn("Non-expected futex return call");
@@ -135,6 +135,9 @@ int bench_futex_hash(int argc, const char **argv,
135 if (!worker) 135 if (!worker)
136 goto errmem; 136 goto errmem;
137 137
138 if (!fshared)
139 futex_flag = FUTEX_PRIVATE_FLAG;
140
138 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n", 141 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
139 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs); 142 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs);
140 143
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 732403bfd31a..bedff6b5b3cf 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -30,16 +30,18 @@ static u_int32_t futex1 = 0, futex2 = 0;
30static unsigned int nrequeue = 1; 30static unsigned int nrequeue = 1;
31 31
32static pthread_t *worker; 32static pthread_t *worker;
33static bool done = 0, silent = 0; 33static bool done = false, silent = false, fshared = false;
34static pthread_mutex_t thread_lock; 34static pthread_mutex_t thread_lock;
35static pthread_cond_t thread_parent, thread_worker; 35static pthread_cond_t thread_parent, thread_worker;
36static struct stats requeuetime_stats, requeued_stats; 36static struct stats requeuetime_stats, requeued_stats;
37static unsigned int ncpus, threads_starting, nthreads = 0; 37static unsigned int ncpus, threads_starting, nthreads = 0;
38static int futex_flag = 0;
38 39
39static const struct option options[] = { 40static const struct option options[] = {
40 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
41 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"), 42 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
42 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
44 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
43 OPT_END() 45 OPT_END()
44}; 46};
45 47
@@ -70,7 +72,7 @@ static void *workerfn(void *arg __maybe_unused)
70 pthread_cond_wait(&thread_worker, &thread_lock); 72 pthread_cond_wait(&thread_worker, &thread_lock);
71 pthread_mutex_unlock(&thread_lock); 73 pthread_mutex_unlock(&thread_lock);
72 74
73 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 75 futex_wait(&futex1, 0, NULL, futex_flag);
74 return NULL; 76 return NULL;
75} 77}
76 78
@@ -127,9 +129,12 @@ int bench_futex_requeue(int argc, const char **argv,
127 if (!worker) 129 if (!worker)
128 err(EXIT_FAILURE, "calloc"); 130 err(EXIT_FAILURE, "calloc");
129 131
130 printf("Run summary [PID %d]: Requeuing %d threads (from %p to %p), " 132 if (!fshared)
131 "%d at a time.\n\n", 133 futex_flag = FUTEX_PRIVATE_FLAG;
132 getpid(), nthreads, &futex1, &futex2, nrequeue); 134
135 printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
136 "%d at a time.\n\n", getpid(), nthreads,
137 fshared ? "shared":"private", &futex1, &futex2, nrequeue);
133 138
134 init_stats(&requeued_stats); 139 init_stats(&requeued_stats);
135 init_stats(&requeuetime_stats); 140 init_stats(&requeuetime_stats);
@@ -156,16 +161,20 @@ int bench_futex_requeue(int argc, const char **argv,
156 161
157 /* Ok, all threads are patiently blocked, start requeueing */ 162 /* Ok, all threads are patiently blocked, start requeueing */
158 gettimeofday(&start, NULL); 163 gettimeofday(&start, NULL);
159 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) 164 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
160 /* 165 /*
161 * Do not wakeup any tasks blocked on futex1, allowing 166 * Do not wakeup any tasks blocked on futex1, allowing
162 * us to really measure futex_wait functionality. 167 * us to really measure futex_wait functionality.
163 */ 168 */
164 futex_cmp_requeue(&futex1, 0, &futex2, 0, nrequeue, 169 futex_cmp_requeue(&futex1, 0, &futex2, 0,
165 FUTEX_PRIVATE_FLAG); 170 nrequeue, futex_flag);
171 }
166 gettimeofday(&end, NULL); 172 gettimeofday(&end, NULL);
167 timersub(&end, &start, &runtime); 173 timersub(&end, &start, &runtime);
168 174
175 if (nrequeued > nthreads)
176 nrequeued = nthreads;
177
169 update_stats(&requeued_stats, nrequeued); 178 update_stats(&requeued_stats, nrequeued);
170 update_stats(&requeuetime_stats, runtime.tv_usec); 179 update_stats(&requeuetime_stats, runtime.tv_usec);
171 180
@@ -175,7 +184,7 @@ int bench_futex_requeue(int argc, const char **argv,
175 } 184 }
176 185
177 /* everybody should be blocked on futex2, wake'em up */ 186 /* everybody should be blocked on futex2, wake'em up */
178 nrequeued = futex_wake(&futex2, nthreads, FUTEX_PRIVATE_FLAG); 187 nrequeued = futex_wake(&futex2, nthreads, futex_flag);
179 if (nthreads != nrequeued) 188 if (nthreads != nrequeued)
180 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads); 189 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
181 190
@@ -184,7 +193,6 @@ int bench_futex_requeue(int argc, const char **argv,
184 if (ret) 193 if (ret)
185 err(EXIT_FAILURE, "pthread_join"); 194 err(EXIT_FAILURE, "pthread_join");
186 } 195 }
187
188 } 196 }
189 197
190 /* cleanup & report results */ 198 /* cleanup & report results */
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 50022cbce87e..929f762be47e 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -31,16 +31,18 @@ static u_int32_t futex1 = 0;
31static unsigned int nwakes = 1; 31static unsigned int nwakes = 1;
32 32
33pthread_t *worker; 33pthread_t *worker;
34static bool done = false, silent = false; 34static bool done = false, silent = false, fshared = false;
35static pthread_mutex_t thread_lock; 35static pthread_mutex_t thread_lock;
36static pthread_cond_t thread_parent, thread_worker; 36static pthread_cond_t thread_parent, thread_worker;
37static struct stats waketime_stats, wakeup_stats; 37static struct stats waketime_stats, wakeup_stats;
38static unsigned int ncpus, threads_starting, nthreads = 0; 38static unsigned int ncpus, threads_starting, nthreads = 0;
39static int futex_flag = 0;
39 40
40static const struct option options[] = { 41static const struct option options[] = {
41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 42 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
42 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"), 43 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"),
43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 44 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
45 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
44 OPT_END() 46 OPT_END()
45}; 47};
46 48
@@ -58,7 +60,7 @@ static void *workerfn(void *arg __maybe_unused)
58 pthread_cond_wait(&thread_worker, &thread_lock); 60 pthread_cond_wait(&thread_worker, &thread_lock);
59 pthread_mutex_unlock(&thread_lock); 61 pthread_mutex_unlock(&thread_lock);
60 62
61 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 63 futex_wait(&futex1, 0, NULL, futex_flag);
62 return NULL; 64 return NULL;
63} 65}
64 66
@@ -130,9 +132,12 @@ int bench_futex_wake(int argc, const char **argv,
130 if (!worker) 132 if (!worker)
131 err(EXIT_FAILURE, "calloc"); 133 err(EXIT_FAILURE, "calloc");
132 134
133 printf("Run summary [PID %d]: blocking on %d threads (at futex %p), " 135 if (!fshared)
136 futex_flag = FUTEX_PRIVATE_FLAG;
137
138 printf("Run summary [PID %d]: blocking on %d threads (at [%s] futex %p), "
134 "waking up %d at a time.\n\n", 139 "waking up %d at a time.\n\n",
135 getpid(), nthreads, &futex1, nwakes); 140 getpid(), nthreads, fshared ? "shared":"private", &futex1, nwakes);
136 141
137 init_stats(&wakeup_stats); 142 init_stats(&wakeup_stats);
138 init_stats(&waketime_stats); 143 init_stats(&waketime_stats);
@@ -160,7 +165,7 @@ int bench_futex_wake(int argc, const char **argv,
160 /* Ok, all threads are patiently blocked, start waking folks up */ 165 /* Ok, all threads are patiently blocked, start waking folks up */
161 gettimeofday(&start, NULL); 166 gettimeofday(&start, NULL);
162 while (nwoken != nthreads) 167 while (nwoken != nthreads)
163 nwoken += futex_wake(&futex1, nwakes, FUTEX_PRIVATE_FLAG); 168 nwoken += futex_wake(&futex1, nwakes, futex_flag);
164 gettimeofday(&end, NULL); 169 gettimeofday(&end, NULL);
165 timersub(&end, &start, &runtime); 170 timersub(&end, &start, &runtime);
166 171
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index 52a56599a543..d7f281c2828d 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -26,7 +26,7 @@
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h> 27#include <sys/wait.h>
28#include <sys/time.h> 28#include <sys/time.h>
29#include <sys/poll.h> 29#include <poll.h>
30#include <limits.h> 30#include <limits.h>
31#include <err.h> 31#include <err.h>
32 32
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec429fef2be..be5939418425 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -36,7 +36,8 @@
36 36
37struct perf_annotate { 37struct perf_annotate {
38 struct perf_tool tool; 38 struct perf_tool tool;
39 bool force, use_tui, use_stdio, use_gtk; 39 struct perf_session *session;
40 bool use_tui, use_stdio, use_gtk;
40 bool full_paths; 41 bool full_paths;
41 bool print_line; 42 bool print_line;
42 bool skip_missing; 43 bool skip_missing;
@@ -188,18 +189,9 @@ find_next:
188static int __cmd_annotate(struct perf_annotate *ann) 189static int __cmd_annotate(struct perf_annotate *ann)
189{ 190{
190 int ret; 191 int ret;
191 struct perf_session *session; 192 struct perf_session *session = ann->session;
192 struct perf_evsel *pos; 193 struct perf_evsel *pos;
193 u64 total_nr_samples; 194 u64 total_nr_samples;
194 struct perf_data_file file = {
195 .path = input_name,
196 .mode = PERF_DATA_MODE_READ,
197 .force = ann->force,
198 };
199
200 session = perf_session__new(&file, false, &ann->tool);
201 if (session == NULL)
202 return -ENOMEM;
203 195
204 machines__set_symbol_filter(&session->machines, symbol__annotate_init); 196 machines__set_symbol_filter(&session->machines, symbol__annotate_init);
205 197
@@ -207,22 +199,22 @@ static int __cmd_annotate(struct perf_annotate *ann)
207 ret = perf_session__cpu_bitmap(session, ann->cpu_list, 199 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
208 ann->cpu_bitmap); 200 ann->cpu_bitmap);
209 if (ret) 201 if (ret)
210 goto out_delete; 202 goto out;
211 } 203 }
212 204
213 if (!objdump_path) { 205 if (!objdump_path) {
214 ret = perf_session_env__lookup_objdump(&session->header.env); 206 ret = perf_session_env__lookup_objdump(&session->header.env);
215 if (ret) 207 if (ret)
216 goto out_delete; 208 goto out;
217 } 209 }
218 210
219 ret = perf_session__process_events(session, &ann->tool); 211 ret = perf_session__process_events(session, &ann->tool);
220 if (ret) 212 if (ret)
221 goto out_delete; 213 goto out;
222 214
223 if (dump_trace) { 215 if (dump_trace) {
224 perf_session__fprintf_nr_events(session, stdout); 216 perf_session__fprintf_nr_events(session, stdout);
225 goto out_delete; 217 goto out;
226 } 218 }
227 219
228 if (verbose > 3) 220 if (verbose > 3)
@@ -250,8 +242,8 @@ static int __cmd_annotate(struct perf_annotate *ann)
250 } 242 }
251 243
252 if (total_nr_samples == 0) { 244 if (total_nr_samples == 0) {
253 ui__error("The %s file has no samples!\n", file.path); 245 ui__error("The %s file has no samples!\n", session->file->path);
254 goto out_delete; 246 goto out;
255 } 247 }
256 248
257 if (use_browser == 2) { 249 if (use_browser == 2) {
@@ -261,24 +253,12 @@ static int __cmd_annotate(struct perf_annotate *ann)
261 "perf_gtk__show_annotations"); 253 "perf_gtk__show_annotations");
262 if (show_annotations == NULL) { 254 if (show_annotations == NULL) {
263 ui__error("GTK browser not found!\n"); 255 ui__error("GTK browser not found!\n");
264 goto out_delete; 256 goto out;
265 } 257 }
266 show_annotations(); 258 show_annotations();
267 } 259 }
268 260
269out_delete: 261out:
270 /*
271 * Speed up the exit process, for large files this can
272 * take quite a while.
273 *
274 * XXX Enable this when using valgrind or if we ever
275 * librarize this command.
276 *
277 * Also experiment with obstacks to see how much speed
278 * up we'll get here.
279 *
280 * perf_session__delete(session);
281 */
282 return ret; 262 return ret;
283} 263}
284 264
@@ -297,10 +277,14 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
297 .comm = perf_event__process_comm, 277 .comm = perf_event__process_comm,
298 .exit = perf_event__process_exit, 278 .exit = perf_event__process_exit,
299 .fork = perf_event__process_fork, 279 .fork = perf_event__process_fork,
300 .ordered_samples = true, 280 .ordered_events = true,
301 .ordering_requires_timestamps = true, 281 .ordering_requires_timestamps = true,
302 }, 282 },
303 }; 283 };
284 struct perf_data_file file = {
285 .path = input_name,
286 .mode = PERF_DATA_MODE_READ,
287 };
304 const struct option options[] = { 288 const struct option options[] = {
305 OPT_STRING('i', "input", &input_name, "file", 289 OPT_STRING('i', "input", &input_name, "file",
306 "input file name"), 290 "input file name"),
@@ -308,7 +292,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
308 "only consider symbols in these dsos"), 292 "only consider symbols in these dsos"),
309 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", 293 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
310 "symbol to annotate"), 294 "symbol to annotate"),
311 OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"), 295 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
312 OPT_INCR('v', "verbose", &verbose, 296 OPT_INCR('v', "verbose", &verbose,
313 "be more verbose (show symbol address, etc)"), 297 "be more verbose (show symbol address, etc)"),
314 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 298 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
@@ -341,6 +325,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
341 "Show event group information together"), 325 "Show event group information together"),
342 OPT_END() 326 OPT_END()
343 }; 327 };
328 int ret;
344 329
345 argc = parse_options(argc, argv, options, annotate_usage, 0); 330 argc = parse_options(argc, argv, options, annotate_usage, 0);
346 331
@@ -353,11 +338,16 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
353 338
354 setup_browser(true); 339 setup_browser(true);
355 340
341 annotate.session = perf_session__new(&file, false, &annotate.tool);
342 if (annotate.session == NULL)
343 return -1;
344
356 symbol_conf.priv_size = sizeof(struct annotation); 345 symbol_conf.priv_size = sizeof(struct annotation);
357 symbol_conf.try_vmlinux_path = true; 346 symbol_conf.try_vmlinux_path = true;
358 347
359 if (symbol__init() < 0) 348 ret = symbol__init(&annotate.session->header.env);
360 return -1; 349 if (ret < 0)
350 goto out_delete;
361 351
362 if (setup_sorting() < 0) 352 if (setup_sorting() < 0)
363 usage_with_options(annotate_usage, options); 353 usage_with_options(annotate_usage, options);
@@ -373,5 +363,20 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
373 annotate.sym_hist_filter = argv[0]; 363 annotate.sym_hist_filter = argv[0];
374 } 364 }
375 365
376 return __cmd_annotate(&annotate); 366 ret = __cmd_annotate(&annotate);
367
368out_delete:
369 /*
370 * Speed up the exit process, for large files this can
371 * take quite a while.
372 *
373 * XXX Enable this when using valgrind or if we ever
374 * librarize this command.
375 *
376 * Also experiment with obstacks to see how much speed
377 * up we'll get here.
378 *
379 * perf_session__delete(session);
380 */
381 return ret;
377} 382}
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 2a2c78f80876..70385756da63 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -246,20 +246,9 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
246 return true; 246 return true;
247} 247}
248 248
249static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) 249static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *fp)
250{ 250{
251 struct perf_data_file file = {
252 .path = filename,
253 .mode = PERF_DATA_MODE_READ,
254 .force = force,
255 };
256 struct perf_session *session = perf_session__new(&file, false, NULL);
257 if (session == NULL)
258 return -1;
259
260 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); 251 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
261 perf_session__delete(session);
262
263 return 0; 252 return 0;
264} 253}
265 254
@@ -302,6 +291,12 @@ int cmd_buildid_cache(int argc, const char **argv,
302 *missing_filename = NULL, 291 *missing_filename = NULL,
303 *update_name_list_str = NULL, 292 *update_name_list_str = NULL,
304 *kcore_filename; 293 *kcore_filename;
294 char sbuf[STRERR_BUFSIZE];
295
296 struct perf_data_file file = {
297 .mode = PERF_DATA_MODE_READ,
298 };
299 struct perf_session *session = NULL;
305 300
306 const struct option buildid_cache_options[] = { 301 const struct option buildid_cache_options[] = {
307 OPT_STRING('a', "add", &add_name_list_str, 302 OPT_STRING('a', "add", &add_name_list_str,
@@ -326,8 +321,17 @@ int cmd_buildid_cache(int argc, const char **argv,
326 argc = parse_options(argc, argv, buildid_cache_options, 321 argc = parse_options(argc, argv, buildid_cache_options,
327 buildid_cache_usage, 0); 322 buildid_cache_usage, 0);
328 323
329 if (symbol__init() < 0) 324 if (missing_filename) {
330 return -1; 325 file.path = missing_filename;
326 file.force = force;
327
328 session = perf_session__new(&file, false, NULL);
329 if (session == NULL)
330 return -1;
331 }
332
333 if (symbol__init(session ? &session->header.env : NULL) < 0)
334 goto out;
331 335
332 setup_pager(); 336 setup_pager();
333 337
@@ -344,7 +348,7 @@ int cmd_buildid_cache(int argc, const char **argv,
344 continue; 348 continue;
345 } 349 }
346 pr_warning("Couldn't add %s: %s\n", 350 pr_warning("Couldn't add %s: %s\n",
347 pos->s, strerror(errno)); 351 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
348 } 352 }
349 353
350 strlist__delete(list); 354 strlist__delete(list);
@@ -362,7 +366,7 @@ int cmd_buildid_cache(int argc, const char **argv,
362 continue; 366 continue;
363 } 367 }
364 pr_warning("Couldn't remove %s: %s\n", 368 pr_warning("Couldn't remove %s: %s\n",
365 pos->s, strerror(errno)); 369 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
366 } 370 }
367 371
368 strlist__delete(list); 372 strlist__delete(list);
@@ -370,7 +374,7 @@ int cmd_buildid_cache(int argc, const char **argv,
370 } 374 }
371 375
372 if (missing_filename) 376 if (missing_filename)
373 ret = build_id_cache__fprintf_missing(missing_filename, force, stdout); 377 ret = build_id_cache__fprintf_missing(session, stdout);
374 378
375 if (update_name_list_str) { 379 if (update_name_list_str) {
376 list = strlist__new(true, update_name_list_str); 380 list = strlist__new(true, update_name_list_str);
@@ -383,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv,
383 continue; 387 continue;
384 } 388 }
385 pr_warning("Couldn't update %s: %s\n", 389 pr_warning("Couldn't update %s: %s\n",
386 pos->s, strerror(errno)); 390 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
387 } 391 }
388 392
389 strlist__delete(list); 393 strlist__delete(list);
@@ -394,5 +398,9 @@ int cmd_buildid_cache(int argc, const char **argv,
394 build_id_cache__add_kcore(kcore_filename, debugdir, force)) 398 build_id_cache__add_kcore(kcore_filename, debugdir, force))
395 pr_warning("Couldn't add %s\n", kcore_filename); 399 pr_warning("Couldn't add %s\n", kcore_filename);
396 400
401out:
402 if (session)
403 perf_session__delete(session);
404
397 return ret; 405 return ret;
398} 406}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9a5a035cb426..a3ce19f7aebd 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -360,7 +360,7 @@ static struct perf_tool tool = {
360 .exit = perf_event__process_exit, 360 .exit = perf_event__process_exit,
361 .fork = perf_event__process_fork, 361 .fork = perf_event__process_fork,
362 .lost = perf_event__process_lost, 362 .lost = perf_event__process_lost,
363 .ordered_samples = true, 363 .ordered_events = true,
364 .ordering_requires_timestamps = true, 364 .ordering_requires_timestamps = true,
365}; 365};
366 366
@@ -683,7 +683,7 @@ static int __cmd_diff(void)
683 d->session = perf_session__new(&d->file, false, &tool); 683 d->session = perf_session__new(&d->file, false, &tool);
684 if (!d->session) { 684 if (!d->session) {
685 pr_err("Failed to open %s\n", d->file.path); 685 pr_err("Failed to open %s\n", d->file.path);
686 ret = -ENOMEM; 686 ret = -1;
687 goto out_delete; 687 goto out_delete;
688 } 688 }
689 689
@@ -1143,7 +1143,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1143 1143
1144 argc = parse_options(argc, argv, options, diff_usage, 0); 1144 argc = parse_options(argc, argv, options, diff_usage, 0);
1145 1145
1146 if (symbol__init() < 0) 1146 if (symbol__init(NULL) < 0)
1147 return -1; 1147 return -1;
1148 1148
1149 if (data_init(argc, argv) < 0) 1149 if (data_init(argc, argv) < 0)
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 66e12f55c052..0f93f859b782 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -28,7 +28,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
28 28
29 session = perf_session__new(&file, 0, NULL); 29 session = perf_session__new(&file, 0, NULL);
30 if (session == NULL) 30 if (session == NULL)
31 return -ENOMEM; 31 return -1;
32 32
33 evlist__for_each(session->evlist, pos) 33 evlist__for_each(session->evlist, pos)
34 perf_evsel__fprintf(pos, details, stdout); 34 perf_evsel__fprintf(pos, details, stdout);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 0384d930480b..25d20628212e 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -103,6 +103,8 @@ static int check_emacsclient_version(void)
103 103
104static void exec_woman_emacs(const char *path, const char *page) 104static void exec_woman_emacs(const char *path, const char *page)
105{ 105{
106 char sbuf[STRERR_BUFSIZE];
107
106 if (!check_emacsclient_version()) { 108 if (!check_emacsclient_version()) {
107 /* This works only with emacsclient version >= 22. */ 109 /* This works only with emacsclient version >= 22. */
108 struct strbuf man_page = STRBUF_INIT; 110 struct strbuf man_page = STRBUF_INIT;
@@ -111,16 +113,19 @@ static void exec_woman_emacs(const char *path, const char *page)
111 path = "emacsclient"; 113 path = "emacsclient";
112 strbuf_addf(&man_page, "(woman \"%s\")", page); 114 strbuf_addf(&man_page, "(woman \"%s\")", page);
113 execlp(path, "emacsclient", "-e", man_page.buf, NULL); 115 execlp(path, "emacsclient", "-e", man_page.buf, NULL);
114 warning("failed to exec '%s': %s", path, strerror(errno)); 116 warning("failed to exec '%s': %s", path,
117 strerror_r(errno, sbuf, sizeof(sbuf)));
115 } 118 }
116} 119}
117 120
118static void exec_man_konqueror(const char *path, const char *page) 121static void exec_man_konqueror(const char *path, const char *page)
119{ 122{
120 const char *display = getenv("DISPLAY"); 123 const char *display = getenv("DISPLAY");
124
121 if (display && *display) { 125 if (display && *display) {
122 struct strbuf man_page = STRBUF_INIT; 126 struct strbuf man_page = STRBUF_INIT;
123 const char *filename = "kfmclient"; 127 const char *filename = "kfmclient";
128 char sbuf[STRERR_BUFSIZE];
124 129
125 /* It's simpler to launch konqueror using kfmclient. */ 130 /* It's simpler to launch konqueror using kfmclient. */
126 if (path) { 131 if (path) {
@@ -139,24 +144,31 @@ static void exec_man_konqueror(const char *path, const char *page)
139 path = "kfmclient"; 144 path = "kfmclient";
140 strbuf_addf(&man_page, "man:%s(1)", page); 145 strbuf_addf(&man_page, "man:%s(1)", page);
141 execlp(path, filename, "newTab", man_page.buf, NULL); 146 execlp(path, filename, "newTab", man_page.buf, NULL);
142 warning("failed to exec '%s': %s", path, strerror(errno)); 147 warning("failed to exec '%s': %s", path,
148 strerror_r(errno, sbuf, sizeof(sbuf)));
143 } 149 }
144} 150}
145 151
146static void exec_man_man(const char *path, const char *page) 152static void exec_man_man(const char *path, const char *page)
147{ 153{
154 char sbuf[STRERR_BUFSIZE];
155
148 if (!path) 156 if (!path)
149 path = "man"; 157 path = "man";
150 execlp(path, "man", page, NULL); 158 execlp(path, "man", page, NULL);
151 warning("failed to exec '%s': %s", path, strerror(errno)); 159 warning("failed to exec '%s': %s", path,
160 strerror_r(errno, sbuf, sizeof(sbuf)));
152} 161}
153 162
154static void exec_man_cmd(const char *cmd, const char *page) 163static void exec_man_cmd(const char *cmd, const char *page)
155{ 164{
156 struct strbuf shell_cmd = STRBUF_INIT; 165 struct strbuf shell_cmd = STRBUF_INIT;
166 char sbuf[STRERR_BUFSIZE];
167
157 strbuf_addf(&shell_cmd, "%s %s", cmd, page); 168 strbuf_addf(&shell_cmd, "%s %s", cmd, page);
158 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); 169 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL);
159 warning("failed to exec '%s': %s", cmd, strerror(errno)); 170 warning("failed to exec '%s': %s", cmd,
171 strerror_r(errno, sbuf, sizeof(sbuf)));
160} 172}
161 173
162static void add_man_viewer(const char *name) 174static void add_man_viewer(const char *name)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9a02807387d6..de99ca1bb942 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -23,6 +23,7 @@
23 23
24struct perf_inject { 24struct perf_inject {
25 struct perf_tool tool; 25 struct perf_tool tool;
26 struct perf_session *session;
26 bool build_ids; 27 bool build_ids;
27 bool sched_stat; 28 bool sched_stat;
28 const char *input_name; 29 const char *input_name;
@@ -340,12 +341,8 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
340 341
341static int __cmd_inject(struct perf_inject *inject) 342static int __cmd_inject(struct perf_inject *inject)
342{ 343{
343 struct perf_session *session;
344 int ret = -EINVAL; 344 int ret = -EINVAL;
345 struct perf_data_file file = { 345 struct perf_session *session = inject->session;
346 .path = inject->input_name,
347 .mode = PERF_DATA_MODE_READ,
348 };
349 struct perf_data_file *file_out = &inject->output; 346 struct perf_data_file *file_out = &inject->output;
350 347
351 signal(SIGINT, sig_handler); 348 signal(SIGINT, sig_handler);
@@ -357,16 +354,12 @@ static int __cmd_inject(struct perf_inject *inject)
357 inject->tool.tracing_data = perf_event__repipe_tracing_data; 354 inject->tool.tracing_data = perf_event__repipe_tracing_data;
358 } 355 }
359 356
360 session = perf_session__new(&file, true, &inject->tool);
361 if (session == NULL)
362 return -ENOMEM;
363
364 if (inject->build_ids) { 357 if (inject->build_ids) {
365 inject->tool.sample = perf_event__inject_buildid; 358 inject->tool.sample = perf_event__inject_buildid;
366 } else if (inject->sched_stat) { 359 } else if (inject->sched_stat) {
367 struct perf_evsel *evsel; 360 struct perf_evsel *evsel;
368 361
369 inject->tool.ordered_samples = true; 362 inject->tool.ordered_events = true;
370 363
371 evlist__for_each(session->evlist, evsel) { 364 evlist__for_each(session->evlist, evsel) {
372 const char *name = perf_evsel__name(evsel); 365 const char *name = perf_evsel__name(evsel);
@@ -396,8 +389,6 @@ static int __cmd_inject(struct perf_inject *inject)
396 perf_session__write_header(session, session->evlist, file_out->fd, true); 389 perf_session__write_header(session, session->evlist, file_out->fd, true);
397 } 390 }
398 391
399 perf_session__delete(session);
400
401 return ret; 392 return ret;
402} 393}
403 394
@@ -427,6 +418,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
427 .mode = PERF_DATA_MODE_WRITE, 418 .mode = PERF_DATA_MODE_WRITE,
428 }, 419 },
429 }; 420 };
421 struct perf_data_file file = {
422 .mode = PERF_DATA_MODE_READ,
423 };
424 int ret;
425
430 const struct option options[] = { 426 const struct option options[] = {
431 OPT_BOOLEAN('b', "build-ids", &inject.build_ids, 427 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
432 "Inject build-ids into the output stream"), 428 "Inject build-ids into the output stream"),
@@ -461,8 +457,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
461 return -1; 457 return -1;
462 } 458 }
463 459
464 if (symbol__init() < 0) 460 file.path = inject.input_name;
461 inject.session = perf_session__new(&file, true, &inject.tool);
462 if (inject.session == NULL)
463 return -1;
464
465 if (symbol__init(&inject.session->header.env) < 0)
465 return -1; 466 return -1;
466 467
467 return __cmd_inject(&inject); 468 ret = __cmd_inject(&inject);
469
470 perf_session__delete(inject.session);
471
472 return ret;
468} 473}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bef3376bfaf3..f295141025bc 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -256,7 +256,9 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
256static struct perf_tool perf_kmem = { 256static struct perf_tool perf_kmem = {
257 .sample = process_sample_event, 257 .sample = process_sample_event,
258 .comm = perf_event__process_comm, 258 .comm = perf_event__process_comm,
259 .ordered_samples = true, 259 .mmap = perf_event__process_mmap,
260 .mmap2 = perf_event__process_mmap2,
261 .ordered_events = true,
260}; 262};
261 263
262static double fragmentation(unsigned long n_req, unsigned long n_alloc) 264static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -403,10 +405,9 @@ static void sort_result(void)
403 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 405 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
404} 406}
405 407
406static int __cmd_kmem(void) 408static int __cmd_kmem(struct perf_session *session)
407{ 409{
408 int err = -EINVAL; 410 int err = -EINVAL;
409 struct perf_session *session;
410 const struct perf_evsel_str_handler kmem_tracepoints[] = { 411 const struct perf_evsel_str_handler kmem_tracepoints[] = {
411 { "kmem:kmalloc", perf_evsel__process_alloc_event, }, 412 { "kmem:kmalloc", perf_evsel__process_alloc_event, },
412 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, 413 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, },
@@ -415,34 +416,22 @@ static int __cmd_kmem(void)
415 { "kmem:kfree", perf_evsel__process_free_event, }, 416 { "kmem:kfree", perf_evsel__process_free_event, },
416 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 417 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
417 }; 418 };
418 struct perf_data_file file = {
419 .path = input_name,
420 .mode = PERF_DATA_MODE_READ,
421 };
422
423 session = perf_session__new(&file, false, &perf_kmem);
424 if (session == NULL)
425 return -ENOMEM;
426
427 if (perf_session__create_kernel_maps(session) < 0)
428 goto out_delete;
429 419
430 if (!perf_session__has_traces(session, "kmem record")) 420 if (!perf_session__has_traces(session, "kmem record"))
431 goto out_delete; 421 goto out;
432 422
433 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { 423 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) {
434 pr_err("Initializing perf session tracepoint handlers failed\n"); 424 pr_err("Initializing perf session tracepoint handlers failed\n");
435 return -1; 425 goto out;
436 } 426 }
437 427
438 setup_pager(); 428 setup_pager();
439 err = perf_session__process_events(session, &perf_kmem); 429 err = perf_session__process_events(session, &perf_kmem);
440 if (err != 0) 430 if (err != 0)
441 goto out_delete; 431 goto out;
442 sort_result(); 432 sort_result();
443 print_result(session); 433 print_result(session);
444out_delete: 434out:
445 perf_session__delete(session);
446 return err; 435 return err;
447} 436}
448 437
@@ -689,29 +678,46 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
689 NULL, 678 NULL,
690 NULL 679 NULL
691 }; 680 };
681 struct perf_session *session;
682 struct perf_data_file file = {
683 .path = input_name,
684 .mode = PERF_DATA_MODE_READ,
685 };
686 int ret = -1;
687
692 argc = parse_options_subcommand(argc, argv, kmem_options, 688 argc = parse_options_subcommand(argc, argv, kmem_options,
693 kmem_subcommands, kmem_usage, 0); 689 kmem_subcommands, kmem_usage, 0);
694 690
695 if (!argc) 691 if (!argc)
696 usage_with_options(kmem_usage, kmem_options); 692 usage_with_options(kmem_usage, kmem_options);
697 693
698 symbol__init();
699
700 if (!strncmp(argv[0], "rec", 3)) { 694 if (!strncmp(argv[0], "rec", 3)) {
695 symbol__init(NULL);
701 return __cmd_record(argc, argv); 696 return __cmd_record(argc, argv);
702 } else if (!strcmp(argv[0], "stat")) { 697 }
698
699 session = perf_session__new(&file, false, &perf_kmem);
700 if (session == NULL)
701 return -1;
702
703 symbol__init(&session->header.env);
704
705 if (!strcmp(argv[0], "stat")) {
703 if (cpu__setup_cpunode_map()) 706 if (cpu__setup_cpunode_map())
704 return -1; 707 goto out_delete;
705 708
706 if (list_empty(&caller_sort)) 709 if (list_empty(&caller_sort))
707 setup_sorting(&caller_sort, default_sort_order); 710 setup_sorting(&caller_sort, default_sort_order);
708 if (list_empty(&alloc_sort)) 711 if (list_empty(&alloc_sort))
709 setup_sorting(&alloc_sort, default_sort_order); 712 setup_sorting(&alloc_sort, default_sort_order);
710 713
711 return __cmd_kmem(); 714 ret = __cmd_kmem(session);
712 } else 715 } else
713 usage_with_options(kmem_usage, kmem_options); 716 usage_with_options(kmem_usage, kmem_options);
714 717
715 return 0; 718out_delete:
719 perf_session__delete(session);
720
721 return ret;
716} 722}
717 723
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 43367eb00510..d8bf2271f4ea 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -543,14 +543,12 @@ static void print_vcpu_info(struct perf_kvm_stat *kvm)
543 543
544 pr_info("Analyze events for "); 544 pr_info("Analyze events for ");
545 545
546 if (kvm->live) { 546 if (kvm->opts.target.system_wide)
547 if (kvm->opts.target.system_wide) 547 pr_info("all VMs, ");
548 pr_info("all VMs, "); 548 else if (kvm->opts.target.pid)
549 else if (kvm->opts.target.pid) 549 pr_info("pid(s) %s, ", kvm->opts.target.pid);
550 pr_info("pid(s) %s, ", kvm->opts.target.pid); 550 else
551 else 551 pr_info("dazed and confused on what is monitored, ");
552 pr_info("dazed and confused on what is monitored, ");
553 }
554 552
555 if (vcpu == -1) 553 if (vcpu == -1)
556 pr_info("all VCPUs:\n\n"); 554 pr_info("all VCPUs:\n\n");
@@ -592,8 +590,8 @@ static void print_result(struct perf_kvm_stat *kvm)
592 pr_info("%9s ", "Samples%"); 590 pr_info("%9s ", "Samples%");
593 591
594 pr_info("%9s ", "Time%"); 592 pr_info("%9s ", "Time%");
595 pr_info("%10s ", "Min Time"); 593 pr_info("%11s ", "Min Time");
596 pr_info("%10s ", "Max Time"); 594 pr_info("%11s ", "Max Time");
597 pr_info("%16s ", "Avg time"); 595 pr_info("%16s ", "Avg time");
598 pr_info("\n\n"); 596 pr_info("\n\n");
599 597
@@ -610,8 +608,8 @@ static void print_result(struct perf_kvm_stat *kvm)
610 pr_info("%10llu ", (unsigned long long)ecount); 608 pr_info("%10llu ", (unsigned long long)ecount);
611 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 609 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
612 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 610 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
613 pr_info("%8" PRIu64 "us ", min / 1000); 611 pr_info("%9.2fus ", (double)min / 1e3);
614 pr_info("%8" PRIu64 "us ", max / 1000); 612 pr_info("%9.2fus ", (double)max / 1e3);
615 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 613 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
616 kvm_event_rel_stddev(vcpu, event)); 614 kvm_event_rel_stddev(vcpu, event));
617 pr_info("\n"); 615 pr_info("\n");
@@ -732,7 +730,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
732 return -1; 730 return -1;
733 } 731 }
734 732
735 err = perf_session_queue_event(kvm->session, event, &sample, 0); 733 err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
736 /* 734 /*
737 * FIXME: Here we can't consume the event, as perf_session_queue_event will 735 * FIXME: Here we can't consume the event, as perf_session_queue_event will
738 * point to it, and it'll get possibly overwritten by the kernel. 736 * point to it, and it'll get possibly overwritten by the kernel.
@@ -785,7 +783,7 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
785 783
786 /* flush queue after each round in which we processed events */ 784 /* flush queue after each round in which we processed events */
787 if (ntotal) { 785 if (ntotal) {
788 kvm->session->ordered_samples.next_flush = flush_time; 786 kvm->session->ordered_events.next_flush = flush_time;
789 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); 787 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
790 if (err) { 788 if (err) {
791 if (kvm->lost_events) 789 if (kvm->lost_events)
@@ -885,15 +883,11 @@ static int fd_set_nonblock(int fd)
885 return 0; 883 return 0;
886} 884}
887 885
888static 886static int perf_kvm__handle_stdin(void)
889int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
890{ 887{
891 int c; 888 int c;
892 889
893 tcsetattr(0, TCSANOW, tc_now);
894 c = getc(stdin); 890 c = getc(stdin);
895 tcsetattr(0, TCSAFLUSH, tc_save);
896
897 if (c == 'q') 891 if (c == 'q')
898 return 1; 892 return 1;
899 893
@@ -904,7 +898,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
904{ 898{
905 struct pollfd *pollfds = NULL; 899 struct pollfd *pollfds = NULL;
906 int nr_fds, nr_stdin, ret, err = -EINVAL; 900 int nr_fds, nr_stdin, ret, err = -EINVAL;
907 struct termios tc, save; 901 struct termios save;
908 902
909 /* live flag must be set first */ 903 /* live flag must be set first */
910 kvm->live = true; 904 kvm->live = true;
@@ -919,26 +913,14 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
919 goto out; 913 goto out;
920 } 914 }
921 915
916 set_term_quiet_input(&save);
922 init_kvm_event_record(kvm); 917 init_kvm_event_record(kvm);
923 918
924 tcgetattr(0, &save);
925 tc = save;
926 tc.c_lflag &= ~(ICANON | ECHO);
927 tc.c_cc[VMIN] = 0;
928 tc.c_cc[VTIME] = 0;
929
930 signal(SIGINT, sig_handler); 919 signal(SIGINT, sig_handler);
931 signal(SIGTERM, sig_handler); 920 signal(SIGTERM, sig_handler);
932 921
933 /* copy pollfds -- need to add timerfd and stdin */ 922 /* use pollfds -- need to add timerfd and stdin */
934 nr_fds = kvm->evlist->nr_fds; 923 nr_fds = kvm->evlist->pollfd.nr;
935 pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
936 if (!pollfds) {
937 err = -ENOMEM;
938 goto out;
939 }
940 memcpy(pollfds, kvm->evlist->pollfd,
941 sizeof(struct pollfd) * kvm->evlist->nr_fds);
942 924
943 /* add timer fd */ 925 /* add timer fd */
944 if (perf_kvm__timerfd_create(kvm) < 0) { 926 if (perf_kvm__timerfd_create(kvm) < 0) {
@@ -946,17 +928,21 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
946 goto out; 928 goto out;
947 } 929 }
948 930
949 pollfds[nr_fds].fd = kvm->timerfd; 931 if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd))
950 pollfds[nr_fds].events = POLLIN; 932 goto out;
933
951 nr_fds++; 934 nr_fds++;
952 935
953 pollfds[nr_fds].fd = fileno(stdin); 936 if (perf_evlist__add_pollfd(kvm->evlist, fileno(stdin)))
954 pollfds[nr_fds].events = POLLIN; 937 goto out;
938
955 nr_stdin = nr_fds; 939 nr_stdin = nr_fds;
956 nr_fds++; 940 nr_fds++;
957 if (fd_set_nonblock(fileno(stdin)) != 0) 941 if (fd_set_nonblock(fileno(stdin)) != 0)
958 goto out; 942 goto out;
959 943
944 pollfds = kvm->evlist->pollfd.entries;
945
960 /* everything is good - enable the events and process */ 946 /* everything is good - enable the events and process */
961 perf_evlist__enable(kvm->evlist); 947 perf_evlist__enable(kvm->evlist);
962 948
@@ -972,7 +958,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
972 goto out; 958 goto out;
973 959
974 if (pollfds[nr_stdin].revents & POLLIN) 960 if (pollfds[nr_stdin].revents & POLLIN)
975 done = perf_kvm__handle_stdin(&tc, &save); 961 done = perf_kvm__handle_stdin();
976 962
977 if (!rc && !done) 963 if (!rc && !done)
978 err = poll(pollfds, nr_fds, 100); 964 err = poll(pollfds, nr_fds, 100);
@@ -989,7 +975,7 @@ out:
989 if (kvm->timerfd >= 0) 975 if (kvm->timerfd >= 0)
990 close(kvm->timerfd); 976 close(kvm->timerfd);
991 977
992 free(pollfds); 978 tcsetattr(0, TCSAFLUSH, &save);
993 return err; 979 return err;
994} 980}
995 981
@@ -998,6 +984,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
998 int err, rc = -1; 984 int err, rc = -1;
999 struct perf_evsel *pos; 985 struct perf_evsel *pos;
1000 struct perf_evlist *evlist = kvm->evlist; 986 struct perf_evlist *evlist = kvm->evlist;
987 char sbuf[STRERR_BUFSIZE];
1001 988
1002 perf_evlist__config(evlist, &kvm->opts); 989 perf_evlist__config(evlist, &kvm->opts);
1003 990
@@ -1034,12 +1021,14 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1034 1021
1035 err = perf_evlist__open(evlist); 1022 err = perf_evlist__open(evlist);
1036 if (err < 0) { 1023 if (err < 0) {
1037 printf("Couldn't create the events: %s\n", strerror(errno)); 1024 printf("Couldn't create the events: %s\n",
1025 strerror_r(errno, sbuf, sizeof(sbuf)));
1038 goto out; 1026 goto out;
1039 } 1027 }
1040 1028
1041 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { 1029 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
1042 ui__error("Failed to mmap the events: %s\n", strerror(errno)); 1030 ui__error("Failed to mmap the events: %s\n",
1031 strerror_r(errno, sbuf, sizeof(sbuf)));
1043 perf_evlist__close(evlist); 1032 perf_evlist__close(evlist);
1044 goto out; 1033 goto out;
1045 } 1034 }
@@ -1058,7 +1047,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1058 struct perf_tool eops = { 1047 struct perf_tool eops = {
1059 .sample = process_sample_event, 1048 .sample = process_sample_event,
1060 .comm = perf_event__process_comm, 1049 .comm = perf_event__process_comm,
1061 .ordered_samples = true, 1050 .ordered_events = true,
1062 }; 1051 };
1063 struct perf_data_file file = { 1052 struct perf_data_file file = {
1064 .path = kvm->file_name, 1053 .path = kvm->file_name,
@@ -1069,9 +1058,11 @@ static int read_events(struct perf_kvm_stat *kvm)
1069 kvm->session = perf_session__new(&file, false, &kvm->tool); 1058 kvm->session = perf_session__new(&file, false, &kvm->tool);
1070 if (!kvm->session) { 1059 if (!kvm->session) {
1071 pr_err("Initializing perf session failed\n"); 1060 pr_err("Initializing perf session failed\n");
1072 return -EINVAL; 1061 return -1;
1073 } 1062 }
1074 1063
1064 symbol__init(&kvm->session->header.env);
1065
1075 if (!perf_session__has_traces(kvm->session, "kvm record")) 1066 if (!perf_session__has_traces(kvm->session, "kvm record"))
1076 return -EINVAL; 1067 return -EINVAL;
1077 1068
@@ -1088,8 +1079,8 @@ static int read_events(struct perf_kvm_stat *kvm)
1088 1079
1089static int parse_target_str(struct perf_kvm_stat *kvm) 1080static int parse_target_str(struct perf_kvm_stat *kvm)
1090{ 1081{
1091 if (kvm->pid_str) { 1082 if (kvm->opts.target.pid) {
1092 kvm->pid_list = intlist__new(kvm->pid_str); 1083 kvm->pid_list = intlist__new(kvm->opts.target.pid);
1093 if (kvm->pid_list == NULL) { 1084 if (kvm->pid_list == NULL) {
1094 pr_err("Error parsing process id string\n"); 1085 pr_err("Error parsing process id string\n");
1095 return -EINVAL; 1086 return -EINVAL;
@@ -1191,7 +1182,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1191 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1182 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1192 "key for sorting: sample(sort by samples number)" 1183 "key for sorting: sample(sort by samples number)"
1193 " time (sort by avg time)"), 1184 " time (sort by avg time)"),
1194 OPT_STRING('p', "pid", &kvm->pid_str, "pid", 1185 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1195 "analyze events only for given process id(s)"), 1186 "analyze events only for given process id(s)"),
1196 OPT_END() 1187 OPT_END()
1197 }; 1188 };
@@ -1201,8 +1192,6 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1201 NULL 1192 NULL
1202 }; 1193 };
1203 1194
1204 symbol__init();
1205
1206 if (argc) { 1195 if (argc) {
1207 argc = parse_options(argc, argv, 1196 argc = parse_options(argc, argv,
1208 kvm_events_report_options, 1197 kvm_events_report_options,
@@ -1212,6 +1201,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1212 kvm_events_report_options); 1201 kvm_events_report_options);
1213 } 1202 }
1214 1203
1204 if (!kvm->opts.target.pid)
1205 kvm->opts.target.system_wide = true;
1206
1215 return kvm_events_report_vcpu(kvm); 1207 return kvm_events_report_vcpu(kvm);
1216} 1208}
1217 1209
@@ -1311,7 +1303,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1311 kvm->tool.exit = perf_event__process_exit; 1303 kvm->tool.exit = perf_event__process_exit;
1312 kvm->tool.fork = perf_event__process_fork; 1304 kvm->tool.fork = perf_event__process_fork;
1313 kvm->tool.lost = process_lost_event; 1305 kvm->tool.lost = process_lost_event;
1314 kvm->tool.ordered_samples = true; 1306 kvm->tool.ordered_events = true;
1315 perf_tool__fill_defaults(&kvm->tool); 1307 perf_tool__fill_defaults(&kvm->tool);
1316 1308
1317 /* set defaults */ 1309 /* set defaults */
@@ -1322,7 +1314,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1322 kvm->opts.target.uid_str = NULL; 1314 kvm->opts.target.uid_str = NULL;
1323 kvm->opts.target.uid = UINT_MAX; 1315 kvm->opts.target.uid = UINT_MAX;
1324 1316
1325 symbol__init(); 1317 symbol__init(NULL);
1326 disable_buildid_cache(); 1318 disable_buildid_cache();
1327 1319
1328 use_browser = 0; 1320 use_browser = 0;
@@ -1369,7 +1361,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1369 */ 1361 */
1370 kvm->session = perf_session__new(&file, false, &kvm->tool); 1362 kvm->session = perf_session__new(&file, false, &kvm->tool);
1371 if (kvm->session == NULL) { 1363 if (kvm->session == NULL) {
1372 err = -ENOMEM; 1364 err = -1;
1373 goto out; 1365 goto out;
1374 } 1366 }
1375 kvm->session->evlist = kvm->evlist; 1367 kvm->session->evlist = kvm->evlist;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6148afc995c6..e7ec71589da6 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -852,7 +852,7 @@ static int __cmd_report(bool display_info)
852 struct perf_tool eops = { 852 struct perf_tool eops = {
853 .sample = process_sample_event, 853 .sample = process_sample_event,
854 .comm = perf_event__process_comm, 854 .comm = perf_event__process_comm,
855 .ordered_samples = true, 855 .ordered_events = true,
856 }; 856 };
857 struct perf_data_file file = { 857 struct perf_data_file file = {
858 .path = input_name, 858 .path = input_name,
@@ -862,9 +862,11 @@ static int __cmd_report(bool display_info)
862 session = perf_session__new(&file, false, &eops); 862 session = perf_session__new(&file, false, &eops);
863 if (!session) { 863 if (!session) {
864 pr_err("Initializing perf session failed\n"); 864 pr_err("Initializing perf session failed\n");
865 return -ENOMEM; 865 return -1;
866 } 866 }
867 867
868 symbol__init(&session->header.env);
869
868 if (!perf_session__has_traces(session, "lock record")) 870 if (!perf_session__has_traces(session, "lock record"))
869 goto out_delete; 871 goto out_delete;
870 872
@@ -974,7 +976,6 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
974 unsigned int i; 976 unsigned int i;
975 int rc = 0; 977 int rc = 0;
976 978
977 symbol__init();
978 for (i = 0; i < LOCKHASH_SIZE; i++) 979 for (i = 0; i < LOCKHASH_SIZE; i++)
979 INIT_LIST_HEAD(lockhash_table + i); 980 INIT_LIST_HEAD(lockhash_table + i);
980 981
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 4a1a6c94a5eb..24db6ffe2957 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -124,7 +124,7 @@ static int report_raw_events(struct perf_mem *mem)
124 &mem->tool); 124 &mem->tool);
125 125
126 if (session == NULL) 126 if (session == NULL)
127 return -ENOMEM; 127 return -1;
128 128
129 if (mem->cpu_list) { 129 if (mem->cpu_list) {
130 ret = perf_session__cpu_bitmap(session, mem->cpu_list, 130 ret = perf_session__cpu_bitmap(session, mem->cpu_list,
@@ -133,7 +133,7 @@ static int report_raw_events(struct perf_mem *mem)
133 goto out_delete; 133 goto out_delete;
134 } 134 }
135 135
136 if (symbol__init() < 0) 136 if (symbol__init(&session->header.env) < 0)
137 return -1; 137 return -1;
138 138
139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
@@ -194,7 +194,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
194 .lost = perf_event__process_lost, 194 .lost = perf_event__process_lost,
195 .fork = perf_event__process_fork, 195 .fork = perf_event__process_fork,
196 .build_id = perf_event__process_build_id, 196 .build_id = perf_event__process_build_id,
197 .ordered_samples = true, 197 .ordered_events = true,
198 }, 198 },
199 .input_name = "perf.data", 199 .input_name = "perf.data",
200 }; 200 };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c63fa2925075..04412b4770a2 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -290,8 +290,11 @@ static void cleanup_params(void)
290 290
291static void pr_err_with_code(const char *msg, int err) 291static void pr_err_with_code(const char *msg, int err)
292{ 292{
293 char sbuf[STRERR_BUFSIZE];
294
293 pr_err("%s", msg); 295 pr_err("%s", msg);
294 pr_debug(" Reason: %s (Code: %d)", strerror(-err), err); 296 pr_debug(" Reason: %s (Code: %d)",
297 strerror_r(-err, sbuf, sizeof(sbuf)), err);
295 pr_err("\n"); 298 pr_err("\n");
296} 299}
297 300
@@ -373,6 +376,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
373 "target executable name or path", opt_set_target), 376 "target executable name or path", opt_set_target),
374 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 377 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
375 "Disable symbol demangling"), 378 "Disable symbol demangling"),
379 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
380 "Enable kernel symbol demangling"),
376 OPT_END() 381 OPT_END()
377 }; 382 };
378 int ret; 383 int ret;
@@ -467,7 +472,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
467 usage_with_options(probe_usage, options); 472 usage_with_options(probe_usage, options);
468 } 473 }
469 474
470 ret = show_line_range(&params.line_range, params.target); 475 ret = show_line_range(&params.line_range, params.target,
476 params.uprobes);
471 if (ret < 0) 477 if (ret < 0)
472 pr_err_with_code(" Error: Failed to show lines.", ret); 478 pr_err_with_code(" Error: Failed to show lines.", ret);
473 return ret; 479 return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4869050e7194..44c6f3d55ce7 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -65,8 +65,9 @@ static int process_synthesized_event(struct perf_tool *tool,
65 return record__write(rec, event, event->header.size); 65 return record__write(rec, event, event->header.size);
66} 66}
67 67
68static int record__mmap_read(struct record *rec, struct perf_mmap *md) 68static int record__mmap_read(struct record *rec, int idx)
69{ 69{
70 struct perf_mmap *md = &rec->evlist->mmap[idx];
70 unsigned int head = perf_mmap__read_head(md); 71 unsigned int head = perf_mmap__read_head(md);
71 unsigned int old = md->prev; 72 unsigned int old = md->prev;
72 unsigned char *data = md->base + page_size; 73 unsigned char *data = md->base + page_size;
@@ -102,8 +103,7 @@ static int record__mmap_read(struct record *rec, struct perf_mmap *md)
102 } 103 }
103 104
104 md->prev = old; 105 md->prev = old;
105 perf_mmap__write_tail(md, old); 106 perf_evlist__mmap_consume(rec->evlist, idx);
106
107out: 107out:
108 return rc; 108 return rc;
109} 109}
@@ -161,7 +161,7 @@ try_again:
161 161
162 if (perf_evlist__apply_filters(evlist)) { 162 if (perf_evlist__apply_filters(evlist)) {
163 error("failed to set filter with %d (%s)\n", errno, 163 error("failed to set filter with %d (%s)\n", errno,
164 strerror(errno)); 164 strerror_r(errno, msg, sizeof(msg)));
165 rc = -1; 165 rc = -1;
166 goto out; 166 goto out;
167 } 167 }
@@ -175,7 +175,8 @@ try_again:
175 "(current value: %u)\n", opts->mmap_pages); 175 "(current value: %u)\n", opts->mmap_pages);
176 rc = -errno; 176 rc = -errno;
177 } else { 177 } else {
178 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 178 pr_err("failed to mmap with %d (%s)\n", errno,
179 strerror_r(errno, msg, sizeof(msg)));
179 rc = -errno; 180 rc = -errno;
180 } 181 }
181 goto out; 182 goto out;
@@ -244,7 +245,7 @@ static int record__mmap_read_all(struct record *rec)
244 245
245 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 246 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
246 if (rec->evlist->mmap[i].base) { 247 if (rec->evlist->mmap[i].base) {
247 if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 248 if (record__mmap_read(rec, i) != 0) {
248 rc = -1; 249 rc = -1;
249 goto out; 250 goto out;
250 } 251 }
@@ -307,7 +308,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
307 struct record_opts *opts = &rec->opts; 308 struct record_opts *opts = &rec->opts;
308 struct perf_data_file *file = &rec->file; 309 struct perf_data_file *file = &rec->file;
309 struct perf_session *session; 310 struct perf_session *session;
310 bool disabled = false; 311 bool disabled = false, draining = false;
311 312
312 rec->progname = argv[0]; 313 rec->progname = argv[0];
313 314
@@ -456,9 +457,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
456 } 457 }
457 458
458 if (hits == rec->samples) { 459 if (hits == rec->samples) {
459 if (done) 460 if (done || draining)
460 break; 461 break;
461 err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1); 462 err = perf_evlist__poll(rec->evlist, -1);
462 /* 463 /*
463 * Propagate error, only if there's any. Ignore positive 464 * Propagate error, only if there's any. Ignore positive
464 * number of returned events and interrupt error. 465 * number of returned events and interrupt error.
@@ -466,6 +467,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
466 if (err > 0 || (err < 0 && errno == EINTR)) 467 if (err > 0 || (err < 0 && errno == EINTR))
467 err = 0; 468 err = 0;
468 waking++; 469 waking++;
470
471 if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
472 draining = true;
469 } 473 }
470 474
471 /* 475 /*
@@ -480,7 +484,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
480 } 484 }
481 485
482 if (forks && workload_exec_errno) { 486 if (forks && workload_exec_errno) {
483 char msg[512]; 487 char msg[STRERR_BUFSIZE];
484 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 488 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
485 pr_err("Workload failed: %s\n", emsg); 489 pr_err("Workload failed: %s\n", emsg);
486 err = -1; 490 err = -1;
@@ -620,145 +624,56 @@ error:
620 return ret; 624 return ret;
621} 625}
622 626
623#ifdef HAVE_DWARF_UNWIND_SUPPORT 627static void callchain_debug(void)
624static int get_stack_size(char *str, unsigned long *_size)
625{
626 char *endptr;
627 unsigned long size;
628 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
629
630 size = strtoul(str, &endptr, 0);
631
632 do {
633 if (*endptr)
634 break;
635
636 size = round_up(size, sizeof(u64));
637 if (!size || size > max_size)
638 break;
639
640 *_size = size;
641 return 0;
642
643 } while (0);
644
645 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
646 max_size, str);
647 return -1;
648}
649#endif /* HAVE_DWARF_UNWIND_SUPPORT */
650
651int record_parse_callchain(const char *arg, struct record_opts *opts)
652{
653 char *tok, *name, *saveptr = NULL;
654 char *buf;
655 int ret = -1;
656
657 /* We need buffer that we know we can write to. */
658 buf = malloc(strlen(arg) + 1);
659 if (!buf)
660 return -ENOMEM;
661
662 strcpy(buf, arg);
663
664 tok = strtok_r((char *)buf, ",", &saveptr);
665 name = tok ? : (char *)buf;
666
667 do {
668 /* Framepointer style */
669 if (!strncmp(name, "fp", sizeof("fp"))) {
670 if (!strtok_r(NULL, ",", &saveptr)) {
671 opts->call_graph = CALLCHAIN_FP;
672 ret = 0;
673 } else
674 pr_err("callchain: No more arguments "
675 "needed for -g fp\n");
676 break;
677
678#ifdef HAVE_DWARF_UNWIND_SUPPORT
679 /* Dwarf style */
680 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
681 const unsigned long default_stack_dump_size = 8192;
682
683 ret = 0;
684 opts->call_graph = CALLCHAIN_DWARF;
685 opts->stack_dump_size = default_stack_dump_size;
686
687 tok = strtok_r(NULL, ",", &saveptr);
688 if (tok) {
689 unsigned long size = 0;
690
691 ret = get_stack_size(tok, &size);
692 opts->stack_dump_size = size;
693 }
694#endif /* HAVE_DWARF_UNWIND_SUPPORT */
695 } else {
696 pr_err("callchain: Unknown --call-graph option "
697 "value: %s\n", arg);
698 break;
699 }
700
701 } while (0);
702
703 free(buf);
704 return ret;
705}
706
707static void callchain_debug(struct record_opts *opts)
708{ 628{
709 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" }; 629 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
710 630
711 pr_debug("callchain: type %s\n", str[opts->call_graph]); 631 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
712 632
713 if (opts->call_graph == CALLCHAIN_DWARF) 633 if (callchain_param.record_mode == CALLCHAIN_DWARF)
714 pr_debug("callchain: stack dump size %d\n", 634 pr_debug("callchain: stack dump size %d\n",
715 opts->stack_dump_size); 635 callchain_param.dump_size);
716} 636}
717 637
718int record_parse_callchain_opt(const struct option *opt, 638int record_parse_callchain_opt(const struct option *opt __maybe_unused,
719 const char *arg, 639 const char *arg,
720 int unset) 640 int unset)
721{ 641{
722 struct record_opts *opts = opt->value;
723 int ret; 642 int ret;
724 643
725 opts->call_graph_enabled = !unset; 644 callchain_param.enabled = !unset;
726 645
727 /* --no-call-graph */ 646 /* --no-call-graph */
728 if (unset) { 647 if (unset) {
729 opts->call_graph = CALLCHAIN_NONE; 648 callchain_param.record_mode = CALLCHAIN_NONE;
730 pr_debug("callchain: disabled\n"); 649 pr_debug("callchain: disabled\n");
731 return 0; 650 return 0;
732 } 651 }
733 652
734 ret = record_parse_callchain(arg, opts); 653 ret = parse_callchain_record_opt(arg);
735 if (!ret) 654 if (!ret)
736 callchain_debug(opts); 655 callchain_debug();
737 656
738 return ret; 657 return ret;
739} 658}
740 659
741int record_callchain_opt(const struct option *opt, 660int record_callchain_opt(const struct option *opt __maybe_unused,
742 const char *arg __maybe_unused, 661 const char *arg __maybe_unused,
743 int unset __maybe_unused) 662 int unset __maybe_unused)
744{ 663{
745 struct record_opts *opts = opt->value; 664 callchain_param.enabled = true;
746 665
747 opts->call_graph_enabled = !unset; 666 if (callchain_param.record_mode == CALLCHAIN_NONE)
667 callchain_param.record_mode = CALLCHAIN_FP;
748 668
749 if (opts->call_graph == CALLCHAIN_NONE) 669 callchain_debug();
750 opts->call_graph = CALLCHAIN_FP;
751
752 callchain_debug(opts);
753 return 0; 670 return 0;
754} 671}
755 672
756static int perf_record_config(const char *var, const char *value, void *cb) 673static int perf_record_config(const char *var, const char *value, void *cb)
757{ 674{
758 struct record *rec = cb;
759
760 if (!strcmp(var, "record.call-graph")) 675 if (!strcmp(var, "record.call-graph"))
761 return record_parse_callchain(value, &rec->opts); 676 var = "call-graph.record-mode"; /* fall-through */
762 677
763 return perf_default_config(var, value, cb); 678 return perf_default_config(var, value, cb);
764} 679}
@@ -781,6 +696,7 @@ static const char * const record_usage[] = {
781 */ 696 */
782static struct record record = { 697static struct record record = {
783 .opts = { 698 .opts = {
699 .sample_time = true,
784 .mmap_pages = UINT_MAX, 700 .mmap_pages = UINT_MAX,
785 .user_freq = UINT_MAX, 701 .user_freq = UINT_MAX,
786 .user_interval = ULLONG_MAX, 702 .user_interval = ULLONG_MAX,
@@ -907,7 +823,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
907 usage_with_options(record_usage, record_options); 823 usage_with_options(record_usage, record_options);
908 } 824 }
909 825
910 symbol__init(); 826 symbol__init(NULL);
911 827
912 if (symbol_conf.kptr_restrict) 828 if (symbol_conf.kptr_restrict)
913 pr_warning( 829 pr_warning(
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 21d830bafff3..ac145fae0521 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -58,17 +58,19 @@ struct report {
58 const char *symbol_filter_str; 58 const char *symbol_filter_str;
59 float min_percent; 59 float min_percent;
60 u64 nr_entries; 60 u64 nr_entries;
61 u64 queue_size;
61 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 62 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
62}; 63};
63 64
64static int report__config(const char *var, const char *value, void *cb) 65static int report__config(const char *var, const char *value, void *cb)
65{ 66{
67 struct report *rep = cb;
68
66 if (!strcmp(var, "report.group")) { 69 if (!strcmp(var, "report.group")) {
67 symbol_conf.event_group = perf_config_bool(var, value); 70 symbol_conf.event_group = perf_config_bool(var, value);
68 return 0; 71 return 0;
69 } 72 }
70 if (!strcmp(var, "report.percent-limit")) { 73 if (!strcmp(var, "report.percent-limit")) {
71 struct report *rep = cb;
72 rep->min_percent = strtof(value, NULL); 74 rep->min_percent = strtof(value, NULL);
73 return 0; 75 return 0;
74 } 76 }
@@ -76,6 +78,10 @@ static int report__config(const char *var, const char *value, void *cb)
76 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 78 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
77 return 0; 79 return 0;
78 } 80 }
81 if (!strcmp(var, "report.queue-size")) {
82 rep->queue_size = perf_config_u64(var, value);
83 return 0;
84 }
79 85
80 return perf_default_config(var, value, cb); 86 return perf_default_config(var, value, cb);
81} 87}
@@ -578,7 +584,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
578 .attr = perf_event__process_attr, 584 .attr = perf_event__process_attr,
579 .tracing_data = perf_event__process_tracing_data, 585 .tracing_data = perf_event__process_tracing_data,
580 .build_id = perf_event__process_build_id, 586 .build_id = perf_event__process_build_id,
581 .ordered_samples = true, 587 .ordered_events = true,
582 .ordering_requires_timestamps = true, 588 .ordering_requires_timestamps = true,
583 }, 589 },
584 .max_stack = PERF_MAX_STACK_DEPTH, 590 .max_stack = PERF_MAX_STACK_DEPTH,
@@ -674,6 +680,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
674 "objdump binary to use for disassembly and annotations"), 680 "objdump binary to use for disassembly and annotations"),
675 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 681 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
676 "Disable symbol demangling"), 682 "Disable symbol demangling"),
683 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
684 "Enable kernel symbol demangling"),
677 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 685 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
678 OPT_CALLBACK(0, "percent-limit", &report, "percent", 686 OPT_CALLBACK(0, "percent-limit", &report, "percent",
679 "Don't show entries under that percent", parse_percent_limit), 687 "Don't show entries under that percent", parse_percent_limit),
@@ -712,14 +720,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
712repeat: 720repeat:
713 session = perf_session__new(&file, false, &report.tool); 721 session = perf_session__new(&file, false, &report.tool);
714 if (session == NULL) 722 if (session == NULL)
715 return -ENOMEM; 723 return -1;
724
725 if (report.queue_size) {
726 ordered_events__set_alloc_size(&session->ordered_events,
727 report.queue_size);
728 }
716 729
717 report.session = session; 730 report.session = session;
718 731
719 has_br_stack = perf_header__has_feat(&session->header, 732 has_br_stack = perf_header__has_feat(&session->header,
720 HEADER_BRANCH_STACK); 733 HEADER_BRANCH_STACK);
721 734
722 if (branch_mode == -1 && has_br_stack) { 735 if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) {
723 sort__mode = SORT_MODE__BRANCH; 736 sort__mode = SORT_MODE__BRANCH;
724 symbol_conf.cumulate_callchain = false; 737 symbol_conf.cumulate_callchain = false;
725 } 738 }
@@ -787,7 +800,7 @@ repeat:
787 } 800 }
788 } 801 }
789 802
790 if (symbol__init() < 0) 803 if (symbol__init(&session->header.env) < 0)
791 goto error; 804 goto error;
792 805
793 if (argc) { 806 if (argc) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index f83c08c0dd87..9c9287fbf8e9 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -428,6 +428,7 @@ static u64 get_cpu_usage_nsec_parent(void)
428static int self_open_counters(void) 428static int self_open_counters(void)
429{ 429{
430 struct perf_event_attr attr; 430 struct perf_event_attr attr;
431 char sbuf[STRERR_BUFSIZE];
431 int fd; 432 int fd;
432 433
433 memset(&attr, 0, sizeof(attr)); 434 memset(&attr, 0, sizeof(attr));
@@ -440,7 +441,8 @@ static int self_open_counters(void)
440 441
441 if (fd < 0) 442 if (fd < 0)
442 pr_err("Error: sys_perf_event_open() syscall returned " 443 pr_err("Error: sys_perf_event_open() syscall returned "
443 "with %d (%s)\n", fd, strerror(errno)); 444 "with %d (%s)\n", fd,
445 strerror_r(errno, sbuf, sizeof(sbuf)));
444 return fd; 446 return fd;
445} 447}
446 448
@@ -1462,6 +1464,8 @@ static int perf_sched__read_events(struct perf_sched *sched,
1462 return -1; 1464 return -1;
1463 } 1465 }
1464 1466
1467 symbol__init(&session->header.env);
1468
1465 if (perf_session__set_tracepoints_handlers(session, handlers)) 1469 if (perf_session__set_tracepoints_handlers(session, handlers))
1466 goto out_delete; 1470 goto out_delete;
1467 1471
@@ -1662,7 +1666,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1662 .comm = perf_event__process_comm, 1666 .comm = perf_event__process_comm,
1663 .lost = perf_event__process_lost, 1667 .lost = perf_event__process_lost,
1664 .fork = perf_sched__process_fork_event, 1668 .fork = perf_sched__process_fork_event,
1665 .ordered_samples = true, 1669 .ordered_events = true,
1666 }, 1670 },
1667 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), 1671 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1668 .sort_list = LIST_HEAD_INIT(sched.sort_list), 1672 .sort_list = LIST_HEAD_INIT(sched.sort_list),
@@ -1747,7 +1751,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1747 if (!strcmp(argv[0], "script")) 1751 if (!strcmp(argv[0], "script"))
1748 return cmd_script(argc, argv, prefix); 1752 return cmd_script(argc, argv, prefix);
1749 1753
1750 symbol__init();
1751 if (!strncmp(argv[0], "rec", 3)) { 1754 if (!strncmp(argv[0], "rec", 3)) {
1752 return __cmd_record(argc, argv); 1755 return __cmd_record(argc, argv);
1753 } else if (!strncmp(argv[0], "lat", 3)) { 1756 } else if (!strncmp(argv[0], "lat", 3)) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index f57035b89c15..b9b9e58a6c39 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -184,10 +184,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", 184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
185 PERF_OUTPUT_IP)) 185 PERF_OUTPUT_IP))
186 return -EINVAL; 186 return -EINVAL;
187
188 if (!no_callchain &&
189 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
190 symbol_conf.use_callchain = false;
191 } 187 }
192 188
193 if (PRINT_FIELD(ADDR) && 189 if (PRINT_FIELD(ADDR) &&
@@ -290,6 +286,19 @@ static int perf_session__check_output_opt(struct perf_session *session)
290 set_print_ip_opts(&evsel->attr); 286 set_print_ip_opts(&evsel->attr);
291 } 287 }
292 288
289 if (!no_callchain) {
290 bool use_callchain = false;
291
292 evlist__for_each(session->evlist, evsel) {
293 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
294 use_callchain = true;
295 break;
296 }
297 }
298 if (!use_callchain)
299 symbol_conf.use_callchain = false;
300 }
301
293 /* 302 /*
294 * set default for tracepoints to print symbols only 303 * set default for tracepoints to print symbols only
295 * if callchains are present 304 * if callchains are present
@@ -476,6 +485,11 @@ static int default_start_script(const char *script __maybe_unused,
476 return 0; 485 return 0;
477} 486}
478 487
488static int default_flush_script(void)
489{
490 return 0;
491}
492
479static int default_stop_script(void) 493static int default_stop_script(void)
480{ 494{
481 return 0; 495 return 0;
@@ -489,6 +503,7 @@ static int default_generate_script(struct pevent *pevent __maybe_unused,
489 503
490static struct scripting_ops default_scripting_ops = { 504static struct scripting_ops default_scripting_ops = {
491 .start_script = default_start_script, 505 .start_script = default_start_script,
506 .flush_script = default_flush_script,
492 .stop_script = default_stop_script, 507 .stop_script = default_stop_script,
493 .process_event = process_event, 508 .process_event = process_event,
494 .generate_script = default_generate_script, 509 .generate_script = default_generate_script,
@@ -504,6 +519,11 @@ static void setup_scripting(void)
504 scripting_ops = &default_scripting_ops; 519 scripting_ops = &default_scripting_ops;
505} 520}
506 521
522static int flush_scripting(void)
523{
524 return scripting_ops->flush_script();
525}
526
507static int cleanup_scripting(void) 527static int cleanup_scripting(void)
508{ 528{
509 pr_debug("\nperf script stopped\n"); 529 pr_debug("\nperf script stopped\n");
@@ -1471,12 +1491,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1471 bool show_full_info = false; 1491 bool show_full_info = false;
1472 bool header = false; 1492 bool header = false;
1473 bool header_only = false; 1493 bool header_only = false;
1494 bool script_started = false;
1474 char *rec_script_path = NULL; 1495 char *rec_script_path = NULL;
1475 char *rep_script_path = NULL; 1496 char *rep_script_path = NULL;
1476 struct perf_session *session; 1497 struct perf_session *session;
1477 char *script_path = NULL; 1498 char *script_path = NULL;
1478 const char **__argv; 1499 const char **__argv;
1479 int i, j, err; 1500 int i, j, err = 0;
1480 struct perf_script script = { 1501 struct perf_script script = {
1481 .tool = { 1502 .tool = {
1482 .sample = process_sample_event, 1503 .sample = process_sample_event,
@@ -1488,7 +1509,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1488 .attr = process_attr, 1509 .attr = process_attr,
1489 .tracing_data = perf_event__process_tracing_data, 1510 .tracing_data = perf_event__process_tracing_data,
1490 .build_id = perf_event__process_build_id, 1511 .build_id = perf_event__process_build_id,
1491 .ordered_samples = true, 1512 .ordered_events = true,
1492 .ordering_requires_timestamps = true, 1513 .ordering_requires_timestamps = true,
1493 }, 1514 },
1494 }; 1515 };
@@ -1718,26 +1739,28 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1718 exit(-1); 1739 exit(-1);
1719 } 1740 }
1720 1741
1721 if (symbol__init() < 0)
1722 return -1;
1723 if (!script_name) 1742 if (!script_name)
1724 setup_pager(); 1743 setup_pager();
1725 1744
1726 session = perf_session__new(&file, false, &script.tool); 1745 session = perf_session__new(&file, false, &script.tool);
1727 if (session == NULL) 1746 if (session == NULL)
1728 return -ENOMEM; 1747 return -1;
1729 1748
1730 if (header || header_only) { 1749 if (header || header_only) {
1731 perf_session__fprintf_info(session, stdout, show_full_info); 1750 perf_session__fprintf_info(session, stdout, show_full_info);
1732 if (header_only) 1751 if (header_only)
1733 return 0; 1752 goto out_delete;
1734 } 1753 }
1735 1754
1755 if (symbol__init(&session->header.env) < 0)
1756 goto out_delete;
1757
1736 script.session = session; 1758 script.session = session;
1737 1759
1738 if (cpu_list) { 1760 if (cpu_list) {
1739 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1761 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
1740 return -1; 1762 if (err < 0)
1763 goto out_delete;
1741 } 1764 }
1742 1765
1743 if (!no_callchain) 1766 if (!no_callchain)
@@ -1752,53 +1775,62 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1752 if (output_set_by_user()) { 1775 if (output_set_by_user()) {
1753 fprintf(stderr, 1776 fprintf(stderr,
1754 "custom fields not supported for generated scripts"); 1777 "custom fields not supported for generated scripts");
1755 return -1; 1778 err = -EINVAL;
1779 goto out_delete;
1756 } 1780 }
1757 1781
1758 input = open(file.path, O_RDONLY); /* input_name */ 1782 input = open(file.path, O_RDONLY); /* input_name */
1759 if (input < 0) { 1783 if (input < 0) {
1784 err = -errno;
1760 perror("failed to open file"); 1785 perror("failed to open file");
1761 return -1; 1786 goto out_delete;
1762 } 1787 }
1763 1788
1764 err = fstat(input, &perf_stat); 1789 err = fstat(input, &perf_stat);
1765 if (err < 0) { 1790 if (err < 0) {
1766 perror("failed to stat file"); 1791 perror("failed to stat file");
1767 return -1; 1792 goto out_delete;
1768 } 1793 }
1769 1794
1770 if (!perf_stat.st_size) { 1795 if (!perf_stat.st_size) {
1771 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1796 fprintf(stderr, "zero-sized file, nothing to do!\n");
1772 return 0; 1797 goto out_delete;
1773 } 1798 }
1774 1799
1775 scripting_ops = script_spec__lookup(generate_script_lang); 1800 scripting_ops = script_spec__lookup(generate_script_lang);
1776 if (!scripting_ops) { 1801 if (!scripting_ops) {
1777 fprintf(stderr, "invalid language specifier"); 1802 fprintf(stderr, "invalid language specifier");
1778 return -1; 1803 err = -ENOENT;
1804 goto out_delete;
1779 } 1805 }
1780 1806
1781 err = scripting_ops->generate_script(session->tevent.pevent, 1807 err = scripting_ops->generate_script(session->tevent.pevent,
1782 "perf-script"); 1808 "perf-script");
1783 goto out; 1809 goto out_delete;
1784 } 1810 }
1785 1811
1786 if (script_name) { 1812 if (script_name) {
1787 err = scripting_ops->start_script(script_name, argc, argv); 1813 err = scripting_ops->start_script(script_name, argc, argv);
1788 if (err) 1814 if (err)
1789 goto out; 1815 goto out_delete;
1790 pr_debug("perf script started with script %s\n\n", script_name); 1816 pr_debug("perf script started with script %s\n\n", script_name);
1817 script_started = true;
1791 } 1818 }
1792 1819
1793 1820
1794 err = perf_session__check_output_opt(session); 1821 err = perf_session__check_output_opt(session);
1795 if (err < 0) 1822 if (err < 0)
1796 goto out; 1823 goto out_delete;
1797 1824
1798 err = __cmd_script(&script); 1825 err = __cmd_script(&script);
1799 1826
1827 flush_scripting();
1828
1829out_delete:
1800 perf_session__delete(session); 1830 perf_session__delete(session);
1801 cleanup_scripting(); 1831
1832 if (script_started)
1833 cleanup_scripting();
1802out: 1834out:
1803 return err; 1835 return err;
1804} 1836}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3e80aa10cfd8..b22c62f80078 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -593,7 +593,7 @@ static int __run_perf_stat(int argc, const char **argv)
593 593
594 if (perf_evlist__apply_filters(evsel_list)) { 594 if (perf_evlist__apply_filters(evsel_list)) {
595 error("failed to set filter with %d (%s)\n", errno, 595 error("failed to set filter with %d (%s)\n", errno,
596 strerror(errno)); 596 strerror_r(errno, msg, sizeof(msg)));
597 return -1; 597 return -1;
598 } 598 }
599 599
@@ -732,7 +732,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
732 } 732 }
733} 733}
734 734
735static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 735static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
736{ 736{
737 double msecs = avg / 1e6; 737 double msecs = avg / 1e6;
738 const char *fmt_v, *fmt_n; 738 const char *fmt_v, *fmt_n;
@@ -741,7 +741,7 @@ static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
741 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s"; 741 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
742 fmt_n = csv_output ? "%s" : "%-25s"; 742 fmt_n = csv_output ? "%s" : "%-25s";
743 743
744 aggr_printout(evsel, cpu, nr); 744 aggr_printout(evsel, id, nr);
745 745
746 scnprintf(name, sizeof(name), "%s%s", 746 scnprintf(name, sizeof(name), "%s%s",
747 perf_evsel__name(evsel), csv_output ? "" : " (msec)"); 747 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
@@ -947,11 +947,12 @@ static void print_ll_cache_misses(int cpu,
947 fprintf(output, " of all LL-cache hits "); 947 fprintf(output, " of all LL-cache hits ");
948} 948}
949 949
950static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 950static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
951{ 951{
952 double total, ratio = 0.0, total2; 952 double total, ratio = 0.0, total2;
953 double sc = evsel->scale; 953 double sc = evsel->scale;
954 const char *fmt; 954 const char *fmt;
955 int cpu = cpu_map__id_to_cpu(id);
955 956
956 if (csv_output) { 957 if (csv_output) {
957 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; 958 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
@@ -962,7 +963,7 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
962 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; 963 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
963 } 964 }
964 965
965 aggr_printout(evsel, cpu, nr); 966 aggr_printout(evsel, id, nr);
966 967
967 if (aggr_mode == AGGR_GLOBAL) 968 if (aggr_mode == AGGR_GLOBAL)
968 cpu = 0; 969 cpu = 0;
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 2f1a5220c090..35b425b6293f 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1605,7 +1605,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1605 int ret = -EINVAL; 1605 int ret = -EINVAL;
1606 1606
1607 if (session == NULL) 1607 if (session == NULL)
1608 return -ENOMEM; 1608 return -1;
1609
1610 symbol__init(&session->header.env);
1609 1611
1610 (void)perf_header__process_sections(&session->header, 1612 (void)perf_header__process_sections(&session->header,
1611 perf_data_file__fd(session->file), 1613 perf_data_file__fd(session->file),
@@ -1920,7 +1922,7 @@ int cmd_timechart(int argc, const char **argv,
1920 .fork = process_fork_event, 1922 .fork = process_fork_event,
1921 .exit = process_exit_event, 1923 .exit = process_exit_event,
1922 .sample = process_sample_event, 1924 .sample = process_sample_event,
1923 .ordered_samples = true, 1925 .ordered_events = true,
1924 }, 1926 },
1925 .proc_num = 15, 1927 .proc_num = 15,
1926 .min_time = 1000000, 1928 .min_time = 1000000,
@@ -1982,8 +1984,6 @@ int cmd_timechart(int argc, const char **argv,
1982 return -1; 1984 return -1;
1983 } 1985 }
1984 1986
1985 symbol__init();
1986
1987 if (argc && !strncmp(argv[0], "rec", 3)) { 1987 if (argc && !strncmp(argv[0], "rec", 3)) {
1988 argc = parse_options(argc, argv, record_options, record_usage, 1988 argc = parse_options(argc, argv, record_options, record_usage,
1989 PARSE_OPT_STOP_AT_NON_OPTION); 1989 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 377971dc89a3..fc3d55f832ac 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -59,7 +59,7 @@
59 59
60#include <sys/syscall.h> 60#include <sys/syscall.h>
61#include <sys/ioctl.h> 61#include <sys/ioctl.h>
62#include <sys/poll.h> 62#include <poll.h>
63#include <sys/prctl.h> 63#include <sys/prctl.h>
64#include <sys/wait.h> 64#include <sys/wait.h>
65#include <sys/uio.h> 65#include <sys/uio.h>
@@ -276,11 +276,17 @@ static void perf_top__print_sym_table(struct perf_top *top)
276 return; 276 return;
277 } 277 }
278 278
279 if (top->zero) {
280 hists__delete_entries(&top->sym_evsel->hists);
281 } else {
282 hists__decay_entries(&top->sym_evsel->hists,
283 top->hide_user_symbols,
284 top->hide_kernel_symbols);
285 }
286
279 hists__collapse_resort(&top->sym_evsel->hists, NULL); 287 hists__collapse_resort(&top->sym_evsel->hists, NULL);
280 hists__output_resort(&top->sym_evsel->hists); 288 hists__output_resort(&top->sym_evsel->hists);
281 hists__decay_entries(&top->sym_evsel->hists, 289
282 top->hide_user_symbols,
283 top->hide_kernel_symbols);
284 hists__output_recalc_col_len(&top->sym_evsel->hists, 290 hists__output_recalc_col_len(&top->sym_evsel->hists,
285 top->print_entries - printed); 291 top->print_entries - printed);
286 putchar('\n'); 292 putchar('\n');
@@ -427,18 +433,13 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
427 433
428 if (!perf_top__key_mapped(top, c)) { 434 if (!perf_top__key_mapped(top, c)) {
429 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 435 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
430 struct termios tc, save; 436 struct termios save;
431 437
432 perf_top__print_mapped_keys(top); 438 perf_top__print_mapped_keys(top);
433 fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 439 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
434 fflush(stdout); 440 fflush(stdout);
435 441
436 tcgetattr(0, &save); 442 set_term_quiet_input(&save);
437 tc = save;
438 tc.c_lflag &= ~(ICANON | ECHO);
439 tc.c_cc[VMIN] = 0;
440 tc.c_cc[VTIME] = 0;
441 tcsetattr(0, TCSANOW, &tc);
442 443
443 poll(&stdin_poll, 1, -1); 444 poll(&stdin_poll, 1, -1);
444 c = getc(stdin); 445 c = getc(stdin);
@@ -542,11 +543,16 @@ static void perf_top__sort_new_samples(void *arg)
542 if (t->evlist->selected != NULL) 543 if (t->evlist->selected != NULL)
543 t->sym_evsel = t->evlist->selected; 544 t->sym_evsel = t->evlist->selected;
544 545
546 if (t->zero) {
547 hists__delete_entries(&t->sym_evsel->hists);
548 } else {
549 hists__decay_entries(&t->sym_evsel->hists,
550 t->hide_user_symbols,
551 t->hide_kernel_symbols);
552 }
553
545 hists__collapse_resort(&t->sym_evsel->hists, NULL); 554 hists__collapse_resort(&t->sym_evsel->hists, NULL);
546 hists__output_resort(&t->sym_evsel->hists); 555 hists__output_resort(&t->sym_evsel->hists);
547 hists__decay_entries(&t->sym_evsel->hists,
548 t->hide_user_symbols,
549 t->hide_kernel_symbols);
550} 556}
551 557
552static void *display_thread_tui(void *arg) 558static void *display_thread_tui(void *arg)
@@ -577,23 +583,32 @@ static void *display_thread_tui(void *arg)
577 return NULL; 583 return NULL;
578} 584}
579 585
586static void display_sig(int sig __maybe_unused)
587{
588 done = 1;
589}
590
591static void display_setup_sig(void)
592{
593 signal(SIGSEGV, display_sig);
594 signal(SIGFPE, display_sig);
595 signal(SIGINT, display_sig);
596 signal(SIGQUIT, display_sig);
597 signal(SIGTERM, display_sig);
598}
599
580static void *display_thread(void *arg) 600static void *display_thread(void *arg)
581{ 601{
582 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 602 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
583 struct termios tc, save; 603 struct termios save;
584 struct perf_top *top = arg; 604 struct perf_top *top = arg;
585 int delay_msecs, c; 605 int delay_msecs, c;
586 606
587 tcgetattr(0, &save); 607 display_setup_sig();
588 tc = save;
589 tc.c_lflag &= ~(ICANON | ECHO);
590 tc.c_cc[VMIN] = 0;
591 tc.c_cc[VTIME] = 0;
592
593 pthread__unblock_sigwinch(); 608 pthread__unblock_sigwinch();
594repeat: 609repeat:
595 delay_msecs = top->delay_secs * 1000; 610 delay_msecs = top->delay_secs * 1000;
596 tcsetattr(0, TCSANOW, &tc); 611 set_term_quiet_input(&save);
597 /* trash return*/ 612 /* trash return*/
598 getc(stdin); 613 getc(stdin);
599 614
@@ -620,13 +635,16 @@ repeat:
620 } 635 }
621 } 636 }
622 637
638 tcsetattr(0, TCSAFLUSH, &save);
623 return NULL; 639 return NULL;
624} 640}
625 641
626static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) 642static int symbol_filter(struct map *map, struct symbol *sym)
627{ 643{
628 const char *name = sym->name; 644 const char *name = sym->name;
629 645
646 if (!map->dso->kernel)
647 return 0;
630 /* 648 /*
631 * ppc64 uses function descriptors and appends a '.' to the 649 * ppc64 uses function descriptors and appends a '.' to the
632 * start of every instruction address. Remove it. 650 * start of every instruction address. Remove it.
@@ -876,7 +894,7 @@ try_again:
876 894
877 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 895 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
878 ui__error("Failed to mmap with %d (%s)\n", 896 ui__error("Failed to mmap with %d (%s)\n",
879 errno, strerror(errno)); 897 errno, strerror_r(errno, msg, sizeof(msg)));
880 goto out_err; 898 goto out_err;
881 } 899 }
882 900
@@ -911,7 +929,7 @@ static int __cmd_top(struct perf_top *top)
911 929
912 top->session = perf_session__new(NULL, false, NULL); 930 top->session = perf_session__new(NULL, false, NULL);
913 if (top->session == NULL) 931 if (top->session == NULL)
914 return -ENOMEM; 932 return -1;
915 933
916 machines__set_symbol_filter(&top->session->machines, symbol_filter); 934 machines__set_symbol_filter(&top->session->machines, symbol_filter);
917 935
@@ -946,7 +964,7 @@ static int __cmd_top(struct perf_top *top)
946 perf_evlist__enable(top->evlist); 964 perf_evlist__enable(top->evlist);
947 965
948 /* Wait for a minimal set of events before starting the snapshot */ 966 /* Wait for a minimal set of events before starting the snapshot */
949 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 967 perf_evlist__poll(top->evlist, 100);
950 968
951 perf_top__mmap_read(top); 969 perf_top__mmap_read(top);
952 970
@@ -963,7 +981,7 @@ static int __cmd_top(struct perf_top *top)
963 param.sched_priority = top->realtime_prio; 981 param.sched_priority = top->realtime_prio;
964 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 982 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
965 ui__error("Could not set realtime priority.\n"); 983 ui__error("Could not set realtime priority.\n");
966 goto out_delete; 984 goto out_join;
967 } 985 }
968 } 986 }
969 987
@@ -973,10 +991,12 @@ static int __cmd_top(struct perf_top *top)
973 perf_top__mmap_read(top); 991 perf_top__mmap_read(top);
974 992
975 if (hits == top->samples) 993 if (hits == top->samples)
976 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 994 ret = perf_evlist__poll(top->evlist, 100);
977 } 995 }
978 996
979 ret = 0; 997 ret = 0;
998out_join:
999 pthread_join(thread, NULL);
980out_delete: 1000out_delete:
981 perf_session__delete(top->session); 1001 perf_session__delete(top->session);
982 top->session = NULL; 1002 top->session = NULL;
@@ -1000,10 +1020,8 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1000 1020
1001static int perf_top_config(const char *var, const char *value, void *cb) 1021static int perf_top_config(const char *var, const char *value, void *cb)
1002{ 1022{
1003 struct perf_top *top = cb;
1004
1005 if (!strcmp(var, "top.call-graph")) 1023 if (!strcmp(var, "top.call-graph"))
1006 return record_parse_callchain(value, &top->record_opts); 1024 var = "call-graph.record-mode"; /* fall-through */
1007 if (!strcmp(var, "top.children")) { 1025 if (!strcmp(var, "top.children")) {
1008 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1026 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1009 return 0; 1027 return 0;
@@ -1122,6 +1140,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1122 "Interleave source code with assembly code (default)"), 1140 "Interleave source code with assembly code (default)"),
1123 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1141 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
1124 "Display raw encoding of assembly instructions (default)"), 1142 "Display raw encoding of assembly instructions (default)"),
1143 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1144 "Enable kernel symbol demangling"),
1125 OPT_STRING(0, "objdump", &objdump_path, "path", 1145 OPT_STRING(0, "objdump", &objdump_path, "path",
1126 "objdump binary to use for disassembly and annotations"), 1146 "objdump binary to use for disassembly and annotations"),
1127 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1147 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
@@ -1131,6 +1151,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1131 "Don't show entries under that percent", parse_percent_limit), 1151 "Don't show entries under that percent", parse_percent_limit),
1132 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1152 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1133 "How to display percentage of filtered entries", parse_filter_percentage), 1153 "How to display percentage of filtered entries", parse_filter_percentage),
1154 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
1155 "width[,width...]",
1156 "don't try to adjust column width, use these fixed values"),
1134 OPT_END() 1157 OPT_END()
1135 }; 1158 };
1136 const char * const top_usage[] = { 1159 const char * const top_usage[] = {
@@ -1217,7 +1240,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1217 symbol_conf.priv_size = sizeof(struct annotation); 1240 symbol_conf.priv_size = sizeof(struct annotation);
1218 1241
1219 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1242 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1220 if (symbol__init() < 0) 1243 if (symbol__init(NULL) < 0)
1221 return -1; 1244 return -1;
1222 1245
1223 sort__setup_elide(stdout); 1246 sort__setup_elide(stdout);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a6c375224f46..09bcf2393910 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -402,6 +402,31 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
402 402
403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
404 404
405static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
406 struct syscall_arg *arg)
407{
408 int printed = 0, flags = arg->val;
409
410#define P_MREMAP_FLAG(n) \
411 if (flags & MREMAP_##n) { \
412 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
413 flags &= ~MREMAP_##n; \
414 }
415
416 P_MREMAP_FLAG(MAYMOVE);
417#ifdef MREMAP_FIXED
418 P_MREMAP_FLAG(FIXED);
419#endif
420#undef P_MREMAP_FLAG
421
422 if (flags)
423 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
424
425 return printed;
426}
427
428#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
429
405static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 430static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
406 struct syscall_arg *arg) 431 struct syscall_arg *arg)
407{ 432{
@@ -1004,6 +1029,7 @@ static struct syscall_fmt {
1004 [2] = SCA_MMAP_PROT, /* prot */ }, }, 1029 [2] = SCA_MMAP_PROT, /* prot */ }, },
1005 { .name = "mremap", .hexret = true, 1030 { .name = "mremap", .hexret = true,
1006 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 1031 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
1032 [3] = SCA_MREMAP_FLAGS, /* flags */
1007 [4] = SCA_HEX, /* new_addr */ }, }, 1033 [4] = SCA_HEX, /* new_addr */ }, },
1008 { .name = "munlock", .errmsg = true, 1034 { .name = "munlock", .errmsg = true,
1009 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1035 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
@@ -1385,7 +1411,7 @@ static int trace__tool_process(struct perf_tool *tool,
1385 1411
1386static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1412static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1387{ 1413{
1388 int err = symbol__init(); 1414 int err = symbol__init(NULL);
1389 1415
1390 if (err) 1416 if (err)
1391 return err; 1417 return err;
@@ -1669,7 +1695,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1669 union perf_event *event __maybe_unused, 1695 union perf_event *event __maybe_unused,
1670 struct perf_sample *sample) 1696 struct perf_sample *sample)
1671{ 1697{
1672 int ret; 1698 long ret;
1673 u64 duration = 0; 1699 u64 duration = 0;
1674 struct thread *thread; 1700 struct thread *thread;
1675 int id = perf_evsel__sc_tp_uint(evsel, id, sample); 1701 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
@@ -1722,9 +1748,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1722 1748
1723 if (sc->fmt == NULL) { 1749 if (sc->fmt == NULL) {
1724signed_print: 1750signed_print:
1725 fprintf(trace->output, ") = %d", ret); 1751 fprintf(trace->output, ") = %ld", ret);
1726 } else if (ret < 0 && sc->fmt->errmsg) { 1752 } else if (ret < 0 && sc->fmt->errmsg) {
1727 char bf[256]; 1753 char bf[STRERR_BUFSIZE];
1728 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1754 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1729 *e = audit_errno_to_name(-ret); 1755 *e = audit_errno_to_name(-ret);
1730 1756
@@ -1732,7 +1758,7 @@ signed_print:
1732 } else if (ret == 0 && sc->fmt->timeout) 1758 } else if (ret == 0 && sc->fmt->timeout)
1733 fprintf(trace->output, ") = 0 Timeout"); 1759 fprintf(trace->output, ") = 0 Timeout");
1734 else if (sc->fmt->hexret) 1760 else if (sc->fmt->hexret)
1735 fprintf(trace->output, ") = %#x", ret); 1761 fprintf(trace->output, ") = %#lx", ret);
1736 else 1762 else
1737 goto signed_print; 1763 goto signed_print;
1738 1764
@@ -2018,6 +2044,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2018 int err = -1, i; 2044 int err = -1, i;
2019 unsigned long before; 2045 unsigned long before;
2020 const bool forks = argc > 0; 2046 const bool forks = argc > 0;
2047 bool draining = false;
2048 char sbuf[STRERR_BUFSIZE];
2021 2049
2022 trace->live = true; 2050 trace->live = true;
2023 2051
@@ -2079,7 +2107,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2079 2107
2080 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2108 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2081 if (err < 0) { 2109 if (err < 0) {
2082 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); 2110 fprintf(trace->output, "Couldn't mmap the events: %s\n",
2111 strerror_r(errno, sbuf, sizeof(sbuf)));
2083 goto out_delete_evlist; 2112 goto out_delete_evlist;
2084 } 2113 }
2085 2114
@@ -2143,8 +2172,12 @@ next_event:
2143 if (trace->nr_events == before) { 2172 if (trace->nr_events == before) {
2144 int timeout = done ? 100 : -1; 2173 int timeout = done ? 100 : -1;
2145 2174
2146 if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0) 2175 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2176 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2177 draining = true;
2178
2147 goto again; 2179 goto again;
2180 }
2148 } else { 2181 } else {
2149 goto again; 2182 goto again;
2150 } 2183 }
@@ -2209,18 +2242,18 @@ static int trace__replay(struct trace *trace)
2209 trace->tool.tracing_data = perf_event__process_tracing_data; 2242 trace->tool.tracing_data = perf_event__process_tracing_data;
2210 trace->tool.build_id = perf_event__process_build_id; 2243 trace->tool.build_id = perf_event__process_build_id;
2211 2244
2212 trace->tool.ordered_samples = true; 2245 trace->tool.ordered_events = true;
2213 trace->tool.ordering_requires_timestamps = true; 2246 trace->tool.ordering_requires_timestamps = true;
2214 2247
2215 /* add tid to output */ 2248 /* add tid to output */
2216 trace->multiple_threads = true; 2249 trace->multiple_threads = true;
2217 2250
2218 if (symbol__init() < 0)
2219 return -1;
2220
2221 session = perf_session__new(&file, false, &trace->tool); 2251 session = perf_session__new(&file, false, &trace->tool);
2222 if (session == NULL) 2252 if (session == NULL)
2223 return -ENOMEM; 2253 return -1;
2254
2255 if (symbol__init(&session->header.env) < 0)
2256 goto out;
2224 2257
2225 trace->host = &session->machines.host; 2258 trace->host = &session->machines.host;
2226 2259
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1f67aa02d240..58f609198c6d 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -48,10 +48,6 @@ ifneq ($(ARCH),$(filter $(ARCH),x86 arm))
48 NO_LIBDW_DWARF_UNWIND := 1 48 NO_LIBDW_DWARF_UNWIND := 1
49endif 49endif
50 50
51ifeq ($(ARCH),powerpc)
52 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
53endif
54
55ifeq ($(LIBUNWIND_LIBS),) 51ifeq ($(LIBUNWIND_LIBS),)
56 NO_LIBUNWIND := 1 52 NO_LIBUNWIND := 1
57else 53else
@@ -120,6 +116,29 @@ ifdef PARSER_DEBUG
120 CFLAGS += -DPARSER_DEBUG 116 CFLAGS += -DPARSER_DEBUG
121endif 117endif
122 118
119ifndef NO_LIBPYTHON
120 # Try different combinations to accommodate systems that only have
121 # python[2][-config] in weird combinations but always preferring
122 # python2 and python2-config as per pep-0394. If we catch a
123 # python[-config] in version 3, the version check will kill it.
124 PYTHON2 := $(if $(call get-executable,python2),python2,python)
125 override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2))
126 PYTHON2_CONFIG := \
127 $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config)
128 override PYTHON_CONFIG := \
129 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
130
131 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
132
133 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
134 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
135
136 FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
137 FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
138 FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
139 FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
140endif
141
123CFLAGS += -fno-omit-frame-pointer 142CFLAGS += -fno-omit-frame-pointer
124CFLAGS += -ggdb3 143CFLAGS += -ggdb3
125CFLAGS += -funwind-tables 144CFLAGS += -funwind-tables
@@ -355,6 +374,12 @@ ifndef NO_LIBELF
355 endif # NO_DWARF 374 endif # NO_DWARF
356endif # NO_LIBELF 375endif # NO_LIBELF
357 376
377ifeq ($(ARCH),powerpc)
378 ifndef NO_DWARF
379 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
380 endif
381endif
382
358ifndef NO_LIBUNWIND 383ifndef NO_LIBUNWIND
359 ifneq ($(feature-libunwind), 1) 384 ifneq ($(feature-libunwind), 1)
360 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); 385 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
@@ -482,21 +507,14 @@ define disable-python_code
482 NO_LIBPYTHON := 1 507 NO_LIBPYTHON := 1
483endef 508endef
484 509
485override PYTHON := \ 510ifdef NO_LIBPYTHON
486 $(call get-executable-or-default,PYTHON,python) 511 $(call disable-python)
487
488ifndef PYTHON
489 $(call disable-python,python interpreter)
490else 512else
491 513
492 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 514 ifndef PYTHON
493 515 $(call disable-python,python interpreter)
494 ifdef NO_LIBPYTHON
495 $(call disable-python)
496 else 516 else
497 517 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
498 override PYTHON_CONFIG := \
499 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config)
500 518
501 ifndef PYTHON_CONFIG 519 ifndef PYTHON_CONFIG
502 $(call disable-python,python-config tool) 520 $(call disable-python,python-config tool)
@@ -635,11 +653,13 @@ else
635sysconfdir = $(prefix)/etc 653sysconfdir = $(prefix)/etc
636ETC_PERFCONFIG = etc/perfconfig 654ETC_PERFCONFIG = etc/perfconfig
637endif 655endif
656ifndef lib
638ifeq ($(IS_X86_64),1) 657ifeq ($(IS_X86_64),1)
639lib = lib64 658lib = lib64
640else 659else
641lib = lib 660lib = lib
642endif 661endif
662endif # lib
643libdir = $(prefix)/$(lib) 663libdir = $(prefix)/$(lib)
644 664
645# Shell quote (do not use $(call) to accommodate ancient setups); 665# Shell quote (do not use $(call) to accommodate ancient setups);
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 6088f8d8a434..72ab2984718e 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -101,25 +101,11 @@ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
101test-libperl.bin: 101test-libperl.bin:
102 $(BUILD) $(FLAGS_PERL_EMBED) 102 $(BUILD) $(FLAGS_PERL_EMBED)
103 103
104override PYTHON := python
105override PYTHON_CONFIG := python-config
106
107escape-for-shell-sq = $(subst ','\'',$(1))
108shell-sq = '$(escape-for-shell-sq)'
109
110PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
111
112PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
113PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
114PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
115PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
116FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
117
118test-libpython.bin: 104test-libpython.bin:
119 $(BUILD) $(FLAGS_PYTHON_EMBED) 105 $(BUILD)
120 106
121test-libpython-version.bin: 107test-libpython-version.bin:
122 $(BUILD) $(FLAGS_PYTHON_EMBED) 108 $(BUILD)
123 109
124test-libbfd.bin: 110test-libbfd.bin:
125 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 111 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 4d985e0f03f5..7076a62d0ff7 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -132,7 +132,7 @@ endef
132# 132#
133# Usage: bool-value = $(call is-absolute,path) 133# Usage: bool-value = $(call is-absolute,path)
134# 134#
135is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y) 135is-absolute = $(shell echo $(shell-sq) | grep -q ^/ && echo y)
136 136
137# lookup 137# lookup
138# 138#
diff --git a/tools/perf/perf-with-kcore.sh b/tools/perf/perf-with-kcore.sh
new file mode 100644
index 000000000000..c7ff90a90e4e
--- /dev/null
+++ b/tools/perf/perf-with-kcore.sh
@@ -0,0 +1,259 @@
1#!/bin/bash
2# perf-with-kcore: use perf with a copy of kcore
3# Copyright (c) 2014, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13
14set -e
15
16usage()
17{
18 echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
19 echo " <perf sub-command> can be record, script, report or inject" >&2
20 echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2
21 exit 1
22}
23
24find_perf()
25{
26 if [ -n "$PERF" ] ; then
27 return
28 fi
29 PERF=`which perf || true`
30 if [ -z "$PERF" ] ; then
31 echo "Failed to find perf" >&2
32 exit 1
33 fi
34 if [ ! -x "$PERF" ] ; then
35 echo "Failed to find perf" >&2
36 exit 1
37 fi
38 echo "Using $PERF"
39 "$PERF" version
40}
41
42copy_kcore()
43{
44 echo "Copying kcore"
45
46 if [ $EUID -eq 0 ] ; then
47 SUDO=""
48 else
49 SUDO="sudo"
50 fi
51
52 rm -f perf.data.junk
53 ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null &
54 PERF_PID=$!
55
56 # Need to make sure that perf has started
57 sleep 1
58
59 KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
60 case "$KCORE" in
61 "kcore added to build-id cache directory "*)
62 KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
63 ;;
64 *)
65 kill $PERF_PID
66 wait >/dev/null 2>/dev/null || true
67 rm perf.data.junk
68 echo "$KCORE"
69 echo "Failed to find kcore" >&2
70 exit 1
71 ;;
72 esac
73
74 kill $PERF_PID
75 wait >/dev/null 2>/dev/null || true
76 rm perf.data.junk
77
78 $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
79 $SUDO rm -f "$KCORE_DIR/kcore"
80 $SUDO rm -f "$KCORE_DIR/kallsyms"
81 $SUDO rm -f "$KCORE_DIR/modules"
82 $SUDO rmdir "$KCORE_DIR"
83
84 KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
85 KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
86
87 $SUDO chown $UID "$KCORE_DIR"
88 $SUDO chown $UID "$KCORE_DIR/kcore"
89 $SUDO chown $UID "$KCORE_DIR/kallsyms"
90 $SUDO chown $UID "$KCORE_DIR/modules"
91
92 $SUDO chgrp $GROUPS "$KCORE_DIR"
93 $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
94 $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
95 $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
96
97 ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
98}
99
100fix_buildid_cache_permissions()
101{
102 if [ $EUID -ne 0 ] ; then
103 echo "This script must be run as root via sudo " >&2
104 exit 1
105 fi
106
107 if [ -z "$SUDO_USER" ] ; then
108 echo "This script must be run via sudo" >&2
109 exit 1
110 fi
111
112 USER_HOME=$(bash <<< "echo ~$SUDO_USER")
113
114 if [ "$HOME" != "$USER_HOME" ] ; then
115 echo "Fix unnecessary because root has a home: $HOME" >&2
116 exit 1
117 fi
118
119 echo "Fixing buildid cache permissions"
120
121 find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
122 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
123 find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
124
125 if [ -n "$SUDO_GID" ] ; then
126 find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
127 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
128 find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
129 fi
130
131 echo "Done"
132}
133
134check_buildid_cache_permissions()
135{
136 if [ $EUID -eq 0 ] ; then
137 return
138 fi
139
140 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit)
141 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
142 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit)
143
144 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit)
145 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
146 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit)
147
148 if [ -n "$PERMISSIONS_OK" ] ; then
149 echo "*** WARNING *** buildid cache permissions may need fixing" >&2
150 fi
151}
152
153record()
154{
155 echo "Recording"
156
157 if [ $EUID -ne 0 ] ; then
158
159 if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
160 echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
161 fi
162
163 if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
164 echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
165 fi
166
167 if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
168 if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
169 echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
170 fi
171
172 if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
173 true
174 elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
175 true
176 elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
177 echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
178 fi
179 fi
180 fi
181
182 if [ -z "$1" ] ; then
183 echo "Workload is required for recording" >&2
184 usage
185 fi
186
187 if [ -e "$PERF_DATA_DIR" ] ; then
188 echo "'$PERF_DATA_DIR' exists" >&2
189 exit 1
190 fi
191
192 find_perf
193
194 mkdir "$PERF_DATA_DIR"
195
196 echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*"
197 "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true
198
199 if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
200 exit 1
201 fi
202
203 copy_kcore
204
205 echo "Done"
206}
207
208subcommand()
209{
210 find_perf
211 check_buildid_cache_permissions
212 echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*"
213 "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $*
214}
215
216if [ "$1" = "fix_buildid_cache_permissions" ] ; then
217 fix_buildid_cache_permissions
218 exit 0
219fi
220
221PERF_SUB_COMMAND=$1
222PERF_DATA_DIR=$2
223shift || true
224shift || true
225
226if [ -z "$PERF_SUB_COMMAND" ] ; then
227 usage
228fi
229
230if [ -z "$PERF_DATA_DIR" ] ; then
231 usage
232fi
233
234case "$PERF_SUB_COMMAND" in
235"record")
236 while [ "$1" != "--" ] ; do
237 PERF_OPTIONS+="$1 "
238 shift || break
239 done
240 if [ "$1" != "--" ] ; then
241 echo "Options and workload are required for recording" >&2
242 usage
243 fi
244 shift
245 record $*
246;;
247"script")
248 subcommand $*
249;;
250"report")
251 subcommand $*
252;;
253"inject")
254 subcommand $*
255;;
256*)
257 usage
258;;
259esac
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 2282d41879a2..452a8474d29d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -313,6 +313,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
313 int status; 313 int status;
314 struct stat st; 314 struct stat st;
315 const char *prefix; 315 const char *prefix;
316 char sbuf[STRERR_BUFSIZE];
316 317
317 prefix = NULL; 318 prefix = NULL;
318 if (p->option & RUN_SETUP) 319 if (p->option & RUN_SETUP)
@@ -343,7 +344,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
343 status = 1; 344 status = 1;
344 /* Check for ENOSPC and EIO errors.. */ 345 /* Check for ENOSPC and EIO errors.. */
345 if (fflush(stdout)) { 346 if (fflush(stdout)) {
346 fprintf(stderr, "write failure on standard output: %s", strerror(errno)); 347 fprintf(stderr, "write failure on standard output: %s",
348 strerror_r(errno, sbuf, sizeof(sbuf)));
347 goto out; 349 goto out;
348 } 350 }
349 if (ferror(stdout)) { 351 if (ferror(stdout)) {
@@ -351,7 +353,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
351 goto out; 353 goto out;
352 } 354 }
353 if (fclose(stdout)) { 355 if (fclose(stdout)) {
354 fprintf(stderr, "close failed on standard output: %s", strerror(errno)); 356 fprintf(stderr, "close failed on standard output: %s",
357 strerror_r(errno, sbuf, sizeof(sbuf)));
355 goto out; 358 goto out;
356 } 359 }
357 status = 0; 360 status = 0;
@@ -466,6 +469,7 @@ void pthread__unblock_sigwinch(void)
466int main(int argc, const char **argv) 469int main(int argc, const char **argv)
467{ 470{
468 const char *cmd; 471 const char *cmd;
472 char sbuf[STRERR_BUFSIZE];
469 473
470 /* The page_size is placed in util object. */ 474 /* The page_size is placed in util object. */
471 page_size = sysconf(_SC_PAGE_SIZE); 475 page_size = sysconf(_SC_PAGE_SIZE);
@@ -561,7 +565,7 @@ int main(int argc, const char **argv)
561 } 565 }
562 566
563 fprintf(stderr, "Failed to run command '%s': %s\n", 567 fprintf(stderr, "Failed to run command '%s': %s\n",
564 cmd, strerror(errno)); 568 cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
565out: 569out:
566 return 1; 570 return 1;
567} 571}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 510c65f72858..220d44e44c1b 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -41,8 +41,6 @@ void pthread__unblock_sigwinch(void);
41 41
42struct record_opts { 42struct record_opts {
43 struct target target; 43 struct target target;
44 int call_graph;
45 bool call_graph_enabled;
46 bool group; 44 bool group;
47 bool inherit_stat; 45 bool inherit_stat;
48 bool no_buffering; 46 bool no_buffering;
@@ -60,7 +58,6 @@ struct record_opts {
60 u64 branch_stack; 58 u64 branch_stack;
61 u64 default_interval; 59 u64 default_interval;
62 u64 user_interval; 60 u64 user_interval;
63 u16 stack_dump_size;
64 bool sample_transaction; 61 bool sample_transaction;
65 unsigned initial_delay; 62 unsigned initial_delay;
66}; 63};
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6f8b01bc6033..ac655b0700e7 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -154,6 +154,18 @@ static struct test {
154 .func = test__hists_cumulate, 154 .func = test__hists_cumulate,
155 }, 155 },
156 { 156 {
157 .desc = "Test tracking with sched_switch",
158 .func = test__switch_tracking,
159 },
160 {
161 .desc = "Filter fds with revents mask in a fdarray",
162 .func = test__fdarray__filter,
163 },
164 {
165 .desc = "Add fd to a fdarray, making it autogrow",
166 .func = test__fdarray__add,
167 },
168 {
157 .func = NULL, 169 .func = NULL,
158 }, 170 },
159}; 171};
@@ -185,9 +197,11 @@ static bool perf_test__matches(int curr, int argc, const char *argv[])
185static int run_test(struct test *test) 197static int run_test(struct test *test)
186{ 198{
187 int status, err = -1, child = fork(); 199 int status, err = -1, child = fork();
200 char sbuf[STRERR_BUFSIZE];
188 201
189 if (child < 0) { 202 if (child < 0) {
190 pr_err("failed to fork test: %s\n", strerror(errno)); 203 pr_err("failed to fork test: %s\n",
204 strerror_r(errno, sbuf, sizeof(sbuf)));
191 return -1; 205 return -1;
192 } 206 }
193 207
@@ -297,7 +311,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
297 symbol_conf.sort_by_name = true; 311 symbol_conf.sort_by_name = true;
298 symbol_conf.try_vmlinux_path = true; 312 symbol_conf.try_vmlinux_path = true;
299 313
300 if (symbol__init() < 0) 314 if (symbol__init(NULL) < 0)
301 return -1; 315 return -1;
302 316
303 if (skip != NULL) 317 if (skip != NULL)
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
new file mode 100644
index 000000000000..d24b837951d4
--- /dev/null
+++ b/tools/perf/tests/fdarray.c
@@ -0,0 +1,174 @@
1#include <api/fd/array.h>
2#include "util/debug.h"
3#include "tests/tests.h"
4
5static void fdarray__init_revents(struct fdarray *fda, short revents)
6{
7 int fd;
8
9 fda->nr = fda->nr_alloc;
10
11 for (fd = 0; fd < fda->nr; ++fd) {
12 fda->entries[fd].fd = fda->nr - fd;
13 fda->entries[fd].revents = revents;
14 }
15}
16
17static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE *fp)
18{
19 int printed = 0;
20
21 if (!verbose)
22 return 0;
23
24 printed += fprintf(fp, "\n%s: ", prefix);
25 return printed + fdarray__fprintf(fda, fp);
26}
27
28int test__fdarray__filter(void)
29{
30 int nr_fds, expected_fd[2], fd, err = TEST_FAIL;
31 struct fdarray *fda = fdarray__new(5, 5);
32
33 if (fda == NULL) {
34 pr_debug("\nfdarray__new() failed!");
35 goto out;
36 }
37
38 fdarray__init_revents(fda, POLLIN);
39 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
40 if (nr_fds != fda->nr_alloc) {
41 pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything",
42 nr_fds, fda->nr_alloc);
43 goto out_delete;
44 }
45
46 fdarray__init_revents(fda, POLLHUP);
47 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
48 if (nr_fds != 0) {
49 pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds",
50 nr_fds, fda->nr_alloc);
51 goto out_delete;
52 }
53
54 fdarray__init_revents(fda, POLLHUP);
55 fda->entries[2].revents = POLLIN;
56 expected_fd[0] = fda->entries[2].fd;
57
58 pr_debug("\nfiltering all but fda->entries[2]:");
59 fdarray__fprintf_prefix(fda, "before", stderr);
60 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
61 fdarray__fprintf_prefix(fda, " after", stderr);
62 if (nr_fds != 1) {
63 pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds);
64 goto out_delete;
65 }
66
67 if (fda->entries[0].fd != expected_fd[0]) {
68 pr_debug("\nfda->entries[0].fd=%d != %d\n",
69 fda->entries[0].fd, expected_fd[0]);
70 goto out_delete;
71 }
72
73 fdarray__init_revents(fda, POLLHUP);
74 fda->entries[0].revents = POLLIN;
75 expected_fd[0] = fda->entries[0].fd;
76 fda->entries[3].revents = POLLIN;
77 expected_fd[1] = fda->entries[3].fd;
78
79 pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):");
80 fdarray__fprintf_prefix(fda, "before", stderr);
81 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
82 fdarray__fprintf_prefix(fda, " after", stderr);
83 if (nr_fds != 2) {
84 pr_debug("\nfdarray__filter()=%d != 2, should have left just two events",
85 nr_fds);
86 goto out_delete;
87 }
88
89 for (fd = 0; fd < 2; ++fd) {
90 if (fda->entries[fd].fd != expected_fd[fd]) {
91 pr_debug("\nfda->entries[%d].fd=%d != %d\n", fd,
92 fda->entries[fd].fd, expected_fd[fd]);
93 goto out_delete;
94 }
95 }
96
97 pr_debug("\n");
98
99 err = 0;
100out_delete:
101 fdarray__delete(fda);
102out:
103 return err;
104}
105
106int test__fdarray__add(void)
107{
108 int err = TEST_FAIL;
109 struct fdarray *fda = fdarray__new(2, 2);
110
111 if (fda == NULL) {
112 pr_debug("\nfdarray__new() failed!");
113 goto out;
114 }
115
116#define FDA_CHECK(_idx, _fd, _revents) \
117 if (fda->entries[_idx].fd != _fd) { \
118 pr_debug("\n%d: fda->entries[%d](%d) != %d!", \
119 __LINE__, _idx, fda->entries[1].fd, _fd); \
120 goto out_delete; \
121 } \
122 if (fda->entries[_idx].events != (_revents)) { \
123 pr_debug("\n%d: fda->entries[%d].revents(%d) != %d!", \
124 __LINE__, _idx, fda->entries[_idx].fd, _revents); \
125 goto out_delete; \
126 }
127
128#define FDA_ADD(_idx, _fd, _revents, _nr) \
129 if (fdarray__add(fda, _fd, _revents) < 0) { \
130 pr_debug("\n%d: fdarray__add(fda, %d, %d) failed!", \
131 __LINE__,_fd, _revents); \
132 goto out_delete; \
133 } \
134 if (fda->nr != _nr) { \
135 pr_debug("\n%d: fdarray__add(fda, %d, %d)=%d != %d", \
136 __LINE__,_fd, _revents, fda->nr, _nr); \
137 goto out_delete; \
138 } \
139 FDA_CHECK(_idx, _fd, _revents)
140
141 FDA_ADD(0, 1, POLLIN, 1);
142 FDA_ADD(1, 2, POLLERR, 2);
143
144 fdarray__fprintf_prefix(fda, "before growing array", stderr);
145
146 FDA_ADD(2, 35, POLLHUP, 3);
147
148 if (fda->entries == NULL) {
149 pr_debug("\nfdarray__add(fda, 35, POLLHUP) should have allocated fda->pollfd!");
150 goto out_delete;
151 }
152
153 fdarray__fprintf_prefix(fda, "after 3rd add", stderr);
154
155 FDA_ADD(3, 88, POLLIN | POLLOUT, 4);
156
157 fdarray__fprintf_prefix(fda, "after 4th add", stderr);
158
159 FDA_CHECK(0, 1, POLLIN);
160 FDA_CHECK(1, 2, POLLERR);
161 FDA_CHECK(2, 35, POLLHUP);
162 FDA_CHECK(3, 88, POLLIN | POLLOUT);
163
164#undef FDA_ADD
165#undef FDA_CHECK
166
167 pr_debug("\n");
168
169 err = 0;
170out_delete:
171 fdarray__delete(fda);
172out:
173 return err;
174}
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 142263492f6f..9b9622a33932 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -31,6 +31,7 @@ int test__basic_mmap(void)
31 unsigned int nr_events[nsyscalls], 31 unsigned int nr_events[nsyscalls],
32 expected_nr_events[nsyscalls], i, j; 32 expected_nr_events[nsyscalls], i, j;
33 struct perf_evsel *evsels[nsyscalls], *evsel; 33 struct perf_evsel *evsels[nsyscalls], *evsel;
34 char sbuf[STRERR_BUFSIZE];
34 35
35 threads = thread_map__new(-1, getpid(), UINT_MAX); 36 threads = thread_map__new(-1, getpid(), UINT_MAX);
36 if (threads == NULL) { 37 if (threads == NULL) {
@@ -49,7 +50,7 @@ int test__basic_mmap(void)
49 sched_setaffinity(0, sizeof(cpu_set), &cpu_set); 50 sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
50 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 51 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
51 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 52 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
52 cpus->map[0], strerror(errno)); 53 cpus->map[0], strerror_r(errno, sbuf, sizeof(sbuf)));
53 goto out_free_cpus; 54 goto out_free_cpus;
54 } 55 }
55 56
@@ -79,7 +80,7 @@ int test__basic_mmap(void)
79 if (perf_evsel__open(evsels[i], cpus, threads) < 0) { 80 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
80 pr_debug("failed to open counter: %s, " 81 pr_debug("failed to open counter: %s, "
81 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 82 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
82 strerror(errno)); 83 strerror_r(errno, sbuf, sizeof(sbuf)));
83 goto out_delete_evlist; 84 goto out_delete_evlist;
84 } 85 }
85 86
@@ -89,7 +90,7 @@ int test__basic_mmap(void)
89 90
90 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
91 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
92 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
93 goto out_delete_evlist; 94 goto out_delete_evlist;
94 } 95 }
95 96
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 5fecdbd2f5f7..8fa82d1700c7 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -12,6 +12,7 @@ int test__open_syscall_event_on_all_cpus(void)
12 unsigned int nr_open_calls = 111, i; 12 unsigned int nr_open_calls = 111, i;
13 cpu_set_t cpu_set; 13 cpu_set_t cpu_set;
14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
15 char sbuf[STRERR_BUFSIZE];
15 16
16 if (threads == NULL) { 17 if (threads == NULL) {
17 pr_debug("thread_map__new\n"); 18 pr_debug("thread_map__new\n");
@@ -35,7 +36,7 @@ int test__open_syscall_event_on_all_cpus(void)
35 if (perf_evsel__open(evsel, cpus, threads) < 0) { 36 if (perf_evsel__open(evsel, cpus, threads) < 0) {
36 pr_debug("failed to open counter: %s, " 37 pr_debug("failed to open counter: %s, "
37 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 38 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
38 strerror(errno)); 39 strerror_r(errno, sbuf, sizeof(sbuf)));
39 goto out_evsel_delete; 40 goto out_evsel_delete;
40 } 41 }
41 42
@@ -56,7 +57,7 @@ int test__open_syscall_event_on_all_cpus(void)
56 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 57 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
57 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 58 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
58 cpus->map[cpu], 59 cpus->map[cpu],
59 strerror(errno)); 60 strerror_r(errno, sbuf, sizeof(sbuf)));
60 goto out_close_fd; 61 goto out_close_fd;
61 } 62 }
62 for (i = 0; i < ncalls; ++i) { 63 for (i = 0; i < ncalls; ++i) {
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index 0785b64ffd6c..127dcae0b760 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -22,6 +22,7 @@ int test__syscall_open_tp_fields(void)
22 struct perf_evlist *evlist = perf_evlist__new(); 22 struct perf_evlist *evlist = perf_evlist__new();
23 struct perf_evsel *evsel; 23 struct perf_evsel *evsel;
24 int err = -1, i, nr_events = 0, nr_polls = 0; 24 int err = -1, i, nr_events = 0, nr_polls = 0;
25 char sbuf[STRERR_BUFSIZE];
25 26
26 if (evlist == NULL) { 27 if (evlist == NULL) {
27 pr_debug("%s: perf_evlist__new\n", __func__); 28 pr_debug("%s: perf_evlist__new\n", __func__);
@@ -48,13 +49,15 @@ int test__syscall_open_tp_fields(void)
48 49
49 err = perf_evlist__open(evlist); 50 err = perf_evlist__open(evlist);
50 if (err < 0) { 51 if (err < 0) {
51 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 52 pr_debug("perf_evlist__open: %s\n",
53 strerror_r(errno, sbuf, sizeof(sbuf)));
52 goto out_delete_evlist; 54 goto out_delete_evlist;
53 } 55 }
54 56
55 err = perf_evlist__mmap(evlist, UINT_MAX, false); 57 err = perf_evlist__mmap(evlist, UINT_MAX, false);
56 if (err < 0) { 58 if (err < 0) {
57 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 59 pr_debug("perf_evlist__mmap: %s\n",
60 strerror_r(errno, sbuf, sizeof(sbuf)));
58 goto out_delete_evlist; 61 goto out_delete_evlist;
59 } 62 }
60 63
@@ -102,7 +105,7 @@ int test__syscall_open_tp_fields(void)
102 } 105 }
103 106
104 if (nr_events == before) 107 if (nr_events == before)
105 poll(evlist->pollfd, evlist->nr_fds, 10); 108 perf_evlist__poll(evlist, 10);
106 109
107 if (++nr_polls > 5) { 110 if (++nr_polls > 5) {
108 pr_debug("%s: no events!\n", __func__); 111 pr_debug("%s: no events!\n", __func__);
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index c1dc7d25f38c..a33b2daae40f 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -9,6 +9,7 @@ int test__open_syscall_event(void)
9 struct perf_evsel *evsel; 9 struct perf_evsel *evsel;
10 unsigned int nr_open_calls = 111, i; 10 unsigned int nr_open_calls = 111, i;
11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
12 char sbuf[STRERR_BUFSIZE];
12 13
13 if (threads == NULL) { 14 if (threads == NULL) {
14 pr_debug("thread_map__new\n"); 15 pr_debug("thread_map__new\n");
@@ -24,7 +25,7 @@ int test__open_syscall_event(void)
24 if (perf_evsel__open_per_thread(evsel, threads) < 0) { 25 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
25 pr_debug("failed to open counter: %s, " 26 pr_debug("failed to open counter: %s, "
26 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 27 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
27 strerror(errno)); 28 strerror_r(errno, sbuf, sizeof(sbuf)));
28 goto out_evsel_delete; 29 goto out_evsel_delete;
29 } 30 }
30 31
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index aca1a83dd13a..7a228a2a070b 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -59,6 +59,7 @@ int test__PERF_RECORD(void)
59 int err = -1, errs = 0, i, wakeups = 0; 59 int err = -1, errs = 0, i, wakeups = 0;
60 u32 cpu; 60 u32 cpu;
61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; 61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
62 char sbuf[STRERR_BUFSIZE];
62 63
63 if (evlist == NULL || argv == NULL) { 64 if (evlist == NULL || argv == NULL) {
64 pr_debug("Not enough memory to create evlist\n"); 65 pr_debug("Not enough memory to create evlist\n");
@@ -100,7 +101,8 @@ int test__PERF_RECORD(void)
100 101
101 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 102 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
102 if (err < 0) { 103 if (err < 0) {
103 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); 104 pr_debug("sched__get_first_possible_cpu: %s\n",
105 strerror_r(errno, sbuf, sizeof(sbuf)));
104 goto out_delete_evlist; 106 goto out_delete_evlist;
105 } 107 }
106 108
@@ -110,7 +112,8 @@ int test__PERF_RECORD(void)
110 * So that we can check perf_sample.cpu on all the samples. 112 * So that we can check perf_sample.cpu on all the samples.
111 */ 113 */
112 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { 114 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
113 pr_debug("sched_setaffinity: %s\n", strerror(errno)); 115 pr_debug("sched_setaffinity: %s\n",
116 strerror_r(errno, sbuf, sizeof(sbuf)));
114 goto out_delete_evlist; 117 goto out_delete_evlist;
115 } 118 }
116 119
@@ -120,7 +123,8 @@ int test__PERF_RECORD(void)
120 */ 123 */
121 err = perf_evlist__open(evlist); 124 err = perf_evlist__open(evlist);
122 if (err < 0) { 125 if (err < 0) {
123 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 126 pr_debug("perf_evlist__open: %s\n",
127 strerror_r(errno, sbuf, sizeof(sbuf)));
124 goto out_delete_evlist; 128 goto out_delete_evlist;
125 } 129 }
126 130
@@ -131,7 +135,8 @@ int test__PERF_RECORD(void)
131 */ 135 */
132 err = perf_evlist__mmap(evlist, opts.mmap_pages, false); 136 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
133 if (err < 0) { 137 if (err < 0) {
134 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 138 pr_debug("perf_evlist__mmap: %s\n",
139 strerror_r(errno, sbuf, sizeof(sbuf)));
135 goto out_delete_evlist; 140 goto out_delete_evlist;
136 } 141 }
137 142
@@ -263,7 +268,7 @@ int test__PERF_RECORD(void)
263 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does. 268 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
264 */ 269 */
265 if (total_events == before && false) 270 if (total_events == before && false)
266 poll(evlist->pollfd, evlist->nr_fds, -1); 271 perf_evlist__poll(evlist, -1);
267 272
268 sleep(1); 273 sleep(1);
269 if (++wakeups > 5) { 274 if (++wakeups > 5) {
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 12b322fa3475..eeb68bb1972d 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -152,7 +152,7 @@ int test__pmu(void)
152 if (ret) 152 if (ret)
153 break; 153 break;
154 154
155 ret = perf_pmu__config_terms(&formats, &attr, terms); 155 ret = perf_pmu__config_terms(&formats, &attr, terms, false);
156 if (ret) 156 if (ret)
157 break; 157 break;
158 158
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
index c04d1f268576..d31f2c4d9f64 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/tests/rdpmc.c
@@ -100,6 +100,7 @@ static int __test__rdpmc(void)
100 }; 100 };
101 u64 delta_sum = 0; 101 u64 delta_sum = 0;
102 struct sigaction sa; 102 struct sigaction sa;
103 char sbuf[STRERR_BUFSIZE];
103 104
104 sigfillset(&sa.sa_mask); 105 sigfillset(&sa.sa_mask);
105 sa.sa_sigaction = segfault_handler; 106 sa.sa_sigaction = segfault_handler;
@@ -109,14 +110,15 @@ static int __test__rdpmc(void)
109 perf_event_open_cloexec_flag()); 110 perf_event_open_cloexec_flag());
110 if (fd < 0) { 111 if (fd < 0) {
111 pr_err("Error: sys_perf_event_open() syscall returned " 112 pr_err("Error: sys_perf_event_open() syscall returned "
112 "with %d (%s)\n", fd, strerror(errno)); 113 "with %d (%s)\n", fd,
114 strerror_r(errno, sbuf, sizeof(sbuf)));
113 return -1; 115 return -1;
114 } 116 }
115 117
116 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); 118 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
117 if (addr == (void *)(-1)) { 119 if (addr == (void *)(-1)) {
118 pr_err("Error: mmap() syscall returned with (%s)\n", 120 pr_err("Error: mmap() syscall returned with (%s)\n",
119 strerror(errno)); 121 strerror_r(errno, sbuf, sizeof(sbuf)));
120 goto out_close; 122 goto out_close;
121 } 123 }
122 124
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 983d6b8562a8..1aa21c90731b 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -22,6 +22,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
22 volatile int tmp = 0; 22 volatile int tmp = 0;
23 u64 total_periods = 0; 23 u64 total_periods = 0;
24 int nr_samples = 0; 24 int nr_samples = 0;
25 char sbuf[STRERR_BUFSIZE];
25 union perf_event *event; 26 union perf_event *event;
26 struct perf_evsel *evsel; 27 struct perf_evsel *evsel;
27 struct perf_evlist *evlist; 28 struct perf_evlist *evlist;
@@ -62,14 +63,15 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
62 63
63 err = -errno; 64 err = -errno;
64 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", 65 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
65 strerror(errno), knob, (u64)attr.sample_freq); 66 strerror_r(errno, sbuf, sizeof(sbuf)),
67 knob, (u64)attr.sample_freq);
66 goto out_delete_evlist; 68 goto out_delete_evlist;
67 } 69 }
68 70
69 err = perf_evlist__mmap(evlist, 128, true); 71 err = perf_evlist__mmap(evlist, 128, true);
70 if (err < 0) { 72 if (err < 0) {
71 pr_debug("failed to mmap event: %d (%s)\n", errno, 73 pr_debug("failed to mmap event: %d (%s)\n", errno,
72 strerror(errno)); 74 strerror_r(errno, sbuf, sizeof(sbuf)));
73 goto out_delete_evlist; 75 goto out_delete_evlist;
74 } 76 }
75 77
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
new file mode 100644
index 000000000000..cc68648c7c55
--- /dev/null
+++ b/tools/perf/tests/switch-tracking.c
@@ -0,0 +1,572 @@
1#include <sys/time.h>
2#include <sys/prctl.h>
3#include <time.h>
4#include <stdlib.h>
5
6#include "parse-events.h"
7#include "evlist.h"
8#include "evsel.h"
9#include "thread_map.h"
10#include "cpumap.h"
11#include "tests.h"
12
13static int spin_sleep(void)
14{
15 struct timeval start, now, diff, maxtime;
16 struct timespec ts;
17 int err, i;
18
19 maxtime.tv_sec = 0;
20 maxtime.tv_usec = 50000;
21
22 err = gettimeofday(&start, NULL);
23 if (err)
24 return err;
25
26 /* Spin for 50ms */
27 while (1) {
28 for (i = 0; i < 1000; i++)
29 barrier();
30
31 err = gettimeofday(&now, NULL);
32 if (err)
33 return err;
34
35 timersub(&now, &start, &diff);
36 if (timercmp(&diff, &maxtime, > /* For checkpatch */))
37 break;
38 }
39
40 ts.tv_nsec = 50 * 1000 * 1000;
41 ts.tv_sec = 0;
42
43 /* Sleep for 50ms */
44 err = nanosleep(&ts, NULL);
45 if (err == EINTR)
46 err = 0;
47
48 return err;
49}
50
51struct switch_tracking {
52 struct perf_evsel *switch_evsel;
53 struct perf_evsel *cycles_evsel;
54 pid_t *tids;
55 int nr_tids;
56 int comm_seen[4];
57 int cycles_before_comm_1;
58 int cycles_between_comm_2_and_comm_3;
59 int cycles_after_comm_4;
60};
61
62static int check_comm(struct switch_tracking *switch_tracking,
63 union perf_event *event, const char *comm, int nr)
64{
65 if (event->header.type == PERF_RECORD_COMM &&
66 (pid_t)event->comm.pid == getpid() &&
67 (pid_t)event->comm.tid == getpid() &&
68 strcmp(event->comm.comm, comm) == 0) {
69 if (switch_tracking->comm_seen[nr]) {
70 pr_debug("Duplicate comm event\n");
71 return -1;
72 }
73 switch_tracking->comm_seen[nr] = 1;
74 pr_debug3("comm event: %s nr: %d\n", event->comm.comm, nr);
75 return 1;
76 }
77 return 0;
78}
79
80static int check_cpu(struct switch_tracking *switch_tracking, int cpu)
81{
82 int i, nr = cpu + 1;
83
84 if (cpu < 0)
85 return -1;
86
87 if (!switch_tracking->tids) {
88 switch_tracking->tids = calloc(nr, sizeof(pid_t));
89 if (!switch_tracking->tids)
90 return -1;
91 for (i = 0; i < nr; i++)
92 switch_tracking->tids[i] = -1;
93 switch_tracking->nr_tids = nr;
94 return 0;
95 }
96
97 if (cpu >= switch_tracking->nr_tids) {
98 void *addr;
99
100 addr = realloc(switch_tracking->tids, nr * sizeof(pid_t));
101 if (!addr)
102 return -1;
103 switch_tracking->tids = addr;
104 for (i = switch_tracking->nr_tids; i < nr; i++)
105 switch_tracking->tids[i] = -1;
106 switch_tracking->nr_tids = nr;
107 return 0;
108 }
109
110 return 0;
111}
112
113static int process_sample_event(struct perf_evlist *evlist,
114 union perf_event *event,
115 struct switch_tracking *switch_tracking)
116{
117 struct perf_sample sample;
118 struct perf_evsel *evsel;
119 pid_t next_tid, prev_tid;
120 int cpu, err;
121
122 if (perf_evlist__parse_sample(evlist, event, &sample)) {
123 pr_debug("perf_evlist__parse_sample failed\n");
124 return -1;
125 }
126
127 evsel = perf_evlist__id2evsel(evlist, sample.id);
128 if (evsel == switch_tracking->switch_evsel) {
129 next_tid = perf_evsel__intval(evsel, &sample, "next_pid");
130 prev_tid = perf_evsel__intval(evsel, &sample, "prev_pid");
131 cpu = sample.cpu;
132 pr_debug3("sched_switch: cpu: %d prev_tid %d next_tid %d\n",
133 cpu, prev_tid, next_tid);
134 err = check_cpu(switch_tracking, cpu);
135 if (err)
136 return err;
137 /*
138 * Check for no missing sched_switch events i.e. that the
139 * evsel->system_wide flag has worked.
140 */
141 if (switch_tracking->tids[cpu] != -1 &&
142 switch_tracking->tids[cpu] != prev_tid) {
143 pr_debug("Missing sched_switch events\n");
144 return -1;
145 }
146 switch_tracking->tids[cpu] = next_tid;
147 }
148
149 if (evsel == switch_tracking->cycles_evsel) {
150 pr_debug3("cycles event\n");
151 if (!switch_tracking->comm_seen[0])
152 switch_tracking->cycles_before_comm_1 = 1;
153 if (switch_tracking->comm_seen[1] &&
154 !switch_tracking->comm_seen[2])
155 switch_tracking->cycles_between_comm_2_and_comm_3 = 1;
156 if (switch_tracking->comm_seen[3])
157 switch_tracking->cycles_after_comm_4 = 1;
158 }
159
160 return 0;
161}
162
163static int process_event(struct perf_evlist *evlist, union perf_event *event,
164 struct switch_tracking *switch_tracking)
165{
166 if (event->header.type == PERF_RECORD_SAMPLE)
167 return process_sample_event(evlist, event, switch_tracking);
168
169 if (event->header.type == PERF_RECORD_COMM) {
170 int err, done = 0;
171
172 err = check_comm(switch_tracking, event, "Test COMM 1", 0);
173 if (err < 0)
174 return -1;
175 done += err;
176 err = check_comm(switch_tracking, event, "Test COMM 2", 1);
177 if (err < 0)
178 return -1;
179 done += err;
180 err = check_comm(switch_tracking, event, "Test COMM 3", 2);
181 if (err < 0)
182 return -1;
183 done += err;
184 err = check_comm(switch_tracking, event, "Test COMM 4", 3);
185 if (err < 0)
186 return -1;
187 done += err;
188 if (done != 1) {
189 pr_debug("Unexpected comm event\n");
190 return -1;
191 }
192 }
193
194 return 0;
195}
196
197struct event_node {
198 struct list_head list;
199 union perf_event *event;
200 u64 event_time;
201};
202
203static int add_event(struct perf_evlist *evlist, struct list_head *events,
204 union perf_event *event)
205{
206 struct perf_sample sample;
207 struct event_node *node;
208
209 node = malloc(sizeof(struct event_node));
210 if (!node) {
211 pr_debug("malloc failed\n");
212 return -1;
213 }
214 node->event = event;
215 list_add(&node->list, events);
216
217 if (perf_evlist__parse_sample(evlist, event, &sample)) {
218 pr_debug("perf_evlist__parse_sample failed\n");
219 return -1;
220 }
221
222 if (!sample.time) {
223 pr_debug("event with no time\n");
224 return -1;
225 }
226
227 node->event_time = sample.time;
228
229 return 0;
230}
231
232static void free_event_nodes(struct list_head *events)
233{
234 struct event_node *node;
235
236 while (!list_empty(events)) {
237 node = list_entry(events->next, struct event_node, list);
238 list_del(&node->list);
239 free(node);
240 }
241}
242
243static int compar(const void *a, const void *b)
244{
245 const struct event_node *nodea = a;
246 const struct event_node *nodeb = b;
247 s64 cmp = nodea->event_time - nodeb->event_time;
248
249 return cmp;
250}
251
252static int process_events(struct perf_evlist *evlist,
253 struct switch_tracking *switch_tracking)
254{
255 union perf_event *event;
256 unsigned pos, cnt = 0;
257 LIST_HEAD(events);
258 struct event_node *events_array, *node;
259 int i, ret;
260
261 for (i = 0; i < evlist->nr_mmaps; i++) {
262 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
263 cnt += 1;
264 ret = add_event(evlist, &events, event);
265 perf_evlist__mmap_consume(evlist, i);
266 if (ret < 0)
267 goto out_free_nodes;
268 }
269 }
270
271 events_array = calloc(cnt, sizeof(struct event_node));
272 if (!events_array) {
273 pr_debug("calloc failed\n");
274 ret = -1;
275 goto out_free_nodes;
276 }
277
278 pos = 0;
279 list_for_each_entry(node, &events, list)
280 events_array[pos++] = *node;
281
282 qsort(events_array, cnt, sizeof(struct event_node), compar);
283
284 for (pos = 0; pos < cnt; pos++) {
285 ret = process_event(evlist, events_array[pos].event,
286 switch_tracking);
287 if (ret < 0)
288 goto out_free;
289 }
290
291 ret = 0;
292out_free:
293 pr_debug("%u events recorded\n", cnt);
294 free(events_array);
295out_free_nodes:
296 free_event_nodes(&events);
297 return ret;
298}
299
300/**
301 * test__switch_tracking - test using sched_switch and tracking events.
302 *
303 * This function implements a test that checks that sched_switch events and
304 * tracking events can be recorded for a workload (current process) using the
305 * evsel->system_wide and evsel->tracking flags (respectively) with other events
306 * sometimes enabled or disabled.
307 */
308int test__switch_tracking(void)
309{
310 const char *sched_switch = "sched:sched_switch";
311 struct switch_tracking switch_tracking = { .tids = NULL, };
312 struct record_opts opts = {
313 .mmap_pages = UINT_MAX,
314 .user_freq = UINT_MAX,
315 .user_interval = ULLONG_MAX,
316 .freq = 4000,
317 .target = {
318 .uses_mmap = true,
319 },
320 };
321 struct thread_map *threads = NULL;
322 struct cpu_map *cpus = NULL;
323 struct perf_evlist *evlist = NULL;
324 struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel;
325 struct perf_evsel *switch_evsel, *tracking_evsel;
326 const char *comm;
327 int err = -1;
328
329 threads = thread_map__new(-1, getpid(), UINT_MAX);
330 if (!threads) {
331 pr_debug("thread_map__new failed!\n");
332 goto out_err;
333 }
334
335 cpus = cpu_map__new(NULL);
336 if (!cpus) {
337 pr_debug("cpu_map__new failed!\n");
338 goto out_err;
339 }
340
341 evlist = perf_evlist__new();
342 if (!evlist) {
343 pr_debug("perf_evlist__new failed!\n");
344 goto out_err;
345 }
346
347 perf_evlist__set_maps(evlist, cpus, threads);
348
349 /* First event */
350 err = parse_events(evlist, "cpu-clock:u");
351 if (err) {
352 pr_debug("Failed to parse event dummy:u\n");
353 goto out_err;
354 }
355
356 cpu_clocks_evsel = perf_evlist__last(evlist);
357
358 /* Second event */
359 err = parse_events(evlist, "cycles:u");
360 if (err) {
361 pr_debug("Failed to parse event cycles:u\n");
362 goto out_err;
363 }
364
365 cycles_evsel = perf_evlist__last(evlist);
366
367 /* Third event */
368 if (!perf_evlist__can_select_event(evlist, sched_switch)) {
369 fprintf(stderr, " (no sched_switch)");
370 err = 0;
371 goto out;
372 }
373
374 err = parse_events(evlist, sched_switch);
375 if (err) {
376 pr_debug("Failed to parse event %s\n", sched_switch);
377 goto out_err;
378 }
379
380 switch_evsel = perf_evlist__last(evlist);
381
382 perf_evsel__set_sample_bit(switch_evsel, CPU);
383 perf_evsel__set_sample_bit(switch_evsel, TIME);
384
385 switch_evsel->system_wide = true;
386 switch_evsel->no_aux_samples = true;
387 switch_evsel->immediate = true;
388
389 /* Test moving an event to the front */
390 if (cycles_evsel == perf_evlist__first(evlist)) {
391 pr_debug("cycles event already at front");
392 goto out_err;
393 }
394 perf_evlist__to_front(evlist, cycles_evsel);
395 if (cycles_evsel != perf_evlist__first(evlist)) {
396 pr_debug("Failed to move cycles event to front");
397 goto out_err;
398 }
399
400 perf_evsel__set_sample_bit(cycles_evsel, CPU);
401 perf_evsel__set_sample_bit(cycles_evsel, TIME);
402
403 /* Fourth event */
404 err = parse_events(evlist, "dummy:u");
405 if (err) {
406 pr_debug("Failed to parse event dummy:u\n");
407 goto out_err;
408 }
409
410 tracking_evsel = perf_evlist__last(evlist);
411
412 perf_evlist__set_tracking_event(evlist, tracking_evsel);
413
414 tracking_evsel->attr.freq = 0;
415 tracking_evsel->attr.sample_period = 1;
416
417 perf_evsel__set_sample_bit(tracking_evsel, TIME);
418
419 /* Config events */
420 perf_evlist__config(evlist, &opts);
421
422 /* Check moved event is still at the front */
423 if (cycles_evsel != perf_evlist__first(evlist)) {
424 pr_debug("Front event no longer at front");
425 goto out_err;
426 }
427
428 /* Check tracking event is tracking */
429 if (!tracking_evsel->attr.mmap || !tracking_evsel->attr.comm) {
430 pr_debug("Tracking event not tracking\n");
431 goto out_err;
432 }
433
434 /* Check non-tracking events are not tracking */
435 evlist__for_each(evlist, evsel) {
436 if (evsel != tracking_evsel) {
437 if (evsel->attr.mmap || evsel->attr.comm) {
438 pr_debug("Non-tracking event is tracking\n");
439 goto out_err;
440 }
441 }
442 }
443
444 if (perf_evlist__open(evlist) < 0) {
445 fprintf(stderr, " (not supported)");
446 err = 0;
447 goto out;
448 }
449
450 err = perf_evlist__mmap(evlist, UINT_MAX, false);
451 if (err) {
452 pr_debug("perf_evlist__mmap failed!\n");
453 goto out_err;
454 }
455
456 perf_evlist__enable(evlist);
457
458 err = perf_evlist__disable_event(evlist, cpu_clocks_evsel);
459 if (err) {
460 pr_debug("perf_evlist__disable_event failed!\n");
461 goto out_err;
462 }
463
464 err = spin_sleep();
465 if (err) {
466 pr_debug("spin_sleep failed!\n");
467 goto out_err;
468 }
469
470 comm = "Test COMM 1";
471 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
472 if (err) {
473 pr_debug("PR_SET_NAME failed!\n");
474 goto out_err;
475 }
476
477 err = perf_evlist__disable_event(evlist, cycles_evsel);
478 if (err) {
479 pr_debug("perf_evlist__disable_event failed!\n");
480 goto out_err;
481 }
482
483 comm = "Test COMM 2";
484 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
485 if (err) {
486 pr_debug("PR_SET_NAME failed!\n");
487 goto out_err;
488 }
489
490 err = spin_sleep();
491 if (err) {
492 pr_debug("spin_sleep failed!\n");
493 goto out_err;
494 }
495
496 comm = "Test COMM 3";
497 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
498 if (err) {
499 pr_debug("PR_SET_NAME failed!\n");
500 goto out_err;
501 }
502
503 err = perf_evlist__enable_event(evlist, cycles_evsel);
504 if (err) {
505 pr_debug("perf_evlist__disable_event failed!\n");
506 goto out_err;
507 }
508
509 comm = "Test COMM 4";
510 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
511 if (err) {
512 pr_debug("PR_SET_NAME failed!\n");
513 goto out_err;
514 }
515
516 err = spin_sleep();
517 if (err) {
518 pr_debug("spin_sleep failed!\n");
519 goto out_err;
520 }
521
522 perf_evlist__disable(evlist);
523
524 switch_tracking.switch_evsel = switch_evsel;
525 switch_tracking.cycles_evsel = cycles_evsel;
526
527 err = process_events(evlist, &switch_tracking);
528
529 zfree(&switch_tracking.tids);
530
531 if (err)
532 goto out_err;
533
534 /* Check all 4 comm events were seen i.e. that evsel->tracking works */
535 if (!switch_tracking.comm_seen[0] || !switch_tracking.comm_seen[1] ||
536 !switch_tracking.comm_seen[2] || !switch_tracking.comm_seen[3]) {
537 pr_debug("Missing comm events\n");
538 goto out_err;
539 }
540
541 /* Check cycles event got enabled */
542 if (!switch_tracking.cycles_before_comm_1) {
543 pr_debug("Missing cycles events\n");
544 goto out_err;
545 }
546
547 /* Check cycles event got disabled */
548 if (switch_tracking.cycles_between_comm_2_and_comm_3) {
549 pr_debug("cycles events even though event was disabled\n");
550 goto out_err;
551 }
552
553 /* Check cycles event got enabled again */
554 if (!switch_tracking.cycles_after_comm_4) {
555 pr_debug("Missing cycles events\n");
556 goto out_err;
557 }
558out:
559 if (evlist) {
560 perf_evlist__disable(evlist);
561 perf_evlist__delete(evlist);
562 } else {
563 cpu_map__delete(cpus);
564 thread_map__delete(threads);
565 }
566
567 return err;
568
569out_err:
570 err = -1;
571 goto out;
572}
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 5ff3db318f12..3a8fedef83bc 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -42,6 +42,7 @@ int test__task_exit(void)
42 .uses_mmap = true, 42 .uses_mmap = true,
43 }; 43 };
44 const char *argv[] = { "true", NULL }; 44 const char *argv[] = { "true", NULL };
45 char sbuf[STRERR_BUFSIZE];
45 46
46 signal(SIGCHLD, sig_handler); 47 signal(SIGCHLD, sig_handler);
47 48
@@ -82,13 +83,14 @@ int test__task_exit(void)
82 83
83 err = perf_evlist__open(evlist); 84 err = perf_evlist__open(evlist);
84 if (err < 0) { 85 if (err < 0) {
85 pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); 86 pr_debug("Couldn't open the evlist: %s\n",
87 strerror_r(-err, sbuf, sizeof(sbuf)));
86 goto out_delete_evlist; 88 goto out_delete_evlist;
87 } 89 }
88 90
89 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
90 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
91 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
92 goto out_delete_evlist; 94 goto out_delete_evlist;
93 } 95 }
94 96
@@ -103,7 +105,7 @@ retry:
103 } 105 }
104 106
105 if (!exited || !nr_exit) { 107 if (!exited || !nr_exit) {
106 poll(evlist->pollfd, evlist->nr_fds, -1); 108 perf_evlist__poll(evlist, -1);
107 goto retry; 109 goto retry;
108 } 110 }
109 111
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index ed64790a395f..00e776a87a9c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -48,6 +48,9 @@ int test__mmap_thread_lookup(void);
48int test__thread_mg_share(void); 48int test__thread_mg_share(void);
49int test__hists_output(void); 49int test__hists_output(void);
50int test__hists_cumulate(void); 50int test__hists_cumulate(void);
51int test__switch_tracking(void);
52int test__fdarray__filter(void);
53int test__fdarray__add(void);
51 54
52#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 55#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
53#ifdef HAVE_DWARF_UNWIND_SUPPORT 56#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a94b11fc5e00..8f60a970404f 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -10,6 +10,7 @@
10#include "../../util/pstack.h" 10#include "../../util/pstack.h"
11#include "../../util/sort.h" 11#include "../../util/sort.h"
12#include "../../util/util.h" 12#include "../../util/util.h"
13#include "../../util/top.h"
13#include "../../arch/common.h" 14#include "../../arch/common.h"
14 15
15#include "../browser.h" 16#include "../browser.h"
@@ -228,8 +229,10 @@ static void callchain_node__init_have_children(struct callchain_node *node)
228{ 229{
229 struct callchain_list *chain; 230 struct callchain_list *chain;
230 231
231 list_for_each_entry(chain, &node->val, list) 232 if (!list_empty(&node->val)) {
233 chain = list_entry(node->val.prev, struct callchain_list, list);
232 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); 234 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
235 }
233 236
234 callchain_node__init_have_children_rb_tree(node); 237 callchain_node__init_have_children_rb_tree(node);
235} 238}
@@ -474,26 +477,87 @@ static char *callchain_list__sym_name(struct callchain_list *cl,
474 return bf; 477 return bf;
475} 478}
476 479
480struct callchain_print_arg {
481 /* for hists browser */
482 off_t row_offset;
483 bool is_current_entry;
484
485 /* for file dump */
486 FILE *fp;
487 int printed;
488};
489
490typedef void (*print_callchain_entry_fn)(struct hist_browser *browser,
491 struct callchain_list *chain,
492 const char *str, int offset,
493 unsigned short row,
494 struct callchain_print_arg *arg);
495
496static void hist_browser__show_callchain_entry(struct hist_browser *browser,
497 struct callchain_list *chain,
498 const char *str, int offset,
499 unsigned short row,
500 struct callchain_print_arg *arg)
501{
502 int color, width;
503 char folded_sign = callchain_list__folded(chain);
504
505 color = HE_COLORSET_NORMAL;
506 width = browser->b.width - (offset + 2);
507 if (ui_browser__is_current_entry(&browser->b, row)) {
508 browser->selection = &chain->ms;
509 color = HE_COLORSET_SELECTED;
510 arg->is_current_entry = true;
511 }
512
513 ui_browser__set_color(&browser->b, color);
514 hist_browser__gotorc(browser, row, 0);
515 slsmg_write_nstring(" ", offset);
516 slsmg_printf("%c ", folded_sign);
517 slsmg_write_nstring(str, width);
518}
519
520static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused,
521 struct callchain_list *chain,
522 const char *str, int offset,
523 unsigned short row __maybe_unused,
524 struct callchain_print_arg *arg)
525{
526 char folded_sign = callchain_list__folded(chain);
527
528 arg->printed += fprintf(arg->fp, "%*s%c %s\n", offset, " ",
529 folded_sign, str);
530}
531
532typedef bool (*check_output_full_fn)(struct hist_browser *browser,
533 unsigned short row);
534
535static bool hist_browser__check_output_full(struct hist_browser *browser,
536 unsigned short row)
537{
538 return browser->b.rows == row;
539}
540
541static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_unused,
542 unsigned short row __maybe_unused)
543{
544 return false;
545}
546
477#define LEVEL_OFFSET_STEP 3 547#define LEVEL_OFFSET_STEP 3
478 548
479static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browser, 549static int hist_browser__show_callchain(struct hist_browser *browser,
480 struct callchain_node *chain_node, 550 struct rb_root *root, int level,
481 u64 total, int level, 551 unsigned short row, u64 total,
482 unsigned short row, 552 print_callchain_entry_fn print,
483 off_t *row_offset, 553 struct callchain_print_arg *arg,
484 bool *is_current_entry) 554 check_output_full_fn is_output_full)
485{ 555{
486 struct rb_node *node; 556 struct rb_node *node;
487 int first_row = row, width, offset = level * LEVEL_OFFSET_STEP; 557 int first_row = row, offset = level * LEVEL_OFFSET_STEP;
488 u64 new_total, remaining; 558 u64 new_total;
489 559
490 if (callchain_param.mode == CHAIN_GRAPH_REL) 560 node = rb_first(root);
491 new_total = chain_node->children_hit;
492 else
493 new_total = total;
494
495 remaining = new_total;
496 node = rb_first(&chain_node->rb_root);
497 while (node) { 561 while (node) {
498 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 562 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
499 struct rb_node *next = rb_next(node); 563 struct rb_node *next = rb_next(node);
@@ -503,30 +567,28 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
503 int first = true; 567 int first = true;
504 int extra_offset = 0; 568 int extra_offset = 0;
505 569
506 remaining -= cumul;
507
508 list_for_each_entry(chain, &child->val, list) { 570 list_for_each_entry(chain, &child->val, list) {
509 char bf[1024], *alloc_str; 571 char bf[1024], *alloc_str;
510 const char *str; 572 const char *str;
511 int color;
512 bool was_first = first; 573 bool was_first = first;
513 574
514 if (first) 575 if (first)
515 first = false; 576 first = false;
516 else 577 else if (level > 1)
517 extra_offset = LEVEL_OFFSET_STEP; 578 extra_offset = LEVEL_OFFSET_STEP;
518 579
519 folded_sign = callchain_list__folded(chain); 580 folded_sign = callchain_list__folded(chain);
520 if (*row_offset != 0) { 581 if (arg->row_offset != 0) {
521 --*row_offset; 582 arg->row_offset--;
522 goto do_next; 583 goto do_next;
523 } 584 }
524 585
525 alloc_str = NULL; 586 alloc_str = NULL;
526 str = callchain_list__sym_name(chain, bf, sizeof(bf), 587 str = callchain_list__sym_name(chain, bf, sizeof(bf),
527 browser->show_dso); 588 browser->show_dso);
528 if (was_first) { 589
529 double percent = cumul * 100.0 / new_total; 590 if (was_first && level > 1) {
591 double percent = cumul * 100.0 / total;
530 592
531 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) 593 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
532 str = "Not enough memory!"; 594 str = "Not enough memory!";
@@ -534,22 +596,11 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
534 str = alloc_str; 596 str = alloc_str;
535 } 597 }
536 598
537 color = HE_COLORSET_NORMAL; 599 print(browser, chain, str, offset + extra_offset, row, arg);
538 width = browser->b.width - (offset + extra_offset + 2);
539 if (ui_browser__is_current_entry(&browser->b, row)) {
540 browser->selection = &chain->ms;
541 color = HE_COLORSET_SELECTED;
542 *is_current_entry = true;
543 }
544 600
545 ui_browser__set_color(&browser->b, color);
546 hist_browser__gotorc(browser, row, 0);
547 slsmg_write_nstring(" ", offset + extra_offset);
548 slsmg_printf("%c ", folded_sign);
549 slsmg_write_nstring(str, width);
550 free(alloc_str); 601 free(alloc_str);
551 602
552 if (++row == browser->b.rows) 603 if (is_output_full(browser, ++row))
553 goto out; 604 goto out;
554do_next: 605do_next:
555 if (folded_sign == '+') 606 if (folded_sign == '+')
@@ -558,89 +609,21 @@ do_next:
558 609
559 if (folded_sign == '-') { 610 if (folded_sign == '-') {
560 const int new_level = level + (extra_offset ? 2 : 1); 611 const int new_level = level + (extra_offset ? 2 : 1);
561 row += hist_browser__show_callchain_node_rb_tree(browser, child, new_total,
562 new_level, row, row_offset,
563 is_current_entry);
564 }
565 if (row == browser->b.rows)
566 goto out;
567 node = next;
568 }
569out:
570 return row - first_row;
571}
572
573static int hist_browser__show_callchain_node(struct hist_browser *browser,
574 struct callchain_node *node,
575 int level, unsigned short row,
576 off_t *row_offset,
577 bool *is_current_entry)
578{
579 struct callchain_list *chain;
580 int first_row = row,
581 offset = level * LEVEL_OFFSET_STEP,
582 width = browser->b.width - offset;
583 char folded_sign = ' ';
584 612
585 list_for_each_entry(chain, &node->val, list) { 613 if (callchain_param.mode == CHAIN_GRAPH_REL)
586 char bf[1024], *s; 614 new_total = child->children_hit;
587 int color; 615 else
588 616 new_total = total;
589 folded_sign = callchain_list__folded(chain);
590
591 if (*row_offset != 0) {
592 --*row_offset;
593 continue;
594 }
595 617
596 color = HE_COLORSET_NORMAL; 618 row += hist_browser__show_callchain(browser, &child->rb_root,
597 if (ui_browser__is_current_entry(&browser->b, row)) { 619 new_level, row, new_total,
598 browser->selection = &chain->ms; 620 print, arg, is_output_full);
599 color = HE_COLORSET_SELECTED;
600 *is_current_entry = true;
601 } 621 }
602 622 if (is_output_full(browser, row))
603 s = callchain_list__sym_name(chain, bf, sizeof(bf),
604 browser->show_dso);
605 hist_browser__gotorc(browser, row, 0);
606 ui_browser__set_color(&browser->b, color);
607 slsmg_write_nstring(" ", offset);
608 slsmg_printf("%c ", folded_sign);
609 slsmg_write_nstring(s, width - 2);
610
611 if (++row == browser->b.rows)
612 goto out;
613 }
614
615 if (folded_sign == '-')
616 row += hist_browser__show_callchain_node_rb_tree(browser, node,
617 browser->hists->stats.total_period,
618 level + 1, row,
619 row_offset,
620 is_current_entry);
621out:
622 return row - first_row;
623}
624
625static int hist_browser__show_callchain(struct hist_browser *browser,
626 struct rb_root *chain,
627 int level, unsigned short row,
628 off_t *row_offset,
629 bool *is_current_entry)
630{
631 struct rb_node *nd;
632 int first_row = row;
633
634 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
635 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
636
637 row += hist_browser__show_callchain_node(browser, node, level,
638 row, row_offset,
639 is_current_entry);
640 if (row == browser->b.rows)
641 break; 623 break;
624 node = next;
642 } 625 }
643 626out:
644 return row - first_row; 627 return row - first_row;
645} 628}
646 629
@@ -653,17 +636,18 @@ struct hpp_arg {
653static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) 636static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
654{ 637{
655 struct hpp_arg *arg = hpp->ptr; 638 struct hpp_arg *arg = hpp->ptr;
656 int ret; 639 int ret, len;
657 va_list args; 640 va_list args;
658 double percent; 641 double percent;
659 642
660 va_start(args, fmt); 643 va_start(args, fmt);
644 len = va_arg(args, int);
661 percent = va_arg(args, double); 645 percent = va_arg(args, double);
662 va_end(args); 646 va_end(args);
663 647
664 ui_browser__set_percent_color(arg->b, percent, arg->current_entry); 648 ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
665 649
666 ret = scnprintf(hpp->buf, hpp->size, fmt, percent); 650 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
667 slsmg_printf("%s", hpp->buf); 651 slsmg_printf("%s", hpp->buf);
668 652
669 advance_hpp(hpp, ret); 653 advance_hpp(hpp, ret);
@@ -677,12 +661,12 @@ static u64 __hpp_get_##_field(struct hist_entry *he) \
677} \ 661} \
678 \ 662 \
679static int \ 663static int \
680hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 664hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
681 struct perf_hpp *hpp, \ 665 struct perf_hpp *hpp, \
682 struct hist_entry *he) \ 666 struct hist_entry *he) \
683{ \ 667{ \
684 return __hpp__fmt(hpp, he, __hpp_get_##_field, " %6.2f%%", \ 668 return hpp__fmt(fmt, hpp, he, __hpp_get_##_field, " %*.2f%%", \
685 __hpp__slsmg_color_printf, true); \ 669 __hpp__slsmg_color_printf, true); \
686} 670}
687 671
688#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 672#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -692,18 +676,20 @@ static u64 __hpp_get_acc_##_field(struct hist_entry *he) \
692} \ 676} \
693 \ 677 \
694static int \ 678static int \
695hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 679hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
696 struct perf_hpp *hpp, \ 680 struct perf_hpp *hpp, \
697 struct hist_entry *he) \ 681 struct hist_entry *he) \
698{ \ 682{ \
699 if (!symbol_conf.cumulate_callchain) { \ 683 if (!symbol_conf.cumulate_callchain) { \
700 int ret = scnprintf(hpp->buf, hpp->size, "%8s", "N/A"); \ 684 int len = fmt->user_len ?: fmt->len; \
685 int ret = scnprintf(hpp->buf, hpp->size, \
686 "%*s", len, "N/A"); \
701 slsmg_printf("%s", hpp->buf); \ 687 slsmg_printf("%s", hpp->buf); \
702 \ 688 \
703 return ret; \ 689 return ret; \
704 } \ 690 } \
705 return __hpp__fmt(hpp, he, __hpp_get_acc_##_field, " %6.2f%%", \ 691 return hpp__fmt(fmt, hpp, he, __hpp_get_acc_##_field, \
706 __hpp__slsmg_color_printf, true); \ 692 " %*.2f%%", __hpp__slsmg_color_printf, true); \
707} 693}
708 694
709__HPP_COLOR_PERCENT_FN(overhead, period) 695__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -812,10 +798,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
812 --row_offset; 798 --row_offset;
813 799
814 if (folded_sign == '-' && row != browser->b.rows) { 800 if (folded_sign == '-' && row != browser->b.rows) {
815 printed += hist_browser__show_callchain(browser, &entry->sorted_chain, 801 u64 total = hists__total_period(entry->hists);
816 1, row, &row_offset, 802 struct callchain_print_arg arg = {
817 &current_entry); 803 .row_offset = row_offset,
818 if (current_entry) 804 .is_current_entry = current_entry,
805 };
806
807 printed += hist_browser__show_callchain(browser,
808 &entry->sorted_chain, 1, row, total,
809 hist_browser__show_callchain_entry, &arg,
810 hist_browser__check_output_full);
811
812 if (arg.is_current_entry)
819 browser->he_selection = entry; 813 browser->he_selection = entry;
820 } 814 }
821 815
@@ -847,9 +841,6 @@ static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
847 if (perf_hpp__should_skip(fmt)) 841 if (perf_hpp__should_skip(fmt))
848 continue; 842 continue;
849 843
850 /* We need to add the length of the columns header. */
851 perf_hpp__reset_width(fmt, hists);
852
853 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 844 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
854 if (advance_hpp_check(&dummy_hpp, ret)) 845 if (advance_hpp_check(&dummy_hpp, ret))
855 break; 846 break;
@@ -1074,113 +1065,21 @@ do_offset:
1074 } 1065 }
1075} 1066}
1076 1067
1077static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
1078 struct callchain_node *chain_node,
1079 u64 total, int level,
1080 FILE *fp)
1081{
1082 struct rb_node *node;
1083 int offset = level * LEVEL_OFFSET_STEP;
1084 u64 new_total, remaining;
1085 int printed = 0;
1086
1087 if (callchain_param.mode == CHAIN_GRAPH_REL)
1088 new_total = chain_node->children_hit;
1089 else
1090 new_total = total;
1091
1092 remaining = new_total;
1093 node = rb_first(&chain_node->rb_root);
1094 while (node) {
1095 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
1096 struct rb_node *next = rb_next(node);
1097 u64 cumul = callchain_cumul_hits(child);
1098 struct callchain_list *chain;
1099 char folded_sign = ' ';
1100 int first = true;
1101 int extra_offset = 0;
1102
1103 remaining -= cumul;
1104
1105 list_for_each_entry(chain, &child->val, list) {
1106 char bf[1024], *alloc_str;
1107 const char *str;
1108 bool was_first = first;
1109
1110 if (first)
1111 first = false;
1112 else
1113 extra_offset = LEVEL_OFFSET_STEP;
1114
1115 folded_sign = callchain_list__folded(chain);
1116
1117 alloc_str = NULL;
1118 str = callchain_list__sym_name(chain, bf, sizeof(bf),
1119 browser->show_dso);
1120 if (was_first) {
1121 double percent = cumul * 100.0 / new_total;
1122
1123 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
1124 str = "Not enough memory!";
1125 else
1126 str = alloc_str;
1127 }
1128
1129 printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
1130 free(alloc_str);
1131 if (folded_sign == '+')
1132 break;
1133 }
1134
1135 if (folded_sign == '-') {
1136 const int new_level = level + (extra_offset ? 2 : 1);
1137 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
1138 new_level, fp);
1139 }
1140
1141 node = next;
1142 }
1143
1144 return printed;
1145}
1146
1147static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
1148 struct callchain_node *node,
1149 int level, FILE *fp)
1150{
1151 struct callchain_list *chain;
1152 int offset = level * LEVEL_OFFSET_STEP;
1153 char folded_sign = ' ';
1154 int printed = 0;
1155
1156 list_for_each_entry(chain, &node->val, list) {
1157 char bf[1024], *s;
1158
1159 folded_sign = callchain_list__folded(chain);
1160 s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso);
1161 printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
1162 }
1163
1164 if (folded_sign == '-')
1165 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
1166 browser->hists->stats.total_period,
1167 level + 1, fp);
1168 return printed;
1169}
1170
1171static int hist_browser__fprintf_callchain(struct hist_browser *browser, 1068static int hist_browser__fprintf_callchain(struct hist_browser *browser,
1172 struct rb_root *chain, int level, FILE *fp) 1069 struct hist_entry *he, FILE *fp)
1173{ 1070{
1174 struct rb_node *nd; 1071 u64 total = hists__total_period(he->hists);
1175 int printed = 0; 1072 struct callchain_print_arg arg = {
1073 .fp = fp,
1074 };
1176 1075
1177 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 1076 if (symbol_conf.cumulate_callchain)
1178 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 1077 total = he->stat_acc->period;
1179 1078
1180 printed += hist_browser__fprintf_callchain_node(browser, node, level, fp); 1079 hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total,
1181 } 1080 hist_browser__fprintf_callchain_entry, &arg,
1182 1081 hist_browser__check_dump_full);
1183 return printed; 1082 return arg.printed;
1184} 1083}
1185 1084
1186static int hist_browser__fprintf_entry(struct hist_browser *browser, 1085static int hist_browser__fprintf_entry(struct hist_browser *browser,
@@ -1219,7 +1118,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1219 printed += fprintf(fp, "%s\n", rtrim(s)); 1118 printed += fprintf(fp, "%s\n", rtrim(s));
1220 1119
1221 if (folded_sign == '-') 1120 if (folded_sign == '-')
1222 printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp); 1121 printed += hist_browser__fprintf_callchain(browser, he, fp);
1223 1122
1224 return printed; 1123 return printed;
1225} 1124}
@@ -1498,6 +1397,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1498 char buf[64]; 1397 char buf[64];
1499 char script_opt[64]; 1398 char script_opt[64];
1500 int delay_secs = hbt ? hbt->refresh : 0; 1399 int delay_secs = hbt ? hbt->refresh : 0;
1400 struct perf_hpp_fmt *fmt;
1501 1401
1502#define HIST_BROWSER_HELP_COMMON \ 1402#define HIST_BROWSER_HELP_COMMON \
1503 "h/?/F1 Show this window\n" \ 1403 "h/?/F1 Show this window\n" \
@@ -1529,6 +1429,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1529 "P Print histograms to perf.hist.N\n" 1429 "P Print histograms to perf.hist.N\n"
1530 "t Zoom into current Thread\n" 1430 "t Zoom into current Thread\n"
1531 "V Verbose (DSO names in callchains, etc)\n" 1431 "V Verbose (DSO names in callchains, etc)\n"
1432 "z Toggle zeroing of samples\n"
1532 "/ Filter symbol by name"; 1433 "/ Filter symbol by name";
1533 1434
1534 if (browser == NULL) 1435 if (browser == NULL)
@@ -1547,6 +1448,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1547 1448
1548 memset(options, 0, sizeof(options)); 1449 memset(options, 0, sizeof(options));
1549 1450
1451 perf_hpp__for_each_format(fmt)
1452 perf_hpp__reset_width(fmt, hists);
1453
1454 if (symbol_conf.col_width_list_str)
1455 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1456
1550 while (1) { 1457 while (1) {
1551 const struct thread *thread = NULL; 1458 const struct thread *thread = NULL;
1552 const struct dso *dso = NULL; 1459 const struct dso *dso = NULL;
@@ -1623,6 +1530,13 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1623 case 'F': 1530 case 'F':
1624 symbol_conf.filter_relative ^= 1; 1531 symbol_conf.filter_relative ^= 1;
1625 continue; 1532 continue;
1533 case 'z':
1534 if (!is_report_browser(hbt)) {
1535 struct perf_top *top = hbt->arg;
1536
1537 top->zero = !top->zero;
1538 }
1539 continue;
1626 case K_F1: 1540 case K_F1:
1627 case 'h': 1541 case 'h':
1628 case '?': 1542 case '?':
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 6ca60e482cdc..f3fa4258b256 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -11,6 +11,7 @@
11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...) 11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
12{ 12{
13 int ret = 0; 13 int ret = 0;
14 int len;
14 va_list args; 15 va_list args;
15 double percent; 16 double percent;
16 const char *markup; 17 const char *markup;
@@ -18,6 +19,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
18 size_t size = hpp->size; 19 size_t size = hpp->size;
19 20
20 va_start(args, fmt); 21 va_start(args, fmt);
22 len = va_arg(args, int);
21 percent = va_arg(args, double); 23 percent = va_arg(args, double);
22 va_end(args); 24 va_end(args);
23 25
@@ -25,7 +27,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
25 if (markup) 27 if (markup)
26 ret += scnprintf(buf, size, markup); 28 ret += scnprintf(buf, size, markup);
27 29
28 ret += scnprintf(buf + ret, size - ret, fmt, percent); 30 ret += scnprintf(buf + ret, size - ret, fmt, len, percent);
29 31
30 if (markup) 32 if (markup)
31 ret += scnprintf(buf + ret, size - ret, "</span>"); 33 ret += scnprintf(buf + ret, size - ret, "</span>");
@@ -39,12 +41,12 @@ static u64 he_get_##_field(struct hist_entry *he) \
39 return he->stat._field; \ 41 return he->stat._field; \
40} \ 42} \
41 \ 43 \
42static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 44static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
43 struct perf_hpp *hpp, \ 45 struct perf_hpp *hpp, \
44 struct hist_entry *he) \ 46 struct hist_entry *he) \
45{ \ 47{ \
46 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 48 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
47 __percent_color_snprintf, true); \ 49 __percent_color_snprintf, true); \
48} 50}
49 51
50#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 52#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -57,8 +59,8 @@ static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,
57 struct perf_hpp *hpp, \ 59 struct perf_hpp *hpp, \
58 struct hist_entry *he) \ 60 struct hist_entry *he) \
59{ \ 61{ \
60 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 62 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
61 __percent_color_snprintf, true); \ 63 __percent_color_snprintf, true); \
62} 64}
63 65
64__HPP_COLOR_PERCENT_FN(overhead, period) 66__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -205,10 +207,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
205 if (perf_hpp__is_sort_entry(fmt)) 207 if (perf_hpp__is_sort_entry(fmt))
206 sym_col = col_idx; 208 sym_col = col_idx;
207 209
208 fmt->header(fmt, &hpp, hists_to_evsel(hists));
209
210 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 210 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
211 -1, ltrim(s), 211 -1, fmt->name,
212 renderer, "markup", 212 renderer, "markup",
213 col_idx++, NULL); 213 col_idx++, NULL);
214 } 214 }
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 498adb23c02e..2af18376b077 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -15,9 +15,9 @@
15 __ret; \ 15 __ret; \
16}) 16})
17 17
18int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 18static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
19 hpp_field_fn get_field, const char *fmt, 19 hpp_field_fn get_field, const char *fmt, int len,
20 hpp_snprint_fn print_fn, bool fmt_percent) 20 hpp_snprint_fn print_fn, bool fmt_percent)
21{ 21{
22 int ret; 22 int ret;
23 struct hists *hists = he->hists; 23 struct hists *hists = he->hists;
@@ -32,9 +32,9 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
32 if (total) 32 if (total)
33 percent = 100.0 * get_field(he) / total; 33 percent = 100.0 * get_field(he) / total;
34 34
35 ret = hpp__call_print_fn(hpp, print_fn, fmt, percent); 35 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, percent);
36 } else 36 } else
37 ret = hpp__call_print_fn(hpp, print_fn, fmt, get_field(he)); 37 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he));
38 38
39 if (perf_evsel__is_group_event(evsel)) { 39 if (perf_evsel__is_group_event(evsel)) {
40 int prev_idx, idx_delta; 40 int prev_idx, idx_delta;
@@ -60,19 +60,19 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
60 */ 60 */
61 if (fmt_percent) { 61 if (fmt_percent) {
62 ret += hpp__call_print_fn(hpp, print_fn, 62 ret += hpp__call_print_fn(hpp, print_fn,
63 fmt, 0.0); 63 fmt, len, 0.0);
64 } else { 64 } else {
65 ret += hpp__call_print_fn(hpp, print_fn, 65 ret += hpp__call_print_fn(hpp, print_fn,
66 fmt, 0ULL); 66 fmt, len, 0ULL);
67 } 67 }
68 } 68 }
69 69
70 if (fmt_percent) { 70 if (fmt_percent) {
71 ret += hpp__call_print_fn(hpp, print_fn, fmt, 71 ret += hpp__call_print_fn(hpp, print_fn, fmt, len,
72 100.0 * period / total); 72 100.0 * period / total);
73 } else { 73 } else {
74 ret += hpp__call_print_fn(hpp, print_fn, fmt, 74 ret += hpp__call_print_fn(hpp, print_fn, fmt,
75 period); 75 len, period);
76 } 76 }
77 77
78 prev_idx = perf_evsel__group_idx(evsel); 78 prev_idx = perf_evsel__group_idx(evsel);
@@ -86,10 +86,10 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
86 */ 86 */
87 if (fmt_percent) { 87 if (fmt_percent) {
88 ret += hpp__call_print_fn(hpp, print_fn, 88 ret += hpp__call_print_fn(hpp, print_fn,
89 fmt, 0.0); 89 fmt, len, 0.0);
90 } else { 90 } else {
91 ret += hpp__call_print_fn(hpp, print_fn, 91 ret += hpp__call_print_fn(hpp, print_fn,
92 fmt, 0ULL); 92 fmt, len, 0ULL);
93 } 93 }
94 } 94 }
95 } 95 }
@@ -104,16 +104,35 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
104 return ret; 104 return ret;
105} 105}
106 106
107int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 107int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
108 hpp_field_fn get_field, const char *fmt, 108 struct hist_entry *he, hpp_field_fn get_field,
109 hpp_snprint_fn print_fn, bool fmt_percent) 109 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{
111 int len = fmt->user_len ?: fmt->len;
112
113 if (symbol_conf.field_sep) {
114 return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
115 print_fn, fmt_percent);
116 }
117
118 if (fmt_percent)
119 len -= 2; /* 2 for a space and a % sign */
120 else
121 len -= 1;
122
123 return __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent);
124}
125
126int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
127 struct hist_entry *he, hpp_field_fn get_field,
128 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{ 129{
111 if (!symbol_conf.cumulate_callchain) { 130 if (!symbol_conf.cumulate_callchain) {
112 return snprintf(hpp->buf, hpp->size, "%*s", 131 int len = fmt->user_len ?: fmt->len;
113 fmt_percent ? 8 : 12, "N/A"); 132 return snprintf(hpp->buf, hpp->size, " %*s", len - 1, "N/A");
114 } 133 }
115 134
116 return __hpp__fmt(hpp, he, get_field, fmt, print_fn, fmt_percent); 135 return hpp__fmt(fmt, hpp, he, get_field, fmtstr, print_fn, fmt_percent);
117} 136}
118 137
119static int field_cmp(u64 field_a, u64 field_b) 138static int field_cmp(u64 field_a, u64 field_b)
@@ -190,30 +209,26 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
190 return ret; 209 return ret;
191} 210}
192 211
193#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 212static int hpp__width_fn(struct perf_hpp_fmt *fmt,
194static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 213 struct perf_hpp *hpp __maybe_unused,
195 struct perf_hpp *hpp, \ 214 struct perf_evsel *evsel)
196 struct perf_evsel *evsel) \ 215{
197{ \ 216 int len = fmt->user_len ?: fmt->len;
198 int len = _min_width; \ 217
199 \ 218 if (symbol_conf.event_group)
200 if (symbol_conf.event_group) \ 219 len = max(len, evsel->nr_members * fmt->len);
201 len = max(len, evsel->nr_members * _unit_width); \ 220
202 \ 221 if (len < (int)strlen(fmt->name))
203 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \ 222 len = strlen(fmt->name);
204} 223
205 224 return len;
206#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 225}
207static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 226
208 struct perf_hpp *hpp __maybe_unused, \ 227static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
209 struct perf_evsel *evsel) \ 228 struct perf_evsel *evsel)
210{ \ 229{
211 int len = _min_width; \ 230 int len = hpp__width_fn(fmt, hpp, evsel);
212 \ 231 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
213 if (symbol_conf.event_group) \
214 len = max(len, evsel->nr_members * _unit_width); \
215 \
216 return len; \
217} 232}
218 233
219static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 234static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
@@ -221,11 +236,12 @@ static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
221 va_list args; 236 va_list args;
222 ssize_t ssize = hpp->size; 237 ssize_t ssize = hpp->size;
223 double percent; 238 double percent;
224 int ret; 239 int ret, len;
225 240
226 va_start(args, fmt); 241 va_start(args, fmt);
242 len = va_arg(args, int);
227 percent = va_arg(args, double); 243 percent = va_arg(args, double);
228 ret = value_color_snprintf(hpp->buf, hpp->size, fmt, percent); 244 ret = percent_color_len_snprintf(hpp->buf, hpp->size, fmt, len, percent);
229 va_end(args); 245 va_end(args);
230 246
231 return (ret >= ssize) ? (ssize - 1) : ret; 247 return (ret >= ssize) ? (ssize - 1) : ret;
@@ -250,20 +266,19 @@ static u64 he_get_##_field(struct hist_entry *he) \
250 return he->stat._field; \ 266 return he->stat._field; \
251} \ 267} \
252 \ 268 \
253static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 269static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
254 struct perf_hpp *hpp, struct hist_entry *he) \ 270 struct perf_hpp *hpp, struct hist_entry *he) \
255{ \ 271{ \
256 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 272 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
257 hpp_color_scnprintf, true); \ 273 hpp_color_scnprintf, true); \
258} 274}
259 275
260#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 276#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
261static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 277static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
262 struct perf_hpp *hpp, struct hist_entry *he) \ 278 struct perf_hpp *hpp, struct hist_entry *he) \
263{ \ 279{ \
264 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 280 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
265 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ 281 hpp_entry_scnprintf, true); \
266 hpp_entry_scnprintf, true); \
267} 282}
268 283
269#define __HPP_SORT_FN(_type, _field) \ 284#define __HPP_SORT_FN(_type, _field) \
@@ -278,20 +293,19 @@ static u64 he_get_acc_##_field(struct hist_entry *he) \
278 return he->stat_acc->_field; \ 293 return he->stat_acc->_field; \
279} \ 294} \
280 \ 295 \
281static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 296static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
282 struct perf_hpp *hpp, struct hist_entry *he) \ 297 struct perf_hpp *hpp, struct hist_entry *he) \
283{ \ 298{ \
284 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 299 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
285 hpp_color_scnprintf, true); \ 300 hpp_color_scnprintf, true); \
286} 301}
287 302
288#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 303#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
289static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 304static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
290 struct perf_hpp *hpp, struct hist_entry *he) \ 305 struct perf_hpp *hpp, struct hist_entry *he) \
291{ \ 306{ \
292 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 307 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
293 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, fmt, \ 308 hpp_entry_scnprintf, true); \
294 hpp_entry_scnprintf, true); \
295} 309}
296 310
297#define __HPP_SORT_ACC_FN(_type, _field) \ 311#define __HPP_SORT_ACC_FN(_type, _field) \
@@ -306,12 +320,11 @@ static u64 he_get_raw_##_field(struct hist_entry *he) \
306 return he->stat._field; \ 320 return he->stat._field; \
307} \ 321} \
308 \ 322 \
309static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 323static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
310 struct perf_hpp *hpp, struct hist_entry *he) \ 324 struct perf_hpp *hpp, struct hist_entry *he) \
311{ \ 325{ \
312 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ 326 return hpp__fmt(fmt, hpp, he, he_get_raw_##_field, " %*"PRIu64, \
313 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, \ 327 hpp_entry_scnprintf, false); \
314 hpp_entry_scnprintf, false); \
315} 328}
316 329
317#define __HPP_SORT_RAW_FN(_type, _field) \ 330#define __HPP_SORT_RAW_FN(_type, _field) \
@@ -321,37 +334,29 @@ static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \
321} 334}
322 335
323 336
324#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \ 337#define HPP_PERCENT_FNS(_type, _field) \
325__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
326__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
327__HPP_COLOR_PERCENT_FN(_type, _field) \ 338__HPP_COLOR_PERCENT_FN(_type, _field) \
328__HPP_ENTRY_PERCENT_FN(_type, _field) \ 339__HPP_ENTRY_PERCENT_FN(_type, _field) \
329__HPP_SORT_FN(_type, _field) 340__HPP_SORT_FN(_type, _field)
330 341
331#define HPP_PERCENT_ACC_FNS(_type, _str, _field, _min_width, _unit_width)\ 342#define HPP_PERCENT_ACC_FNS(_type, _field) \
332__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
333__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
334__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 343__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
335__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 344__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
336__HPP_SORT_ACC_FN(_type, _field) 345__HPP_SORT_ACC_FN(_type, _field)
337 346
338#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width) \ 347#define HPP_RAW_FNS(_type, _field) \
339__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
340__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
341__HPP_ENTRY_RAW_FN(_type, _field) \ 348__HPP_ENTRY_RAW_FN(_type, _field) \
342__HPP_SORT_RAW_FN(_type, _field) 349__HPP_SORT_RAW_FN(_type, _field)
343 350
344__HPP_HEADER_FN(overhead_self, "Self", 8, 8) 351HPP_PERCENT_FNS(overhead, period)
345 352HPP_PERCENT_FNS(overhead_sys, period_sys)
346HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8) 353HPP_PERCENT_FNS(overhead_us, period_us)
347HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8) 354HPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys)
348HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8) 355HPP_PERCENT_FNS(overhead_guest_us, period_guest_us)
349HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8) 356HPP_PERCENT_ACC_FNS(overhead_acc, period)
350HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
351HPP_PERCENT_ACC_FNS(overhead_acc, "Children", period, 8, 8)
352 357
353HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) 358HPP_RAW_FNS(samples, nr_events)
354HPP_RAW_FNS(period, "Period", period, 12, 12) 359HPP_RAW_FNS(period, period)
355 360
356static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused, 361static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
357 struct hist_entry *b __maybe_unused) 362 struct hist_entry *b __maybe_unused)
@@ -359,47 +364,50 @@ static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
359 return 0; 364 return 0;
360} 365}
361 366
362#define HPP__COLOR_PRINT_FNS(_name) \ 367#define HPP__COLOR_PRINT_FNS(_name, _fn) \
363 { \ 368 { \
364 .header = hpp__header_ ## _name, \ 369 .name = _name, \
365 .width = hpp__width_ ## _name, \ 370 .header = hpp__header_fn, \
366 .color = hpp__color_ ## _name, \ 371 .width = hpp__width_fn, \
367 .entry = hpp__entry_ ## _name, \ 372 .color = hpp__color_ ## _fn, \
373 .entry = hpp__entry_ ## _fn, \
368 .cmp = hpp__nop_cmp, \ 374 .cmp = hpp__nop_cmp, \
369 .collapse = hpp__nop_cmp, \ 375 .collapse = hpp__nop_cmp, \
370 .sort = hpp__sort_ ## _name, \ 376 .sort = hpp__sort_ ## _fn, \
371 } 377 }
372 378
373#define HPP__COLOR_ACC_PRINT_FNS(_name) \ 379#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn) \
374 { \ 380 { \
375 .header = hpp__header_ ## _name, \ 381 .name = _name, \
376 .width = hpp__width_ ## _name, \ 382 .header = hpp__header_fn, \
377 .color = hpp__color_ ## _name, \ 383 .width = hpp__width_fn, \
378 .entry = hpp__entry_ ## _name, \ 384 .color = hpp__color_ ## _fn, \
385 .entry = hpp__entry_ ## _fn, \
379 .cmp = hpp__nop_cmp, \ 386 .cmp = hpp__nop_cmp, \
380 .collapse = hpp__nop_cmp, \ 387 .collapse = hpp__nop_cmp, \
381 .sort = hpp__sort_ ## _name, \ 388 .sort = hpp__sort_ ## _fn, \
382 } 389 }
383 390
384#define HPP__PRINT_FNS(_name) \ 391#define HPP__PRINT_FNS(_name, _fn) \
385 { \ 392 { \
386 .header = hpp__header_ ## _name, \ 393 .name = _name, \
387 .width = hpp__width_ ## _name, \ 394 .header = hpp__header_fn, \
388 .entry = hpp__entry_ ## _name, \ 395 .width = hpp__width_fn, \
396 .entry = hpp__entry_ ## _fn, \
389 .cmp = hpp__nop_cmp, \ 397 .cmp = hpp__nop_cmp, \
390 .collapse = hpp__nop_cmp, \ 398 .collapse = hpp__nop_cmp, \
391 .sort = hpp__sort_ ## _name, \ 399 .sort = hpp__sort_ ## _fn, \
392 } 400 }
393 401
394struct perf_hpp_fmt perf_hpp__format[] = { 402struct perf_hpp_fmt perf_hpp__format[] = {
395 HPP__COLOR_PRINT_FNS(overhead), 403 HPP__COLOR_PRINT_FNS("Overhead", overhead),
396 HPP__COLOR_PRINT_FNS(overhead_sys), 404 HPP__COLOR_PRINT_FNS("sys", overhead_sys),
397 HPP__COLOR_PRINT_FNS(overhead_us), 405 HPP__COLOR_PRINT_FNS("usr", overhead_us),
398 HPP__COLOR_PRINT_FNS(overhead_guest_sys), 406 HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys),
399 HPP__COLOR_PRINT_FNS(overhead_guest_us), 407 HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us),
400 HPP__COLOR_ACC_PRINT_FNS(overhead_acc), 408 HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc),
401 HPP__PRINT_FNS(samples), 409 HPP__PRINT_FNS("Samples", samples),
402 HPP__PRINT_FNS(period) 410 HPP__PRINT_FNS("Period", period)
403}; 411};
404 412
405LIST_HEAD(perf_hpp__list); 413LIST_HEAD(perf_hpp__list);
@@ -444,14 +452,12 @@ void perf_hpp__init(void)
444 /* 452 /*
445 * If user specified field order, no need to setup default fields. 453 * If user specified field order, no need to setup default fields.
446 */ 454 */
447 if (field_order) 455 if (is_strict_order(field_order))
448 return; 456 return;
449 457
450 if (symbol_conf.cumulate_callchain) { 458 if (symbol_conf.cumulate_callchain) {
451 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC); 459 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC);
452 460 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self";
453 perf_hpp__format[PERF_HPP__OVERHEAD].header =
454 hpp__header_overhead_self;
455 } 461 }
456 462
457 perf_hpp__column_enable(PERF_HPP__OVERHEAD); 463 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
@@ -513,11 +519,11 @@ void perf_hpp__column_disable(unsigned col)
513 519
514void perf_hpp__cancel_cumulate(void) 520void perf_hpp__cancel_cumulate(void)
515{ 521{
516 if (field_order) 522 if (is_strict_order(field_order))
517 return; 523 return;
518 524
519 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC); 525 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC);
520 perf_hpp__format[PERF_HPP__OVERHEAD].header = hpp__header_overhead; 526 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead";
521} 527}
522 528
523void perf_hpp__setup_output_field(void) 529void perf_hpp__setup_output_field(void)
@@ -622,3 +628,59 @@ unsigned int hists__sort_list_width(struct hists *hists)
622 628
623 return ret; 629 return ret;
624} 630}
631
632void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
633{
634 int idx;
635
636 if (perf_hpp__is_sort_entry(fmt))
637 return perf_hpp__reset_sort_width(fmt, hists);
638
639 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
640 if (fmt == &perf_hpp__format[idx])
641 break;
642 }
643
644 if (idx == PERF_HPP__MAX_INDEX)
645 return;
646
647 switch (idx) {
648 case PERF_HPP__OVERHEAD:
649 case PERF_HPP__OVERHEAD_SYS:
650 case PERF_HPP__OVERHEAD_US:
651 case PERF_HPP__OVERHEAD_ACC:
652 fmt->len = 8;
653 break;
654
655 case PERF_HPP__OVERHEAD_GUEST_SYS:
656 case PERF_HPP__OVERHEAD_GUEST_US:
657 fmt->len = 9;
658 break;
659
660 case PERF_HPP__SAMPLES:
661 case PERF_HPP__PERIOD:
662 fmt->len = 12;
663 break;
664
665 default:
666 break;
667 }
668}
669
670void perf_hpp__set_user_width(const char *width_list_str)
671{
672 struct perf_hpp_fmt *fmt;
673 const char *ptr = width_list_str;
674
675 perf_hpp__for_each_format(fmt) {
676 char *p;
677
678 int len = strtol(ptr, &p, 10);
679 fmt->user_len = len;
680
681 if (*p == ',')
682 ptr = p + 1;
683 else
684 break;
685 }
686}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 40af0acb4fe9..15b451acbde6 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -395,10 +395,12 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
395 395
396 init_rem_hits(); 396 init_rem_hits();
397 397
398
399 perf_hpp__for_each_format(fmt) 398 perf_hpp__for_each_format(fmt)
400 perf_hpp__reset_width(fmt, hists); 399 perf_hpp__reset_width(fmt, hists);
401 400
401 if (symbol_conf.col_width_list_str)
402 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
403
402 if (!show_header) 404 if (!show_header)
403 goto print_entries; 405 goto print_entries;
404 406
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 809b4c50beae..36437527dbb3 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -232,9 +232,16 @@ static int mov__parse(struct ins_operands *ops)
232 return -1; 232 return -1;
233 233
234 target = ++s; 234 target = ++s;
235 comment = strchr(s, '#');
235 236
236 while (s[0] != '\0' && !isspace(s[0])) 237 if (comment != NULL)
237 ++s; 238 s = comment - 1;
239 else
240 s = strchr(s, '\0') - 1;
241
242 while (s > target && isspace(s[0]))
243 --s;
244 s++;
238 prev = *s; 245 prev = *s;
239 *s = '\0'; 246 *s = '\0';
240 247
@@ -244,7 +251,6 @@ static int mov__parse(struct ins_operands *ops)
244 if (ops->target.raw == NULL) 251 if (ops->target.raw == NULL)
245 goto out_free_source; 252 goto out_free_source;
246 253
247 comment = strchr(s, '#');
248 if (comment == NULL) 254 if (comment == NULL)
249 return 0; 255 return 0;
250 256
@@ -899,10 +905,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
899 struct kcore_extract kce; 905 struct kcore_extract kce;
900 bool delete_extract = false; 906 bool delete_extract = false;
901 907
902 if (filename) { 908 if (filename)
903 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 909 symbol__join_symfs(symfs_filename, filename);
904 symbol_conf.symfs, filename);
905 }
906 910
907 if (filename == NULL) { 911 if (filename == NULL) {
908 if (dso->has_build_id) { 912 if (dso->has_build_id) {
@@ -922,8 +926,7 @@ fallback:
922 * DSO is the same as when 'perf record' ran. 926 * DSO is the same as when 'perf record' ran.
923 */ 927 */
924 filename = (char *)dso->long_name; 928 filename = (char *)dso->long_name;
925 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 929 symbol__join_symfs(symfs_filename, filename);
926 symbol_conf.symfs, filename);
927 free_filename = false; 930 free_filename = false;
928 } 931 }
929 932
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 7b176dd02e1a..5cf9e1b5989d 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -22,6 +22,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 22extern int perf_default_config(const char *, const char *, void *);
23extern int perf_config(config_fn_t fn, void *); 23extern int perf_config(config_fn_t fn, void *);
24extern int perf_config_int(const char *, const char *); 24extern int perf_config_int(const char *, const char *);
25extern u64 perf_config_u64(const char *, const char *);
25extern int perf_config_bool(const char *, const char *); 26extern int perf_config_bool(const char *, const char *);
26extern int config_error_nonbool(const char *); 27extern int config_error_nonbool(const char *);
27extern const char *perf_config_dirname(const char *, const char *); 28extern const char *perf_config_dirname(const char *, const char *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 437ee09727e6..c84d3f8dcb75 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,77 +25,172 @@
25 25
26__thread struct callchain_cursor callchain_cursor; 26__thread struct callchain_cursor callchain_cursor;
27 27
28int 28#ifdef HAVE_DWARF_UNWIND_SUPPORT
29parse_callchain_report_opt(const char *arg) 29static int get_stack_size(const char *str, unsigned long *_size)
30{ 30{
31 char *tok, *tok2;
32 char *endptr; 31 char *endptr;
32 unsigned long size;
33 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
33 34
34 symbol_conf.use_callchain = true; 35 size = strtoul(str, &endptr, 0);
35 36
36 if (!arg) 37 do {
38 if (*endptr)
39 break;
40
41 size = round_up(size, sizeof(u64));
42 if (!size || size > max_size)
43 break;
44
45 *_size = size;
37 return 0; 46 return 0;
38 47
39 tok = strtok((char *)arg, ","); 48 } while (0);
40 if (!tok)
41 return -1;
42 49
43 /* get the output mode */ 50 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
44 if (!strncmp(tok, "graph", strlen(arg))) { 51 max_size, str);
45 callchain_param.mode = CHAIN_GRAPH_ABS; 52 return -1;
53}
54#endif /* HAVE_DWARF_UNWIND_SUPPORT */
46 55
47 } else if (!strncmp(tok, "flat", strlen(arg))) { 56int parse_callchain_record_opt(const char *arg)
48 callchain_param.mode = CHAIN_FLAT; 57{
49 } else if (!strncmp(tok, "fractal", strlen(arg))) { 58 char *tok, *name, *saveptr = NULL;
50 callchain_param.mode = CHAIN_GRAPH_REL; 59 char *buf;
51 } else if (!strncmp(tok, "none", strlen(arg))) { 60 int ret = -1;
52 callchain_param.mode = CHAIN_NONE; 61
53 symbol_conf.use_callchain = false; 62 /* We need buffer that we know we can write to. */
54 return 0; 63 buf = malloc(strlen(arg) + 1);
55 } else { 64 if (!buf)
56 return -1; 65 return -ENOMEM;
57 } 66
67 strcpy(buf, arg);
68
69 tok = strtok_r((char *)buf, ",", &saveptr);
70 name = tok ? : (char *)buf;
71
72 do {
73 /* Framepointer style */
74 if (!strncmp(name, "fp", sizeof("fp"))) {
75 if (!strtok_r(NULL, ",", &saveptr)) {
76 callchain_param.record_mode = CALLCHAIN_FP;
77 ret = 0;
78 } else
79 pr_err("callchain: No more arguments "
80 "needed for -g fp\n");
81 break;
58 82
59 /* get the min percentage */ 83#ifdef HAVE_DWARF_UNWIND_SUPPORT
60 tok = strtok(NULL, ","); 84 /* Dwarf style */
61 if (!tok) 85 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
62 goto setup; 86 const unsigned long default_stack_dump_size = 8192;
63 87
64 callchain_param.min_percent = strtod(tok, &endptr); 88 ret = 0;
65 if (tok == endptr) 89 callchain_param.record_mode = CALLCHAIN_DWARF;
66 return -1; 90 callchain_param.dump_size = default_stack_dump_size;
67 91
68 /* get the print limit */ 92 tok = strtok_r(NULL, ",", &saveptr);
69 tok2 = strtok(NULL, ","); 93 if (tok) {
70 if (!tok2) 94 unsigned long size = 0;
71 goto setup;
72 95
73 if (tok2[0] != 'c') { 96 ret = get_stack_size(tok, &size);
74 callchain_param.print_limit = strtoul(tok2, &endptr, 0); 97 callchain_param.dump_size = size;
75 tok2 = strtok(NULL, ","); 98 }
76 if (!tok2) 99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
77 goto setup; 100 } else {
101 pr_err("callchain: Unknown --call-graph option "
102 "value: %s\n", arg);
103 break;
104 }
105
106 } while (0);
107
108 free(buf);
109 return ret;
110}
111
112static int parse_callchain_mode(const char *value)
113{
114 if (!strncmp(value, "graph", strlen(value))) {
115 callchain_param.mode = CHAIN_GRAPH_ABS;
116 return 0;
117 }
118 if (!strncmp(value, "flat", strlen(value))) {
119 callchain_param.mode = CHAIN_FLAT;
120 return 0;
78 } 121 }
122 if (!strncmp(value, "fractal", strlen(value))) {
123 callchain_param.mode = CHAIN_GRAPH_REL;
124 return 0;
125 }
126 return -1;
127}
79 128
80 /* get the call chain order */ 129static int parse_callchain_order(const char *value)
81 if (!strncmp(tok2, "caller", strlen("caller"))) 130{
131 if (!strncmp(value, "caller", strlen(value))) {
82 callchain_param.order = ORDER_CALLER; 132 callchain_param.order = ORDER_CALLER;
83 else if (!strncmp(tok2, "callee", strlen("callee"))) 133 return 0;
134 }
135 if (!strncmp(value, "callee", strlen(value))) {
84 callchain_param.order = ORDER_CALLEE; 136 callchain_param.order = ORDER_CALLEE;
85 else 137 return 0;
86 return -1; 138 }
139 return -1;
140}
87 141
88 /* Get the sort key */ 142static int parse_callchain_sort_key(const char *value)
89 tok2 = strtok(NULL, ","); 143{
90 if (!tok2) 144 if (!strncmp(value, "function", strlen(value))) {
91 goto setup;
92 if (!strncmp(tok2, "function", strlen("function")))
93 callchain_param.key = CCKEY_FUNCTION; 145 callchain_param.key = CCKEY_FUNCTION;
94 else if (!strncmp(tok2, "address", strlen("address"))) 146 return 0;
147 }
148 if (!strncmp(value, "address", strlen(value))) {
95 callchain_param.key = CCKEY_ADDRESS; 149 callchain_param.key = CCKEY_ADDRESS;
96 else 150 return 0;
97 return -1; 151 }
98setup: 152 return -1;
153}
154
155int
156parse_callchain_report_opt(const char *arg)
157{
158 char *tok;
159 char *endptr;
160 bool minpcnt_set = false;
161
162 symbol_conf.use_callchain = true;
163
164 if (!arg)
165 return 0;
166
167 while ((tok = strtok((char *)arg, ",")) != NULL) {
168 if (!strncmp(tok, "none", strlen(tok))) {
169 callchain_param.mode = CHAIN_NONE;
170 symbol_conf.use_callchain = false;
171 return 0;
172 }
173
174 if (!parse_callchain_mode(tok) ||
175 !parse_callchain_order(tok) ||
176 !parse_callchain_sort_key(tok)) {
177 /* parsing ok - move on to the next */
178 } else if (!minpcnt_set) {
179 /* try to get the min percent */
180 callchain_param.min_percent = strtod(tok, &endptr);
181 if (tok == endptr)
182 return -1;
183 minpcnt_set = true;
184 } else {
185 /* try print limit at last */
186 callchain_param.print_limit = strtoul(tok, &endptr, 0);
187 if (tok == endptr)
188 return -1;
189 }
190
191 arg = NULL;
192 }
193
99 if (callchain_register_param(&callchain_param) < 0) { 194 if (callchain_register_param(&callchain_param) < 0) {
100 pr_err("Can't register callchain params\n"); 195 pr_err("Can't register callchain params\n");
101 return -1; 196 return -1;
@@ -103,6 +198,47 @@ setup:
103 return 0; 198 return 0;
104} 199}
105 200
201int perf_callchain_config(const char *var, const char *value)
202{
203 char *endptr;
204
205 if (prefixcmp(var, "call-graph."))
206 return 0;
207 var += sizeof("call-graph.") - 1;
208
209 if (!strcmp(var, "record-mode"))
210 return parse_callchain_record_opt(value);
211#ifdef HAVE_DWARF_UNWIND_SUPPORT
212 if (!strcmp(var, "dump-size")) {
213 unsigned long size = 0;
214 int ret;
215
216 ret = get_stack_size(value, &size);
217 callchain_param.dump_size = size;
218
219 return ret;
220 }
221#endif
222 if (!strcmp(var, "print-type"))
223 return parse_callchain_mode(value);
224 if (!strcmp(var, "order"))
225 return parse_callchain_order(value);
226 if (!strcmp(var, "sort-key"))
227 return parse_callchain_sort_key(value);
228 if (!strcmp(var, "threshold")) {
229 callchain_param.min_percent = strtod(value, &endptr);
230 if (value == endptr)
231 return -1;
232 }
233 if (!strcmp(var, "print-limit")) {
234 callchain_param.print_limit = strtod(value, &endptr);
235 if (value == endptr)
236 return -1;
237 }
238
239 return 0;
240}
241
106static void 242static void
107rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 243rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
108 enum chain_mode mode) 244 enum chain_mode mode)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index da43619d6173..2a1f5a46543a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -54,6 +54,9 @@ enum chain_key {
54}; 54};
55 55
56struct callchain_param { 56struct callchain_param {
57 bool enabled;
58 enum perf_call_graph_mode record_mode;
59 u32 dump_size;
57 enum chain_mode mode; 60 enum chain_mode mode;
58 u32 print_limit; 61 u32 print_limit;
59 double min_percent; 62 double min_percent;
@@ -154,7 +157,6 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
154struct option; 157struct option;
155struct hist_entry; 158struct hist_entry;
156 159
157int record_parse_callchain(const char *arg, struct record_opts *opts);
158int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 160int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
159int record_callchain_opt(const struct option *opt, const char *arg, int unset); 161int record_callchain_opt(const struct option *opt, const char *arg, int unset);
160 162
@@ -166,7 +168,9 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
166 bool hide_unresolved); 168 bool hide_unresolved);
167 169
168extern const char record_callchain_help[]; 170extern const char record_callchain_help[];
171int parse_callchain_record_opt(const char *arg);
169int parse_callchain_report_opt(const char *arg); 172int parse_callchain_report_opt(const char *arg);
173int perf_callchain_config(const char *var, const char *value);
170 174
171static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, 175static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
172 struct callchain_cursor *src) 176 struct callchain_cursor *src)
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index c5d05ec17220..47b78b3f0325 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,7 +1,9 @@
1#include <sched.h>
1#include "util.h" 2#include "util.h"
2#include "../perf.h" 3#include "../perf.h"
3#include "cloexec.h" 4#include "cloexec.h"
4#include "asm/bug.h" 5#include "asm/bug.h"
6#include "debug.h"
5 7
6static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 8static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
7 9
@@ -9,15 +11,30 @@ static int perf_flag_probe(void)
9{ 11{
10 /* use 'safest' configuration as used in perf_evsel__fallback() */ 12 /* use 'safest' configuration as used in perf_evsel__fallback() */
11 struct perf_event_attr attr = { 13 struct perf_event_attr attr = {
12 .type = PERF_COUNT_SW_CPU_CLOCK, 14 .type = PERF_TYPE_SOFTWARE,
13 .config = PERF_COUNT_SW_CPU_CLOCK, 15 .config = PERF_COUNT_SW_CPU_CLOCK,
16 .exclude_kernel = 1,
14 }; 17 };
15 int fd; 18 int fd;
16 int err; 19 int err;
20 int cpu;
21 pid_t pid = -1;
22 char sbuf[STRERR_BUFSIZE];
17 23
18 /* check cloexec flag */ 24 cpu = sched_getcpu();
19 fd = sys_perf_event_open(&attr, 0, -1, -1, 25 if (cpu < 0)
20 PERF_FLAG_FD_CLOEXEC); 26 cpu = 0;
27
28 while (1) {
29 /* check cloexec flag */
30 fd = sys_perf_event_open(&attr, pid, cpu, -1,
31 PERF_FLAG_FD_CLOEXEC);
32 if (fd < 0 && pid == -1 && errno == EACCES) {
33 pid = 0;
34 continue;
35 }
36 break;
37 }
21 err = errno; 38 err = errno;
22 39
23 if (fd >= 0) { 40 if (fd >= 0) {
@@ -25,17 +42,17 @@ static int perf_flag_probe(void)
25 return 1; 42 return 1;
26 } 43 }
27 44
28 WARN_ONCE(err != EINVAL, 45 WARN_ONCE(err != EINVAL && err != EBUSY,
29 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 46 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
30 err, strerror(err)); 47 err, strerror_r(err, sbuf, sizeof(sbuf)));
31 48
32 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 49 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
33 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 50 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
34 err = errno; 51 err = errno;
35 52
36 if (WARN_ONCE(fd < 0, 53 if (WARN_ONCE(fd < 0 && err != EBUSY,
37 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 54 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
38 err, strerror(err))) 55 err, strerror_r(err, sbuf, sizeof(sbuf))))
39 return -1; 56 return -1;
40 57
41 close(fd); 58 close(fd);
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 87b8672eb413..f4654183d391 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -335,3 +335,19 @@ int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
335 va_end(args); 335 va_end(args);
336 return value_color_snprintf(bf, size, fmt, percent); 336 return value_color_snprintf(bf, size, fmt, percent);
337} 337}
338
339int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
340{
341 va_list args;
342 int len;
343 double percent;
344 const char *color;
345
346 va_start(args, fmt);
347 len = va_arg(args, int);
348 percent = va_arg(args, double);
349 va_end(args);
350
351 color = get_percent_color(percent);
352 return color_snprintf(bf, size, color, fmt, len, percent);
353}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 7ff30a62a132..0a594b8a0c26 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -41,6 +41,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); 42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 45int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
45const char *get_percent_color(double percent); 46const char *get_percent_color(double percent);
46 47
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index f9e777629e21..b2bb59df65e1 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -74,7 +74,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
74 return new; 74 return new;
75} 75}
76 76
77struct comm *comm__new(const char *str, u64 timestamp) 77struct comm *comm__new(const char *str, u64 timestamp, bool exec)
78{ 78{
79 struct comm *comm = zalloc(sizeof(*comm)); 79 struct comm *comm = zalloc(sizeof(*comm));
80 80
@@ -82,6 +82,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
82 return NULL; 82 return NULL;
83 83
84 comm->start = timestamp; 84 comm->start = timestamp;
85 comm->exec = exec;
85 86
86 comm->comm_str = comm_str__findnew(str, &comm_str_root); 87 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) { 88 if (!comm->comm_str) {
@@ -94,7 +95,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
94 return comm; 95 return comm;
95} 96}
96 97
97int comm__override(struct comm *comm, const char *str, u64 timestamp) 98int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
98{ 99{
99 struct comm_str *new, *old = comm->comm_str; 100 struct comm_str *new, *old = comm->comm_str;
100 101
@@ -106,6 +107,8 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp)
106 comm_str__put(old); 107 comm_str__put(old);
107 comm->comm_str = new; 108 comm->comm_str = new;
108 comm->start = timestamp; 109 comm->start = timestamp;
110 if (exec)
111 comm->exec = true;
109 112
110 return 0; 113 return 0;
111} 114}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index fac5bd51befc..51c10ab257f8 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -11,11 +11,13 @@ struct comm {
11 struct comm_str *comm_str; 11 struct comm_str *comm_str;
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec;
14}; 15};
15 16
16void comm__free(struct comm *comm); 17void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp); 18struct comm *comm__new(const char *str, u64 timestamp, bool exec);
18const char *comm__str(const struct comm *comm); 19const char *comm__str(const struct comm *comm);
19int comm__override(struct comm *comm, const char *str, u64 timestamp); 20int comm__override(struct comm *comm, const char *str, u64 timestamp,
21 bool exec);
20 22
21#endif /* __PERF_COMM_H */ 23#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 1e5e2e5af6b1..57ff826f150b 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -222,7 +222,8 @@ static int perf_parse_file(config_fn_t fn, void *data)
222 const unsigned char *bomptr = utf8_bom; 222 const unsigned char *bomptr = utf8_bom;
223 223
224 for (;;) { 224 for (;;) {
225 int c = get_next_char(); 225 int line, c = get_next_char();
226
226 if (bomptr && *bomptr) { 227 if (bomptr && *bomptr) {
227 /* We are at the file beginning; skip UTF8-encoded BOM 228 /* We are at the file beginning; skip UTF8-encoded BOM
228 * if present. Sane editors won't put this in on their 229 * if present. Sane editors won't put this in on their
@@ -261,8 +262,16 @@ static int perf_parse_file(config_fn_t fn, void *data)
261 if (!isalpha(c)) 262 if (!isalpha(c))
262 break; 263 break;
263 var[baselen] = tolower(c); 264 var[baselen] = tolower(c);
264 if (get_value(fn, data, var, baselen+1) < 0) 265
266 /*
267 * The get_value function might or might not reach the '\n',
268 * so saving the current line number for error reporting.
269 */
270 line = config_linenr;
271 if (get_value(fn, data, var, baselen+1) < 0) {
272 config_linenr = line;
265 break; 273 break;
274 }
266 } 275 }
267 die("bad config file line %d in %s", config_linenr, config_file_name); 276 die("bad config file line %d in %s", config_linenr, config_file_name);
268} 277}
@@ -286,6 +295,21 @@ static int parse_unit_factor(const char *end, unsigned long *val)
286 return 0; 295 return 0;
287} 296}
288 297
298static int perf_parse_llong(const char *value, long long *ret)
299{
300 if (value && *value) {
301 char *end;
302 long long val = strtoll(value, &end, 0);
303 unsigned long factor = 1;
304
305 if (!parse_unit_factor(end, &factor))
306 return 0;
307 *ret = val * factor;
308 return 1;
309 }
310 return 0;
311}
312
289static int perf_parse_long(const char *value, long *ret) 313static int perf_parse_long(const char *value, long *ret)
290{ 314{
291 if (value && *value) { 315 if (value && *value) {
@@ -307,6 +331,15 @@ static void die_bad_config(const char *name)
307 die("bad config value for '%s'", name); 331 die("bad config value for '%s'", name);
308} 332}
309 333
334u64 perf_config_u64(const char *name, const char *value)
335{
336 long long ret = 0;
337
338 if (!perf_parse_llong(value, &ret))
339 die_bad_config(name);
340 return (u64) ret;
341}
342
310int perf_config_int(const char *name, const char *value) 343int perf_config_int(const char *name, const char *value)
311{ 344{
312 long ret = 0; 345 long ret = 0;
@@ -372,6 +405,9 @@ int perf_default_config(const char *var, const char *value,
372 if (!prefixcmp(var, "ui.")) 405 if (!prefixcmp(var, "ui."))
373 return perf_ui_config(var, value); 406 return perf_ui_config(var, value);
374 407
408 if (!prefixcmp(var, "call-graph."))
409 return perf_callchain_config(var, value);
410
375 /* Add other config variables here. */ 411 /* Add other config variables here. */
376 return 0; 412 return 0;
377} 413}
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 29d720cf5844..1921942fc2e0 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -50,12 +50,14 @@ static int open_file_read(struct perf_data_file *file)
50{ 50{
51 struct stat st; 51 struct stat st;
52 int fd; 52 int fd;
53 char sbuf[STRERR_BUFSIZE];
53 54
54 fd = open(file->path, O_RDONLY); 55 fd = open(file->path, O_RDONLY);
55 if (fd < 0) { 56 if (fd < 0) {
56 int err = errno; 57 int err = errno;
57 58
58 pr_err("failed to open %s: %s", file->path, strerror(err)); 59 pr_err("failed to open %s: %s", file->path,
60 strerror_r(err, sbuf, sizeof(sbuf)));
59 if (err == ENOENT && !strcmp(file->path, "perf.data")) 61 if (err == ENOENT && !strcmp(file->path, "perf.data"))
60 pr_err(" (try 'perf record' first)"); 62 pr_err(" (try 'perf record' first)");
61 pr_err("\n"); 63 pr_err("\n");
@@ -88,6 +90,7 @@ static int open_file_read(struct perf_data_file *file)
88static int open_file_write(struct perf_data_file *file) 90static int open_file_write(struct perf_data_file *file)
89{ 91{
90 int fd; 92 int fd;
93 char sbuf[STRERR_BUFSIZE];
91 94
92 if (check_backup(file)) 95 if (check_backup(file))
93 return -1; 96 return -1;
@@ -95,7 +98,8 @@ static int open_file_write(struct perf_data_file *file)
95 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 98 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
96 99
97 if (fd < 0) 100 if (fd < 0)
98 pr_err("failed to open %s : %s\n", file->path, strerror(errno)); 101 pr_err("failed to open %s : %s\n", file->path,
102 strerror_r(errno, sbuf, sizeof(sbuf)));
99 103
100 return fd; 104 return fd;
101} 105}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 71d419362634..ba357f3226c6 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -13,8 +13,12 @@
13#include "util.h" 13#include "util.h"
14#include "target.h" 14#include "target.h"
15 15
16#define NSECS_PER_SEC 1000000000ULL
17#define NSECS_PER_USEC 1000ULL
18
16int verbose; 19int verbose;
17bool dump_trace = false, quiet = false; 20bool dump_trace = false, quiet = false;
21int debug_ordered_events;
18 22
19static int _eprintf(int level, int var, const char *fmt, va_list args) 23static int _eprintf(int level, int var, const char *fmt, va_list args)
20{ 24{
@@ -42,6 +46,35 @@ int eprintf(int level, int var, const char *fmt, ...)
42 return ret; 46 return ret;
43} 47}
44 48
49static int __eprintf_time(u64 t, const char *fmt, va_list args)
50{
51 int ret = 0;
52 u64 secs, usecs, nsecs = t;
53
54 secs = nsecs / NSECS_PER_SEC;
55 nsecs -= secs * NSECS_PER_SEC;
56 usecs = nsecs / NSECS_PER_USEC;
57
58 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
59 secs, usecs);
60 ret += vfprintf(stderr, fmt, args);
61 return ret;
62}
63
64int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
65{
66 int ret = 0;
67 va_list args;
68
69 if (var >= level) {
70 va_start(args, fmt);
71 ret = __eprintf_time(t, fmt, args);
72 va_end(args);
73 }
74
75 return ret;
76}
77
45/* 78/*
46 * Overloading libtraceevent standard info print 79 * Overloading libtraceevent standard info print
47 * function, display with -v in perf. 80 * function, display with -v in perf.
@@ -110,7 +143,8 @@ static struct debug_variable {
110 const char *name; 143 const char *name;
111 int *ptr; 144 int *ptr;
112} debug_variables[] = { 145} debug_variables[] = {
113 { .name = "verbose", .ptr = &verbose }, 146 { .name = "verbose", .ptr = &verbose },
147 { .name = "ordered-events", .ptr = &debug_ordered_events},
114 { .name = NULL, } 148 { .name = NULL, }
115}; 149};
116 150
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 89fb6b0f7ab2..be264d6f3b30 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -3,6 +3,7 @@
3#define __PERF_DEBUG_H 3#define __PERF_DEBUG_H
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#include <string.h>
6#include "event.h" 7#include "event.h"
7#include "../ui/helpline.h" 8#include "../ui/helpline.h"
8#include "../ui/progress.h" 9#include "../ui/progress.h"
@@ -10,6 +11,7 @@
10 11
11extern int verbose; 12extern int verbose;
12extern bool quiet, dump_trace; 13extern bool quiet, dump_trace;
14extern int debug_ordered_events;
13 15
14#ifndef pr_fmt 16#ifndef pr_fmt
15#define pr_fmt(fmt) fmt 17#define pr_fmt(fmt) fmt
@@ -29,6 +31,14 @@ extern bool quiet, dump_trace;
29#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 31#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
30#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 32#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
31 33
34#define pr_time_N(n, var, t, fmt, ...) \
35 eprintf_time(n, var, t, fmt, ##__VA_ARGS__)
36
37#define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
38#define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
39
40#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
41
32int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 42int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
33void trace_event(union perf_event *event); 43void trace_event(union perf_event *event);
34 44
@@ -38,6 +48,7 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
38void pr_stat(const char *fmt, ...); 48void pr_stat(const char *fmt, ...);
39 49
40int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); 50int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
51int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
41 52
42int perf_debug_option(const char *str); 53int perf_debug_option(const char *str);
43 54
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 90d02c661dd4..0247acfdfaca 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -37,6 +37,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
37{ 37{
38 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 38 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
39 int ret = 0; 39 int ret = 0;
40 size_t len;
40 41
41 switch (type) { 42 switch (type) {
42 case DSO_BINARY_TYPE__DEBUGLINK: { 43 case DSO_BINARY_TYPE__DEBUGLINK: {
@@ -60,26 +61,25 @@ int dso__read_binary_type_filename(const struct dso *dso,
60 break; 61 break;
61 62
62 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: 63 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
63 snprintf(filename, size, "%s/usr/lib/debug%s.debug", 64 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
64 symbol_conf.symfs, dso->long_name); 65 snprintf(filename + len, size - len, "%s.debug", dso->long_name);
65 break; 66 break;
66 67
67 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: 68 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
68 snprintf(filename, size, "%s/usr/lib/debug%s", 69 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
69 symbol_conf.symfs, dso->long_name); 70 snprintf(filename + len, size - len, "%s", dso->long_name);
70 break; 71 break;
71 72
72 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: 73 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
73 { 74 {
74 const char *last_slash; 75 const char *last_slash;
75 size_t len;
76 size_t dir_size; 76 size_t dir_size;
77 77
78 last_slash = dso->long_name + dso->long_name_len; 78 last_slash = dso->long_name + dso->long_name_len;
79 while (last_slash != dso->long_name && *last_slash != '/') 79 while (last_slash != dso->long_name && *last_slash != '/')
80 last_slash--; 80 last_slash--;
81 81
82 len = scnprintf(filename, size, "%s", symbol_conf.symfs); 82 len = __symbol__join_symfs(filename, size, "");
83 dir_size = last_slash - dso->long_name + 2; 83 dir_size = last_slash - dso->long_name + 2;
84 if (dir_size > (size - len)) { 84 if (dir_size > (size - len)) {
85 ret = -1; 85 ret = -1;
@@ -100,26 +100,24 @@ int dso__read_binary_type_filename(const struct dso *dso,
100 build_id__sprintf(dso->build_id, 100 build_id__sprintf(dso->build_id,
101 sizeof(dso->build_id), 101 sizeof(dso->build_id),
102 build_id_hex); 102 build_id_hex);
103 snprintf(filename, size, 103 len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
104 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", 104 snprintf(filename + len, size - len, "%.2s/%s.debug",
105 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 105 build_id_hex, build_id_hex + 2);
106 break; 106 break;
107 107
108 case DSO_BINARY_TYPE__VMLINUX: 108 case DSO_BINARY_TYPE__VMLINUX:
109 case DSO_BINARY_TYPE__GUEST_VMLINUX: 109 case DSO_BINARY_TYPE__GUEST_VMLINUX:
110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: 110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
111 snprintf(filename, size, "%s%s", 111 __symbol__join_symfs(filename, size, dso->long_name);
112 symbol_conf.symfs, dso->long_name);
113 break; 112 break;
114 113
115 case DSO_BINARY_TYPE__GUEST_KMODULE: 114 case DSO_BINARY_TYPE__GUEST_KMODULE:
116 snprintf(filename, size, "%s%s%s", symbol_conf.symfs, 115 path__join3(filename, size, symbol_conf.symfs,
117 root_dir, dso->long_name); 116 root_dir, dso->long_name);
118 break; 117 break;
119 118
120 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 119 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
121 snprintf(filename, size, "%s%s", symbol_conf.symfs, 120 __symbol__join_symfs(filename, size, dso->long_name);
122 dso->long_name);
123 break; 121 break;
124 122
125 case DSO_BINARY_TYPE__KCORE: 123 case DSO_BINARY_TYPE__KCORE:
@@ -164,13 +162,15 @@ static void close_first_dso(void);
164static int do_open(char *name) 162static int do_open(char *name)
165{ 163{
166 int fd; 164 int fd;
165 char sbuf[STRERR_BUFSIZE];
167 166
168 do { 167 do {
169 fd = open(name, O_RDONLY); 168 fd = open(name, O_RDONLY);
170 if (fd >= 0) 169 if (fd >= 0)
171 return fd; 170 return fd;
172 171
173 pr_debug("dso open failed, mmap: %s\n", strerror(errno)); 172 pr_debug("dso open failed, mmap: %s\n",
173 strerror_r(errno, sbuf, sizeof(sbuf)));
174 if (!dso__data_open_cnt || errno != EMFILE) 174 if (!dso__data_open_cnt || errno != EMFILE)
175 break; 175 break;
176 176
@@ -532,10 +532,12 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
532static int data_file_size(struct dso *dso) 532static int data_file_size(struct dso *dso)
533{ 533{
534 struct stat st; 534 struct stat st;
535 char sbuf[STRERR_BUFSIZE];
535 536
536 if (!dso->data.file_size) { 537 if (!dso->data.file_size) {
537 if (fstat(dso->data.fd, &st)) { 538 if (fstat(dso->data.fd, &st)) {
538 pr_err("dso mmap failed, fstat: %s\n", strerror(errno)); 539 pr_err("dso mmap failed, fstat: %s\n",
540 strerror_r(errno, sbuf, sizeof(sbuf)));
539 return -1; 541 return -1;
540 } 542 }
541 dso->data.file_size = st.st_size; 543 dso->data.file_size = st.st_size;
@@ -651,6 +653,65 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
651 return dso; 653 return dso;
652} 654}
653 655
656/*
657 * Find a matching entry and/or link current entry to RB tree.
658 * Either one of the dso or name parameter must be non-NULL or the
659 * function will not work.
660 */
661static struct dso *dso__findlink_by_longname(struct rb_root *root,
662 struct dso *dso, const char *name)
663{
664 struct rb_node **p = &root->rb_node;
665 struct rb_node *parent = NULL;
666
667 if (!name)
668 name = dso->long_name;
669 /*
670 * Find node with the matching name
671 */
672 while (*p) {
673 struct dso *this = rb_entry(*p, struct dso, rb_node);
674 int rc = strcmp(name, this->long_name);
675
676 parent = *p;
677 if (rc == 0) {
678 /*
679 * In case the new DSO is a duplicate of an existing
680 * one, print an one-time warning & put the new entry
681 * at the end of the list of duplicates.
682 */
683 if (!dso || (dso == this))
684 return this; /* Find matching dso */
685 /*
686 * The core kernel DSOs may have duplicated long name.
687 * In this case, the short name should be different.
688 * Comparing the short names to differentiate the DSOs.
689 */
690 rc = strcmp(dso->short_name, this->short_name);
691 if (rc == 0) {
692 pr_err("Duplicated dso name: %s\n", name);
693 return NULL;
694 }
695 }
696 if (rc < 0)
697 p = &parent->rb_left;
698 else
699 p = &parent->rb_right;
700 }
701 if (dso) {
702 /* Add new node and rebalance tree */
703 rb_link_node(&dso->rb_node, parent, p);
704 rb_insert_color(&dso->rb_node, root);
705 }
706 return NULL;
707}
708
709static inline struct dso *
710dso__find_by_longname(const struct rb_root *root, const char *name)
711{
712 return dso__findlink_by_longname((struct rb_root *)root, NULL, name);
713}
714
654void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 715void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
655{ 716{
656 if (name == NULL) 717 if (name == NULL)
@@ -753,6 +814,7 @@ struct dso *dso__new(const char *name)
753 dso->a2l_fails = 1; 814 dso->a2l_fails = 1;
754 dso->kernel = DSO_TYPE_USER; 815 dso->kernel = DSO_TYPE_USER;
755 dso->needs_swap = DSO_SWAP__UNSET; 816 dso->needs_swap = DSO_SWAP__UNSET;
817 RB_CLEAR_NODE(&dso->rb_node);
756 INIT_LIST_HEAD(&dso->node); 818 INIT_LIST_HEAD(&dso->node);
757 INIT_LIST_HEAD(&dso->data.open_entry); 819 INIT_LIST_HEAD(&dso->data.open_entry);
758 } 820 }
@@ -763,6 +825,10 @@ struct dso *dso__new(const char *name)
763void dso__delete(struct dso *dso) 825void dso__delete(struct dso *dso)
764{ 826{
765 int i; 827 int i;
828
829 if (!RB_EMPTY_NODE(&dso->rb_node))
830 pr_err("DSO %s is still in rbtree when being deleted!\n",
831 dso->long_name);
766 for (i = 0; i < MAP__NR_TYPES; ++i) 832 for (i = 0; i < MAP__NR_TYPES; ++i)
767 symbols__delete(&dso->symbols[i]); 833 symbols__delete(&dso->symbols[i]);
768 834
@@ -849,35 +915,34 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
849 return have_build_id; 915 return have_build_id;
850} 916}
851 917
852void dsos__add(struct list_head *head, struct dso *dso) 918void dsos__add(struct dsos *dsos, struct dso *dso)
853{ 919{
854 list_add_tail(&dso->node, head); 920 list_add_tail(&dso->node, &dsos->head);
921 dso__findlink_by_longname(&dsos->root, dso, NULL);
855} 922}
856 923
857struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short) 924struct dso *dsos__find(const struct dsos *dsos, const char *name,
925 bool cmp_short)
858{ 926{
859 struct dso *pos; 927 struct dso *pos;
860 928
861 if (cmp_short) { 929 if (cmp_short) {
862 list_for_each_entry(pos, head, node) 930 list_for_each_entry(pos, &dsos->head, node)
863 if (strcmp(pos->short_name, name) == 0) 931 if (strcmp(pos->short_name, name) == 0)
864 return pos; 932 return pos;
865 return NULL; 933 return NULL;
866 } 934 }
867 list_for_each_entry(pos, head, node) 935 return dso__find_by_longname(&dsos->root, name);
868 if (strcmp(pos->long_name, name) == 0)
869 return pos;
870 return NULL;
871} 936}
872 937
873struct dso *__dsos__findnew(struct list_head *head, const char *name) 938struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
874{ 939{
875 struct dso *dso = dsos__find(head, name, false); 940 struct dso *dso = dsos__find(dsos, name, false);
876 941
877 if (!dso) { 942 if (!dso) {
878 dso = dso__new(name); 943 dso = dso__new(name);
879 if (dso != NULL) { 944 if (dso != NULL) {
880 dsos__add(head, dso); 945 dsos__add(dsos, dso);
881 dso__set_basename(dso); 946 dso__set_basename(dso);
882 } 947 }
883 } 948 }
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 5e463c0964d4..acb651acc7fd 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -90,8 +90,18 @@ struct dso_cache {
90 char data[0]; 90 char data[0];
91}; 91};
92 92
93/*
94 * DSOs are put into both a list for fast iteration and rbtree for fast
95 * long name lookup.
96 */
97struct dsos {
98 struct list_head head;
99 struct rb_root root; /* rbtree root sorted by long name */
100};
101
93struct dso { 102struct dso {
94 struct list_head node; 103 struct list_head node;
104 struct rb_node rb_node; /* rbtree node sorted by long name */
95 struct rb_root symbols[MAP__NR_TYPES]; 105 struct rb_root symbols[MAP__NR_TYPES];
96 struct rb_root symbol_names[MAP__NR_TYPES]; 106 struct rb_root symbol_names[MAP__NR_TYPES];
97 void *a2l; 107 void *a2l;
@@ -224,10 +234,10 @@ struct map *dso__new_map(const char *name);
224struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 234struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
225 const char *short_name, int dso_type); 235 const char *short_name, int dso_type);
226 236
227void dsos__add(struct list_head *head, struct dso *dso); 237void dsos__add(struct dsos *dsos, struct dso *dso);
228struct dso *dsos__find(const struct list_head *head, const char *name, 238struct dso *dsos__find(const struct dsos *dsos, const char *name,
229 bool cmp_short); 239 bool cmp_short);
230struct dso *__dsos__findnew(struct list_head *head, const char *name); 240struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
231bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 241bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
232 242
233size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 243size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 1398c83d896d..4af6b279e34a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -558,13 +558,17 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
558 struct map *map; 558 struct map *map;
559 struct kmap *kmap; 559 struct kmap *kmap;
560 int err; 560 int err;
561 union perf_event *event;
562
563 if (machine->vmlinux_maps[0] == NULL)
564 return -1;
565
561 /* 566 /*
562 * We should get this from /sys/kernel/sections/.text, but till that is 567 * We should get this from /sys/kernel/sections/.text, but till that is
563 * available use this, and after it is use this as a fallback for older 568 * available use this, and after it is use this as a fallback for older
564 * kernels. 569 * kernels.
565 */ 570 */
566 union perf_event *event = zalloc((sizeof(event->mmap) + 571 event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
567 machine->id_hdr_size));
568 if (event == NULL) { 572 if (event == NULL) {
569 pr_debug("Not enough memory synthesizing mmap event " 573 pr_debug("Not enough memory synthesizing mmap event "
570 "for kernel modules\n"); 574 "for kernel modules\n");
@@ -784,9 +788,9 @@ try_again:
784 * "[vdso]" dso, but for now lets use the old trick of looking 788 * "[vdso]" dso, but for now lets use the old trick of looking
785 * in the whole kernel symbol list. 789 * in the whole kernel symbol list.
786 */ 790 */
787 if ((long long)al->addr < 0 && 791 if (cpumode == PERF_RECORD_MISC_USER && machine &&
788 cpumode == PERF_RECORD_MISC_USER && 792 mg != &machine->kmaps &&
789 machine && mg != &machine->kmaps) { 793 machine__kernel_ip(machine, al->addr)) {
790 mg = &machine->kmaps; 794 mg = &machine->kmaps;
791 load_map = true; 795 load_map = true;
792 goto try_again; 796 goto try_again;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 94d6976180da..7eb7107731ec 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -156,6 +156,8 @@ struct perf_sample {
156 u32 cpu; 156 u32 cpu;
157 u32 raw_size; 157 u32 raw_size;
158 u64 data_src; 158 u64 data_src;
159 u32 flags;
160 u16 insn_len;
159 void *raw_data; 161 void *raw_data;
160 struct ip_callchain *callchain; 162 struct ip_callchain *callchain;
161 struct branch_stack *branch_stack; 163 struct branch_stack *branch_stack;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 814e954c1318..3cebc9a8d52e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,9 @@
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/hash.h> 26#include <linux/hash.h>
27 27
28static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
29static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
30
28#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 31#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
29#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 32#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
30 33
@@ -37,6 +40,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
37 INIT_HLIST_HEAD(&evlist->heads[i]); 40 INIT_HLIST_HEAD(&evlist->heads[i]);
38 INIT_LIST_HEAD(&evlist->entries); 41 INIT_LIST_HEAD(&evlist->entries);
39 perf_evlist__set_maps(evlist, cpus, threads); 42 perf_evlist__set_maps(evlist, cpus, threads);
43 fdarray__init(&evlist->pollfd, 64);
40 evlist->workload.pid = -1; 44 evlist->workload.pid = -1;
41} 45}
42 46
@@ -102,7 +106,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
102void perf_evlist__exit(struct perf_evlist *evlist) 106void perf_evlist__exit(struct perf_evlist *evlist)
103{ 107{
104 zfree(&evlist->mmap); 108 zfree(&evlist->mmap);
105 zfree(&evlist->pollfd); 109 fdarray__exit(&evlist->pollfd);
106} 110}
107 111
108void perf_evlist__delete(struct perf_evlist *evlist) 112void perf_evlist__delete(struct perf_evlist *evlist)
@@ -122,6 +126,7 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
122{ 126{
123 list_add_tail(&entry->node, &evlist->entries); 127 list_add_tail(&entry->node, &evlist->entries);
124 entry->idx = evlist->nr_entries; 128 entry->idx = evlist->nr_entries;
129 entry->tracking = !entry->idx;
125 130
126 if (!evlist->nr_entries++) 131 if (!evlist->nr_entries++)
127 perf_evlist__set_id_pos(evlist); 132 perf_evlist__set_id_pos(evlist);
@@ -265,17 +270,27 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
265 return 0; 270 return 0;
266} 271}
267 272
273static int perf_evlist__nr_threads(struct perf_evlist *evlist,
274 struct perf_evsel *evsel)
275{
276 if (evsel->system_wide)
277 return 1;
278 else
279 return thread_map__nr(evlist->threads);
280}
281
268void perf_evlist__disable(struct perf_evlist *evlist) 282void perf_evlist__disable(struct perf_evlist *evlist)
269{ 283{
270 int cpu, thread; 284 int cpu, thread;
271 struct perf_evsel *pos; 285 struct perf_evsel *pos;
272 int nr_cpus = cpu_map__nr(evlist->cpus); 286 int nr_cpus = cpu_map__nr(evlist->cpus);
273 int nr_threads = thread_map__nr(evlist->threads); 287 int nr_threads;
274 288
275 for (cpu = 0; cpu < nr_cpus; cpu++) { 289 for (cpu = 0; cpu < nr_cpus; cpu++) {
276 evlist__for_each(evlist, pos) { 290 evlist__for_each(evlist, pos) {
277 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 291 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
278 continue; 292 continue;
293 nr_threads = perf_evlist__nr_threads(evlist, pos);
279 for (thread = 0; thread < nr_threads; thread++) 294 for (thread = 0; thread < nr_threads; thread++)
280 ioctl(FD(pos, cpu, thread), 295 ioctl(FD(pos, cpu, thread),
281 PERF_EVENT_IOC_DISABLE, 0); 296 PERF_EVENT_IOC_DISABLE, 0);
@@ -288,12 +303,13 @@ void perf_evlist__enable(struct perf_evlist *evlist)
288 int cpu, thread; 303 int cpu, thread;
289 struct perf_evsel *pos; 304 struct perf_evsel *pos;
290 int nr_cpus = cpu_map__nr(evlist->cpus); 305 int nr_cpus = cpu_map__nr(evlist->cpus);
291 int nr_threads = thread_map__nr(evlist->threads); 306 int nr_threads;
292 307
293 for (cpu = 0; cpu < nr_cpus; cpu++) { 308 for (cpu = 0; cpu < nr_cpus; cpu++) {
294 evlist__for_each(evlist, pos) { 309 evlist__for_each(evlist, pos) {
295 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 310 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
296 continue; 311 continue;
312 nr_threads = perf_evlist__nr_threads(evlist, pos);
297 for (thread = 0; thread < nr_threads; thread++) 313 for (thread = 0; thread < nr_threads; thread++)
298 ioctl(FD(pos, cpu, thread), 314 ioctl(FD(pos, cpu, thread),
299 PERF_EVENT_IOC_ENABLE, 0); 315 PERF_EVENT_IOC_ENABLE, 0);
@@ -305,12 +321,14 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
305 struct perf_evsel *evsel) 321 struct perf_evsel *evsel)
306{ 322{
307 int cpu, thread, err; 323 int cpu, thread, err;
324 int nr_cpus = cpu_map__nr(evlist->cpus);
325 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
308 326
309 if (!evsel->fd) 327 if (!evsel->fd)
310 return 0; 328 return 0;
311 329
312 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 330 for (cpu = 0; cpu < nr_cpus; cpu++) {
313 for (thread = 0; thread < evlist->threads->nr; thread++) { 331 for (thread = 0; thread < nr_threads; thread++) {
314 err = ioctl(FD(evsel, cpu, thread), 332 err = ioctl(FD(evsel, cpu, thread),
315 PERF_EVENT_IOC_DISABLE, 0); 333 PERF_EVENT_IOC_DISABLE, 0);
316 if (err) 334 if (err)
@@ -324,12 +342,14 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
324 struct perf_evsel *evsel) 342 struct perf_evsel *evsel)
325{ 343{
326 int cpu, thread, err; 344 int cpu, thread, err;
345 int nr_cpus = cpu_map__nr(evlist->cpus);
346 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
327 347
328 if (!evsel->fd) 348 if (!evsel->fd)
329 return -EINVAL; 349 return -EINVAL;
330 350
331 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 351 for (cpu = 0; cpu < nr_cpus; cpu++) {
332 for (thread = 0; thread < evlist->threads->nr; thread++) { 352 for (thread = 0; thread < nr_threads; thread++) {
333 err = ioctl(FD(evsel, cpu, thread), 353 err = ioctl(FD(evsel, cpu, thread),
334 PERF_EVENT_IOC_ENABLE, 0); 354 PERF_EVENT_IOC_ENABLE, 0);
335 if (err) 355 if (err)
@@ -339,21 +359,111 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
339 return 0; 359 return 0;
340} 360}
341 361
342static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 362static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
363 struct perf_evsel *evsel, int cpu)
364{
365 int thread, err;
366 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
367
368 if (!evsel->fd)
369 return -EINVAL;
370
371 for (thread = 0; thread < nr_threads; thread++) {
372 err = ioctl(FD(evsel, cpu, thread),
373 PERF_EVENT_IOC_ENABLE, 0);
374 if (err)
375 return err;
376 }
377 return 0;
378}
379
380static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
381 struct perf_evsel *evsel,
382 int thread)
383{
384 int cpu, err;
385 int nr_cpus = cpu_map__nr(evlist->cpus);
386
387 if (!evsel->fd)
388 return -EINVAL;
389
390 for (cpu = 0; cpu < nr_cpus; cpu++) {
391 err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
392 if (err)
393 return err;
394 }
395 return 0;
396}
397
398int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
399 struct perf_evsel *evsel, int idx)
400{
401 bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
402
403 if (per_cpu_mmaps)
404 return perf_evlist__enable_event_cpu(evlist, evsel, idx);
405 else
406 return perf_evlist__enable_event_thread(evlist, evsel, idx);
407}
408
409int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
343{ 410{
344 int nr_cpus = cpu_map__nr(evlist->cpus); 411 int nr_cpus = cpu_map__nr(evlist->cpus);
345 int nr_threads = thread_map__nr(evlist->threads); 412 int nr_threads = thread_map__nr(evlist->threads);
346 int nfds = nr_cpus * nr_threads * evlist->nr_entries; 413 int nfds = 0;
347 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 414 struct perf_evsel *evsel;
348 return evlist->pollfd != NULL ? 0 : -ENOMEM; 415
416 list_for_each_entry(evsel, &evlist->entries, node) {
417 if (evsel->system_wide)
418 nfds += nr_cpus;
419 else
420 nfds += nr_cpus * nr_threads;
421 }
422
423 if (fdarray__available_entries(&evlist->pollfd) < nfds &&
424 fdarray__grow(&evlist->pollfd, nfds) < 0)
425 return -ENOMEM;
426
427 return 0;
428}
429
430static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx)
431{
432 int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
433 /*
434 * Save the idx so that when we filter out fds POLLHUP'ed we can
435 * close the associated evlist->mmap[] entry.
436 */
437 if (pos >= 0) {
438 evlist->pollfd.priv[pos].idx = idx;
439
440 fcntl(fd, F_SETFL, O_NONBLOCK);
441 }
442
443 return pos;
444}
445
446int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
447{
448 return __perf_evlist__add_pollfd(evlist, fd, -1);
449}
450
451static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
452{
453 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd);
454
455 perf_evlist__mmap_put(evlist, fda->priv[fd].idx);
456}
457
458int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
459{
460 return fdarray__filter(&evlist->pollfd, revents_and_mask,
461 perf_evlist__munmap_filtered);
349} 462}
350 463
351void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 464int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
352{ 465{
353 fcntl(fd, F_SETFL, O_NONBLOCK); 466 return fdarray__poll(&evlist->pollfd, timeout);
354 evlist->pollfd[evlist->nr_fds].fd = fd;
355 evlist->pollfd[evlist->nr_fds].events = POLLIN;
356 evlist->nr_fds++;
357} 467}
358 468
359static void perf_evlist__id_hash(struct perf_evlist *evlist, 469static void perf_evlist__id_hash(struct perf_evlist *evlist,
@@ -566,14 +676,36 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
566 return event; 676 return event;
567} 677}
568 678
679static bool perf_mmap__empty(struct perf_mmap *md)
680{
681 return perf_mmap__read_head(md) != md->prev;
682}
683
684static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
685{
686 ++evlist->mmap[idx].refcnt;
687}
688
689static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
690{
691 BUG_ON(evlist->mmap[idx].refcnt == 0);
692
693 if (--evlist->mmap[idx].refcnt == 0)
694 __perf_evlist__munmap(evlist, idx);
695}
696
569void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 697void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
570{ 698{
699 struct perf_mmap *md = &evlist->mmap[idx];
700
571 if (!evlist->overwrite) { 701 if (!evlist->overwrite) {
572 struct perf_mmap *md = &evlist->mmap[idx];
573 unsigned int old = md->prev; 702 unsigned int old = md->prev;
574 703
575 perf_mmap__write_tail(md, old); 704 perf_mmap__write_tail(md, old);
576 } 705 }
706
707 if (md->refcnt == 1 && perf_mmap__empty(md))
708 perf_evlist__mmap_put(evlist, idx);
577} 709}
578 710
579static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 711static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
@@ -581,6 +713,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
581 if (evlist->mmap[idx].base != NULL) { 713 if (evlist->mmap[idx].base != NULL) {
582 munmap(evlist->mmap[idx].base, evlist->mmap_len); 714 munmap(evlist->mmap[idx].base, evlist->mmap_len);
583 evlist->mmap[idx].base = NULL; 715 evlist->mmap[idx].base = NULL;
716 evlist->mmap[idx].refcnt = 0;
584 } 717 }
585} 718}
586 719
@@ -614,6 +747,20 @@ struct mmap_params {
614static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 747static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
615 struct mmap_params *mp, int fd) 748 struct mmap_params *mp, int fd)
616{ 749{
750 /*
751 * The last one will be done at perf_evlist__mmap_consume(), so that we
752 * make sure we don't prevent tools from consuming every last event in
753 * the ring buffer.
754 *
755 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
756 * anymore, but the last events for it are still in the ring buffer,
757 * waiting to be consumed.
758 *
759 * Tools can chose to ignore this at their own discretion, but the
760 * evlist layer can't just drop it when filtering events in
761 * perf_evlist__filter_pollfd().
762 */
763 evlist->mmap[idx].refcnt = 2;
617 evlist->mmap[idx].prev = 0; 764 evlist->mmap[idx].prev = 0;
618 evlist->mmap[idx].mask = mp->mask; 765 evlist->mmap[idx].mask = mp->mask;
619 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 766 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
@@ -625,7 +772,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
625 return -1; 772 return -1;
626 } 773 }
627 774
628 perf_evlist__add_pollfd(evlist, fd);
629 return 0; 775 return 0;
630} 776}
631 777
@@ -636,7 +782,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
636 struct perf_evsel *evsel; 782 struct perf_evsel *evsel;
637 783
638 evlist__for_each(evlist, evsel) { 784 evlist__for_each(evlist, evsel) {
639 int fd = FD(evsel, cpu, thread); 785 int fd;
786
787 if (evsel->system_wide && thread)
788 continue;
789
790 fd = FD(evsel, cpu, thread);
640 791
641 if (*output == -1) { 792 if (*output == -1) {
642 *output = fd; 793 *output = fd;
@@ -645,6 +796,13 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
645 } else { 796 } else {
646 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 797 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
647 return -1; 798 return -1;
799
800 perf_evlist__mmap_get(evlist, idx);
801 }
802
803 if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
804 perf_evlist__mmap_put(evlist, idx);
805 return -1;
648 } 806 }
649 807
650 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 808 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -804,7 +962,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
804 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 962 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
805 return -ENOMEM; 963 return -ENOMEM;
806 964
807 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 965 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
808 return -ENOMEM; 966 return -ENOMEM;
809 967
810 evlist->overwrite = overwrite; 968 evlist->overwrite = overwrite;
@@ -1061,6 +1219,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1061 } 1219 }
1062 1220
1063 if (!evlist->workload.pid) { 1221 if (!evlist->workload.pid) {
1222 int ret;
1223
1064 if (pipe_output) 1224 if (pipe_output)
1065 dup2(2, 1); 1225 dup2(2, 1);
1066 1226
@@ -1078,8 +1238,22 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1078 /* 1238 /*
1079 * Wait until the parent tells us to go. 1239 * Wait until the parent tells us to go.
1080 */ 1240 */
1081 if (read(go_pipe[0], &bf, 1) == -1) 1241 ret = read(go_pipe[0], &bf, 1);
1082 perror("unable to read pipe"); 1242 /*
1243 * The parent will ask for the execvp() to be performed by
1244 * writing exactly one byte, in workload.cork_fd, usually via
1245 * perf_evlist__start_workload().
1246 *
1247 * For cancelling the workload without actuallin running it,
1248 * the parent will just close workload.cork_fd, without writing
1249 * anything, i.e. read will return zero and we just exit()
1250 * here.
1251 */
1252 if (ret != 1) {
1253 if (ret == -1)
1254 perror("unable to read pipe");
1255 exit(ret);
1256 }
1083 1257
1084 execvp(argv[0], (char **)argv); 1258 execvp(argv[0], (char **)argv);
1085 1259
@@ -1202,7 +1376,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1202 int err, char *buf, size_t size) 1376 int err, char *buf, size_t size)
1203{ 1377{
1204 int printed, value; 1378 int printed, value;
1205 char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1379 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1206 1380
1207 switch (err) { 1381 switch (err) {
1208 case EACCES: 1382 case EACCES:
@@ -1250,3 +1424,19 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
1250 1424
1251 list_splice(&move, &evlist->entries); 1425 list_splice(&move, &evlist->entries);
1252} 1426}
1427
1428void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
1429 struct perf_evsel *tracking_evsel)
1430{
1431 struct perf_evsel *evsel;
1432
1433 if (tracking_evsel->tracking)
1434 return;
1435
1436 evlist__for_each(evlist, evsel) {
1437 if (evsel != tracking_evsel)
1438 evsel->tracking = false;
1439 }
1440
1441 tracking_evsel->tracking = true;
1442}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index f5173cd63693..bd312b01e876 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,6 +2,7 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <api/fd/array.h>
5#include <stdio.h> 6#include <stdio.h>
6#include "../perf.h" 7#include "../perf.h"
7#include "event.h" 8#include "event.h"
@@ -17,9 +18,15 @@ struct record_opts;
17#define PERF_EVLIST__HLIST_BITS 8 18#define PERF_EVLIST__HLIST_BITS 8
18#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 19#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
19 20
21/**
22 * struct perf_mmap - perf's ring buffer mmap details
23 *
24 * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
25 */
20struct perf_mmap { 26struct perf_mmap {
21 void *base; 27 void *base;
22 int mask; 28 int mask;
29 int refcnt;
23 unsigned int prev; 30 unsigned int prev;
24 char event_copy[PERF_SAMPLE_MAX_SIZE]; 31 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 32};
@@ -29,7 +36,6 @@ struct perf_evlist {
29 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 36 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
30 int nr_entries; 37 int nr_entries;
31 int nr_groups; 38 int nr_groups;
32 int nr_fds;
33 int nr_mmaps; 39 int nr_mmaps;
34 size_t mmap_len; 40 size_t mmap_len;
35 int id_pos; 41 int id_pos;
@@ -40,8 +46,8 @@ struct perf_evlist {
40 pid_t pid; 46 pid_t pid;
41 } workload; 47 } workload;
42 bool overwrite; 48 bool overwrite;
49 struct fdarray pollfd;
43 struct perf_mmap *mmap; 50 struct perf_mmap *mmap;
44 struct pollfd *pollfd;
45 struct thread_map *threads; 51 struct thread_map *threads;
46 struct cpu_map *cpus; 52 struct cpu_map *cpus;
47 struct perf_evsel *selected; 53 struct perf_evsel *selected;
@@ -82,7 +88,11 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
82void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 88void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
83 int cpu, int thread, u64 id); 89 int cpu, int thread, u64 id);
84 90
85void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 91int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
92int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
93int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
94
95int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
86 96
87struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 97struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
88 98
@@ -122,6 +132,8 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
122 struct perf_evsel *evsel); 132 struct perf_evsel *evsel);
123int perf_evlist__enable_event(struct perf_evlist *evlist, 133int perf_evlist__enable_event(struct perf_evlist *evlist,
124 struct perf_evsel *evsel); 134 struct perf_evsel *evsel);
135int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
136 struct perf_evsel *evsel, int idx);
125 137
126void perf_evlist__set_selected(struct perf_evlist *evlist, 138void perf_evlist__set_selected(struct perf_evlist *evlist,
127 struct perf_evsel *evsel); 139 struct perf_evsel *evsel);
@@ -262,4 +274,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
262#define evlist__for_each_safe(evlist, tmp, evsel) \ 274#define evlist__for_each_safe(evlist, tmp, evsel) \
263 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) 275 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
264 276
277void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
278 struct perf_evsel *tracking_evsel);
279
265#endif /* __PERF_EVLIST_H */ 280#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21a373ebea22..e0868a901c4a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -162,6 +162,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
162 struct perf_event_attr *attr, int idx) 162 struct perf_event_attr *attr, int idx)
163{ 163{
164 evsel->idx = idx; 164 evsel->idx = idx;
165 evsel->tracking = !idx;
165 evsel->attr = *attr; 166 evsel->attr = *attr;
166 evsel->leader = evsel; 167 evsel->leader = evsel;
167 evsel->unit = ""; 168 evsel->unit = "";
@@ -502,20 +503,19 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
502} 503}
503 504
504static void 505static void
505perf_evsel__config_callgraph(struct perf_evsel *evsel, 506perf_evsel__config_callgraph(struct perf_evsel *evsel)
506 struct record_opts *opts)
507{ 507{
508 bool function = perf_evsel__is_function_event(evsel); 508 bool function = perf_evsel__is_function_event(evsel);
509 struct perf_event_attr *attr = &evsel->attr; 509 struct perf_event_attr *attr = &evsel->attr;
510 510
511 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 511 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
512 512
513 if (opts->call_graph == CALLCHAIN_DWARF) { 513 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
514 if (!function) { 514 if (!function) {
515 perf_evsel__set_sample_bit(evsel, REGS_USER); 515 perf_evsel__set_sample_bit(evsel, REGS_USER);
516 perf_evsel__set_sample_bit(evsel, STACK_USER); 516 perf_evsel__set_sample_bit(evsel, STACK_USER);
517 attr->sample_regs_user = PERF_REGS_MASK; 517 attr->sample_regs_user = PERF_REGS_MASK;
518 attr->sample_stack_user = opts->stack_dump_size; 518 attr->sample_stack_user = callchain_param.dump_size;
519 attr->exclude_callchain_user = 1; 519 attr->exclude_callchain_user = 1;
520 } else { 520 } else {
521 pr_info("Cannot use DWARF unwind for function trace event," 521 pr_info("Cannot use DWARF unwind for function trace event,"
@@ -561,7 +561,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
561{ 561{
562 struct perf_evsel *leader = evsel->leader; 562 struct perf_evsel *leader = evsel->leader;
563 struct perf_event_attr *attr = &evsel->attr; 563 struct perf_event_attr *attr = &evsel->attr;
564 int track = !evsel->idx; /* only the first counter needs these */ 564 int track = evsel->tracking;
565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; 565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
566 566
567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
@@ -624,8 +624,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
624 attr->mmap_data = track; 624 attr->mmap_data = track;
625 } 625 }
626 626
627 if (opts->call_graph_enabled && !evsel->no_aux_samples) 627 if (callchain_param.enabled && !evsel->no_aux_samples)
628 perf_evsel__config_callgraph(evsel, opts); 628 perf_evsel__config_callgraph(evsel);
629 629
630 if (target__has_cpu(&opts->target)) 630 if (target__has_cpu(&opts->target))
631 perf_evsel__set_sample_bit(evsel, CPU); 631 perf_evsel__set_sample_bit(evsel, CPU);
@@ -633,9 +633,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
633 if (opts->period) 633 if (opts->period)
634 perf_evsel__set_sample_bit(evsel, PERIOD); 634 perf_evsel__set_sample_bit(evsel, PERIOD);
635 635
636 if (!perf_missing_features.sample_id_all && 636 /*
637 (opts->sample_time || !opts->no_inherit || 637 * When the user explicitely disabled time don't force it here.
638 target__has_cpu(&opts->target) || per_cpu)) 638 */
639 if (opts->sample_time &&
640 (!perf_missing_features.sample_id_all &&
641 (!opts->no_inherit || target__has_cpu(&opts->target) || per_cpu)))
639 perf_evsel__set_sample_bit(evsel, TIME); 642 perf_evsel__set_sample_bit(evsel, TIME);
640 643
641 if (opts->raw_samples && !evsel->no_aux_samples) { 644 if (opts->raw_samples && !evsel->no_aux_samples) {
@@ -692,6 +695,10 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
692int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 695int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
693{ 696{
694 int cpu, thread; 697 int cpu, thread;
698
699 if (evsel->system_wide)
700 nthreads = 1;
701
695 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 702 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
696 703
697 if (evsel->fd) { 704 if (evsel->fd) {
@@ -710,6 +717,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea
710{ 717{
711 int cpu, thread; 718 int cpu, thread;
712 719
720 if (evsel->system_wide)
721 nthreads = 1;
722
713 for (cpu = 0; cpu < ncpus; cpu++) { 723 for (cpu = 0; cpu < ncpus; cpu++) {
714 for (thread = 0; thread < nthreads; thread++) { 724 for (thread = 0; thread < nthreads; thread++) {
715 int fd = FD(evsel, cpu, thread), 725 int fd = FD(evsel, cpu, thread),
@@ -740,6 +750,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
740 750
741int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 751int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
742{ 752{
753 if (evsel->system_wide)
754 nthreads = 1;
755
743 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 756 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
744 if (evsel->sample_id == NULL) 757 if (evsel->sample_id == NULL)
745 return -ENOMEM; 758 return -ENOMEM;
@@ -784,6 +797,9 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
784{ 797{
785 int cpu, thread; 798 int cpu, thread;
786 799
800 if (evsel->system_wide)
801 nthreads = 1;
802
787 for (cpu = 0; cpu < ncpus; cpu++) 803 for (cpu = 0; cpu < ncpus; cpu++)
788 for (thread = 0; thread < nthreads; ++thread) { 804 for (thread = 0; thread < nthreads; ++thread) {
789 close(FD(evsel, cpu, thread)); 805 close(FD(evsel, cpu, thread));
@@ -872,6 +888,9 @@ int __perf_evsel__read(struct perf_evsel *evsel,
872 int cpu, thread; 888 int cpu, thread;
873 struct perf_counts_values *aggr = &evsel->counts->aggr, count; 889 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
874 890
891 if (evsel->system_wide)
892 nthreads = 1;
893
875 aggr->val = aggr->ena = aggr->run = 0; 894 aggr->val = aggr->ena = aggr->run = 0;
876 895
877 for (cpu = 0; cpu < ncpus; cpu++) { 896 for (cpu = 0; cpu < ncpus; cpu++) {
@@ -994,13 +1013,18 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
994static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1013static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
995 struct thread_map *threads) 1014 struct thread_map *threads)
996{ 1015{
997 int cpu, thread; 1016 int cpu, thread, nthreads;
998 unsigned long flags = PERF_FLAG_FD_CLOEXEC; 1017 unsigned long flags = PERF_FLAG_FD_CLOEXEC;
999 int pid = -1, err; 1018 int pid = -1, err;
1000 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1019 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1001 1020
1021 if (evsel->system_wide)
1022 nthreads = 1;
1023 else
1024 nthreads = threads->nr;
1025
1002 if (evsel->fd == NULL && 1026 if (evsel->fd == NULL &&
1003 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 1027 perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
1004 return -ENOMEM; 1028 return -ENOMEM;
1005 1029
1006 if (evsel->cgrp) { 1030 if (evsel->cgrp) {
@@ -1024,10 +1048,10 @@ retry_sample_id:
1024 1048
1025 for (cpu = 0; cpu < cpus->nr; cpu++) { 1049 for (cpu = 0; cpu < cpus->nr; cpu++) {
1026 1050
1027 for (thread = 0; thread < threads->nr; thread++) { 1051 for (thread = 0; thread < nthreads; thread++) {
1028 int group_fd; 1052 int group_fd;
1029 1053
1030 if (!evsel->cgrp) 1054 if (!evsel->cgrp && !evsel->system_wide)
1031 pid = threads->map[thread]; 1055 pid = threads->map[thread];
1032 1056
1033 group_fd = get_group_fd(evsel, cpu, thread); 1057 group_fd = get_group_fd(evsel, cpu, thread);
@@ -1100,7 +1124,7 @@ out_close:
1100 close(FD(evsel, cpu, thread)); 1124 close(FD(evsel, cpu, thread));
1101 FD(evsel, cpu, thread) = -1; 1125 FD(evsel, cpu, thread) = -1;
1102 } 1126 }
1103 thread = threads->nr; 1127 thread = nthreads;
1104 } while (--cpu >= 0); 1128 } while (--cpu >= 0);
1105 return err; 1129 return err;
1106} 1130}
@@ -2002,6 +2026,8 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2002int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 2026int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2003 int err, char *msg, size_t size) 2027 int err, char *msg, size_t size)
2004{ 2028{
2029 char sbuf[STRERR_BUFSIZE];
2030
2005 switch (err) { 2031 switch (err) {
2006 case EPERM: 2032 case EPERM:
2007 case EACCES: 2033 case EACCES:
@@ -2036,13 +2062,20 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2036 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); 2062 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
2037#endif 2063#endif
2038 break; 2064 break;
2065 case EBUSY:
2066 if (find_process("oprofiled"))
2067 return scnprintf(msg, size,
2068 "The PMU counters are busy/taken by another profiler.\n"
2069 "We found oprofile daemon running, please stop it and try again.");
2070 break;
2039 default: 2071 default:
2040 break; 2072 break;
2041 } 2073 }
2042 2074
2043 return scnprintf(msg, size, 2075 return scnprintf(msg, size,
2044 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" 2076 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2045 "/bin/dmesg may provide additional information.\n" 2077 "/bin/dmesg may provide additional information.\n"
2046 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2078 "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
2047 err, strerror(err), perf_evsel__name(evsel)); 2079 err, strerror_r(err, sbuf, sizeof(sbuf)),
2080 perf_evsel__name(evsel));
2048} 2081}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d7f93ce0ebc1..7bc314be6a7b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -85,6 +85,8 @@ struct perf_evsel {
85 bool needs_swap; 85 bool needs_swap;
86 bool no_aux_samples; 86 bool no_aux_samples;
87 bool immediate; 87 bool immediate;
88 bool system_wide;
89 bool tracking;
88 /* parse modifier helper */ 90 /* parse modifier helper */
89 int exclude_GH; 91 int exclude_GH;
90 int nr_members; 92 int nr_members;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 158c787ce0c4..ce0de00399da 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -214,11 +214,11 @@ static int machine__hit_all_dsos(struct machine *machine)
214{ 214{
215 int err; 215 int err;
216 216
217 err = __dsos__hit_all(&machine->kernel_dsos); 217 err = __dsos__hit_all(&machine->kernel_dsos.head);
218 if (err) 218 if (err)
219 return err; 219 return err;
220 220
221 return __dsos__hit_all(&machine->user_dsos); 221 return __dsos__hit_all(&machine->user_dsos.head);
222} 222}
223 223
224int dsos__hit_all(struct perf_session *session) 224int dsos__hit_all(struct perf_session *session)
@@ -288,11 +288,12 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
288 umisc = PERF_RECORD_MISC_GUEST_USER; 288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 } 289 }
290 290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine, 291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
292 machine->pid, kmisc, fd); 292 machine->pid, kmisc, fd);
293 if (err == 0) 293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos, machine, 294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine->pid, umisc, fd); 295 machine, machine->pid, umisc,
296 fd);
296 return err; 297 return err;
297} 298}
298 299
@@ -455,9 +456,10 @@ static int __dsos__cache_build_ids(struct list_head *head,
455 456
456static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
457{ 458{
458 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine, 459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
459 debugdir); 460 debugdir);
460 ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir); 461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
461 return ret; 463 return ret;
462} 464}
463 465
@@ -483,8 +485,10 @@ static int perf_session__cache_build_ids(struct perf_session *session)
483 485
484static bool machine__read_build_ids(struct machine *machine, bool with_hits) 486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
485{ 487{
486 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits); 488 bool ret;
487 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits); 489
490 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
491 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
488 return ret; 492 return ret;
489} 493}
490 494
@@ -1548,7 +1552,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1548 struct perf_session *session) 1552 struct perf_session *session)
1549{ 1553{
1550 int err = -1; 1554 int err = -1;
1551 struct list_head *head; 1555 struct dsos *dsos;
1552 struct machine *machine; 1556 struct machine *machine;
1553 u16 misc; 1557 u16 misc;
1554 struct dso *dso; 1558 struct dso *dso;
@@ -1563,22 +1567,22 @@ static int __event_process_build_id(struct build_id_event *bev,
1563 switch (misc) { 1567 switch (misc) {
1564 case PERF_RECORD_MISC_KERNEL: 1568 case PERF_RECORD_MISC_KERNEL:
1565 dso_type = DSO_TYPE_KERNEL; 1569 dso_type = DSO_TYPE_KERNEL;
1566 head = &machine->kernel_dsos; 1570 dsos = &machine->kernel_dsos;
1567 break; 1571 break;
1568 case PERF_RECORD_MISC_GUEST_KERNEL: 1572 case PERF_RECORD_MISC_GUEST_KERNEL:
1569 dso_type = DSO_TYPE_GUEST_KERNEL; 1573 dso_type = DSO_TYPE_GUEST_KERNEL;
1570 head = &machine->kernel_dsos; 1574 dsos = &machine->kernel_dsos;
1571 break; 1575 break;
1572 case PERF_RECORD_MISC_USER: 1576 case PERF_RECORD_MISC_USER:
1573 case PERF_RECORD_MISC_GUEST_USER: 1577 case PERF_RECORD_MISC_GUEST_USER:
1574 dso_type = DSO_TYPE_USER; 1578 dso_type = DSO_TYPE_USER;
1575 head = &machine->user_dsos; 1579 dsos = &machine->user_dsos;
1576 break; 1580 break;
1577 default: 1581 default:
1578 goto out; 1582 goto out;
1579 } 1583 }
1580 1584
1581 dso = __dsos__findnew(head, filename); 1585 dso = __dsos__findnew(dsos, filename);
1582 if (dso != NULL) { 1586 if (dso != NULL) {
1583 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1587 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1584 1588
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 30df6187ee02..86569fa3651d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -277,6 +277,28 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
277 } 277 }
278} 278}
279 279
280void hists__delete_entries(struct hists *hists)
281{
282 struct rb_node *next = rb_first(&hists->entries);
283 struct hist_entry *n;
284
285 while (next) {
286 n = rb_entry(next, struct hist_entry, rb_node);
287 next = rb_next(&n->rb_node);
288
289 rb_erase(&n->rb_node, &hists->entries);
290
291 if (sort__need_collapse)
292 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
293
294 --hists->nr_entries;
295 if (!n->filtered)
296 --hists->nr_non_filtered_entries;
297
298 hist_entry__free(n);
299 }
300}
301
280/* 302/*
281 * histogram, sorted on item, collects periods 303 * histogram, sorted on item, collects periods
282 */ 304 */
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 742f49a85725..8c9c70e18cbb 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -152,6 +152,7 @@ void hists__output_resort(struct hists *hists);
152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
153 153
154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
155void hists__delete_entries(struct hists *hists);
155void hists__output_recalc_col_len(struct hists *hists, int max_rows); 156void hists__output_recalc_col_len(struct hists *hists, int max_rows);
156 157
157u64 hists__total_period(struct hists *hists); 158u64 hists__total_period(struct hists *hists);
@@ -192,6 +193,7 @@ struct perf_hpp {
192}; 193};
193 194
194struct perf_hpp_fmt { 195struct perf_hpp_fmt {
196 const char *name;
195 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 197 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
196 struct perf_evsel *evsel); 198 struct perf_evsel *evsel);
197 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 199 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -207,6 +209,8 @@ struct perf_hpp_fmt {
207 struct list_head list; 209 struct list_head list;
208 struct list_head sort_list; 210 struct list_head sort_list;
209 bool elide; 211 bool elide;
212 int len;
213 int user_len;
210}; 214};
211 215
212extern struct list_head perf_hpp__list; 216extern struct list_head perf_hpp__list;
@@ -261,17 +265,19 @@ static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
261} 265}
262 266
263void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 267void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
268void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists);
269void perf_hpp__set_user_width(const char *width_list_str);
264 270
265typedef u64 (*hpp_field_fn)(struct hist_entry *he); 271typedef u64 (*hpp_field_fn)(struct hist_entry *he);
266typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 272typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
267typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...); 273typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
268 274
269int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 275int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
270 hpp_field_fn get_field, const char *fmt, 276 struct hist_entry *he, hpp_field_fn get_field,
271 hpp_snprint_fn print_fn, bool fmt_percent); 277 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
272int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 278int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
273 hpp_field_fn get_field, const char *fmt, 279 struct hist_entry *he, hpp_field_fn get_field,
274 hpp_snprint_fn print_fn, bool fmt_percent); 280 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
275 281
276static inline void advance_hpp(struct perf_hpp *hpp, int inc) 282static inline void advance_hpp(struct perf_hpp *hpp, int inc)
277{ 283{
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index 0b5a8cd2ee79..cf1d7913783b 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -92,7 +92,6 @@ struct perf_kvm_stat {
92 u64 lost_events; 92 u64 lost_events;
93 u64 duration; 93 u64 duration;
94 94
95 const char *pid_str;
96 struct intlist *pid_list; 95 struct intlist *pid_list;
97 96
98 struct rb_root result; 97 struct rb_root result;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 16bba9fff2c8..b7d477fbda02 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -17,8 +17,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
17{ 17{
18 map_groups__init(&machine->kmaps); 18 map_groups__init(&machine->kmaps);
19 RB_CLEAR_NODE(&machine->rb_node); 19 RB_CLEAR_NODE(&machine->rb_node);
20 INIT_LIST_HEAD(&machine->user_dsos); 20 INIT_LIST_HEAD(&machine->user_dsos.head);
21 INIT_LIST_HEAD(&machine->kernel_dsos); 21 INIT_LIST_HEAD(&machine->kernel_dsos.head);
22 22
23 machine->threads = RB_ROOT; 23 machine->threads = RB_ROOT;
24 INIT_LIST_HEAD(&machine->dead_threads); 24 INIT_LIST_HEAD(&machine->dead_threads);
@@ -31,6 +31,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
31 31
32 machine->symbol_filter = NULL; 32 machine->symbol_filter = NULL;
33 machine->id_hdr_size = 0; 33 machine->id_hdr_size = 0;
34 machine->comm_exec = false;
35 machine->kernel_start = 0;
34 36
35 machine->root_dir = strdup(root_dir); 37 machine->root_dir = strdup(root_dir);
36 if (machine->root_dir == NULL) 38 if (machine->root_dir == NULL)
@@ -70,11 +72,12 @@ out_delete:
70 return NULL; 72 return NULL;
71} 73}
72 74
73static void dsos__delete(struct list_head *dsos) 75static void dsos__delete(struct dsos *dsos)
74{ 76{
75 struct dso *pos, *n; 77 struct dso *pos, *n;
76 78
77 list_for_each_entry_safe(pos, n, dsos, node) { 79 list_for_each_entry_safe(pos, n, &dsos->head, node) {
80 RB_CLEAR_NODE(&pos->rb_node);
78 list_del(&pos->node); 81 list_del(&pos->node);
79 dso__delete(pos); 82 dso__delete(pos);
80 } 83 }
@@ -179,6 +182,19 @@ void machines__set_symbol_filter(struct machines *machines,
179 } 182 }
180} 183}
181 184
185void machines__set_comm_exec(struct machines *machines, bool comm_exec)
186{
187 struct rb_node *nd;
188
189 machines->host.comm_exec = comm_exec;
190
191 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
192 struct machine *machine = rb_entry(nd, struct machine, rb_node);
193
194 machine->comm_exec = comm_exec;
195 }
196}
197
182struct machine *machines__find(struct machines *machines, pid_t pid) 198struct machine *machines__find(struct machines *machines, pid_t pid)
183{ 199{
184 struct rb_node **p = &machines->guests.rb_node; 200 struct rb_node **p = &machines->guests.rb_node;
@@ -398,17 +414,31 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid,
398 return __machine__findnew_thread(machine, pid, tid, false); 414 return __machine__findnew_thread(machine, pid, tid, false);
399} 415}
400 416
417struct comm *machine__thread_exec_comm(struct machine *machine,
418 struct thread *thread)
419{
420 if (machine->comm_exec)
421 return thread__exec_comm(thread);
422 else
423 return thread__comm(thread);
424}
425
401int machine__process_comm_event(struct machine *machine, union perf_event *event, 426int machine__process_comm_event(struct machine *machine, union perf_event *event,
402 struct perf_sample *sample) 427 struct perf_sample *sample)
403{ 428{
404 struct thread *thread = machine__findnew_thread(machine, 429 struct thread *thread = machine__findnew_thread(machine,
405 event->comm.pid, 430 event->comm.pid,
406 event->comm.tid); 431 event->comm.tid);
432 bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC;
433
434 if (exec)
435 machine->comm_exec = true;
407 436
408 if (dump_trace) 437 if (dump_trace)
409 perf_event__fprintf_comm(event, stdout); 438 perf_event__fprintf_comm(event, stdout);
410 439
411 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) { 440 if (thread == NULL ||
441 __thread__set_comm(thread, event->comm.comm, sample->time, exec)) {
412 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 442 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
413 return -1; 443 return -1;
414 } 444 }
@@ -448,23 +478,23 @@ struct map *machine__new_module(struct machine *machine, u64 start,
448size_t machines__fprintf_dsos(struct machines *machines, FILE *fp) 478size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
449{ 479{
450 struct rb_node *nd; 480 struct rb_node *nd;
451 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) + 481 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos.head, fp) +
452 __dsos__fprintf(&machines->host.user_dsos, fp); 482 __dsos__fprintf(&machines->host.user_dsos.head, fp);
453 483
454 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 484 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
455 struct machine *pos = rb_entry(nd, struct machine, rb_node); 485 struct machine *pos = rb_entry(nd, struct machine, rb_node);
456 ret += __dsos__fprintf(&pos->kernel_dsos, fp); 486 ret += __dsos__fprintf(&pos->kernel_dsos.head, fp);
457 ret += __dsos__fprintf(&pos->user_dsos, fp); 487 ret += __dsos__fprintf(&pos->user_dsos.head, fp);
458 } 488 }
459 489
460 return ret; 490 return ret;
461} 491}
462 492
463size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 493size_t machine__fprintf_dsos_buildid(struct machine *m, FILE *fp,
464 bool (skip)(struct dso *dso, int parm), int parm) 494 bool (skip)(struct dso *dso, int parm), int parm)
465{ 495{
466 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) + 496 return __dsos__fprintf_buildid(&m->kernel_dsos.head, fp, skip, parm) +
467 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm); 497 __dsos__fprintf_buildid(&m->user_dsos.head, fp, skip, parm);
468} 498}
469 499
470size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, 500size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
@@ -565,8 +595,8 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
565 * Returns the name of the start symbol in *symbol_name. Pass in NULL as 595 * Returns the name of the start symbol in *symbol_name. Pass in NULL as
566 * symbol_name if it's not that important. 596 * symbol_name if it's not that important.
567 */ 597 */
568static u64 machine__get_kernel_start_addr(struct machine *machine, 598static u64 machine__get_running_kernel_start(struct machine *machine,
569 const char **symbol_name) 599 const char **symbol_name)
570{ 600{
571 char filename[PATH_MAX]; 601 char filename[PATH_MAX];
572 int i; 602 int i;
@@ -593,7 +623,7 @@ static u64 machine__get_kernel_start_addr(struct machine *machine,
593int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 623int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
594{ 624{
595 enum map_type type; 625 enum map_type type;
596 u64 start = machine__get_kernel_start_addr(machine, NULL); 626 u64 start = machine__get_running_kernel_start(machine, NULL);
597 627
598 for (type = 0; type < MAP__NR_TYPES; ++type) { 628 for (type = 0; type < MAP__NR_TYPES; ++type) {
599 struct kmap *kmap; 629 struct kmap *kmap;
@@ -912,7 +942,7 @@ int machine__create_kernel_maps(struct machine *machine)
912{ 942{
913 struct dso *kernel = machine__get_kernel(machine); 943 struct dso *kernel = machine__get_kernel(machine);
914 const char *name; 944 const char *name;
915 u64 addr = machine__get_kernel_start_addr(machine, &name); 945 u64 addr = machine__get_running_kernel_start(machine, &name);
916 if (!addr) 946 if (!addr)
917 return -1; 947 return -1;
918 948
@@ -965,7 +995,7 @@ static bool machine__uses_kcore(struct machine *machine)
965{ 995{
966 struct dso *dso; 996 struct dso *dso;
967 997
968 list_for_each_entry(dso, &machine->kernel_dsos, node) { 998 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
969 if (dso__is_kcore(dso)) 999 if (dso__is_kcore(dso))
970 return true; 1000 return true;
971 } 1001 }
@@ -1285,6 +1315,16 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread,
1285 1315
1286 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, 1316 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr,
1287 &al); 1317 &al);
1318 if (al.map == NULL) {
1319 /*
1320 * some shared data regions have execute bit set which puts
1321 * their mapping in the MAP__FUNCTION type array.
1322 * Check there as a fallback option before dropping the sample.
1323 */
1324 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr,
1325 &al);
1326 }
1327
1288 ams->addr = addr; 1328 ams->addr = addr;
1289 ams->al_addr = al.addr; 1329 ams->al_addr = al.addr;
1290 ams->sym = al.sym; 1330 ams->sym = al.sym;
@@ -1531,3 +1571,25 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1531 1571
1532 return 0; 1572 return 0;
1533} 1573}
1574
1575int machine__get_kernel_start(struct machine *machine)
1576{
1577 struct map *map = machine__kernel_map(machine, MAP__FUNCTION);
1578 int err = 0;
1579
1580 /*
1581 * The only addresses above 2^63 are kernel addresses of a 64-bit
1582 * kernel. Note that addresses are unsigned so that on a 32-bit system
1583 * all addresses including kernel addresses are less than 2^32. In
1584 * that case (32-bit system), if the kernel mapping is unknown, all
1585 * addresses will be assumed to be in user space - see
1586 * machine__kernel_ip().
1587 */
1588 machine->kernel_start = 1ULL << 63;
1589 if (map) {
1590 err = map__load(map, machine->symbol_filter);
1591 if (map->start)
1592 machine->kernel_start = map->start;
1593 }
1594 return err;
1595}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index b972824e6294..2b651a7f5d0d 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -4,6 +4,7 @@
4#include <sys/types.h> 4#include <sys/types.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include "map.h" 6#include "map.h"
7#include "dso.h"
7#include "event.h" 8#include "event.h"
8 9
9struct addr_location; 10struct addr_location;
@@ -26,15 +27,17 @@ struct machine {
26 struct rb_node rb_node; 27 struct rb_node rb_node;
27 pid_t pid; 28 pid_t pid;
28 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec;
29 char *root_dir; 31 char *root_dir;
30 struct rb_root threads; 32 struct rb_root threads;
31 struct list_head dead_threads; 33 struct list_head dead_threads;
32 struct thread *last_match; 34 struct thread *last_match;
33 struct vdso_info *vdso_info; 35 struct vdso_info *vdso_info;
34 struct list_head user_dsos; 36 struct dsos user_dsos;
35 struct list_head kernel_dsos; 37 struct dsos kernel_dsos;
36 struct map_groups kmaps; 38 struct map_groups kmaps;
37 struct map *vmlinux_maps[MAP__NR_TYPES]; 39 struct map *vmlinux_maps[MAP__NR_TYPES];
40 u64 kernel_start;
38 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
39 pid_t *current_tid; 42 pid_t *current_tid;
40}; 43};
@@ -45,8 +48,26 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
45 return machine->vmlinux_maps[type]; 48 return machine->vmlinux_maps[type];
46} 49}
47 50
51int machine__get_kernel_start(struct machine *machine);
52
53static inline u64 machine__kernel_start(struct machine *machine)
54{
55 if (!machine->kernel_start)
56 machine__get_kernel_start(machine);
57 return machine->kernel_start;
58}
59
60static inline bool machine__kernel_ip(struct machine *machine, u64 ip)
61{
62 u64 kernel_start = machine__kernel_start(machine);
63
64 return ip >= kernel_start;
65}
66
48struct thread *machine__find_thread(struct machine *machine, pid_t pid, 67struct thread *machine__find_thread(struct machine *machine, pid_t pid,
49 pid_t tid); 68 pid_t tid);
69struct comm *machine__thread_exec_comm(struct machine *machine,
70 struct thread *thread);
50 71
51int machine__process_comm_event(struct machine *machine, union perf_event *event, 72int machine__process_comm_event(struct machine *machine, union perf_event *event,
52 struct perf_sample *sample); 73 struct perf_sample *sample);
@@ -88,6 +109,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
88 109
89void machines__set_symbol_filter(struct machines *machines, 110void machines__set_symbol_filter(struct machines *machines,
90 symbol_filter_t symbol_filter); 111 symbol_filter_t symbol_filter);
112void machines__set_comm_exec(struct machines *machines, bool comm_exec);
91 113
92struct machine *machine__new_host(void); 114struct machine *machine__new_host(void);
93int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 115int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 31b8905dd863..b7090596ac50 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -31,6 +31,7 @@ static inline int is_anon_memory(const char *filename)
31static inline int is_no_dso_memory(const char *filename) 31static inline int is_no_dso_memory(const char *filename)
32{ 32{
33 return !strncmp(filename, "[stack", 6) || 33 return !strncmp(filename, "[stack", 6) ||
34 !strncmp(filename, "/SYSV",5) ||
34 !strcmp(filename, "[heap]"); 35 !strcmp(filename, "[heap]");
35} 36}
36 37
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 000000000000..706ce1a66169
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,245 @@
1#include <linux/list.h>
2#include <linux/compiler.h>
3#include "ordered-events.h"
4#include "evlist.h"
5#include "session.h"
6#include "asm/bug.h"
7#include "debug.h"
8
9#define pr_N(n, fmt, ...) \
10 eprintf(n, debug_ordered_events, fmt, ##__VA_ARGS__)
11
12#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
13
14static void queue_event(struct ordered_events *oe, struct ordered_event *new)
15{
16 struct ordered_event *last = oe->last;
17 u64 timestamp = new->timestamp;
18 struct list_head *p;
19
20 ++oe->nr_events;
21 oe->last = new;
22
23 pr_oe_time2(timestamp, "queue_event nr_events %u\n", oe->nr_events);
24
25 if (!last) {
26 list_add(&new->list, &oe->events);
27 oe->max_timestamp = timestamp;
28 return;
29 }
30
31 /*
32 * last event might point to some random place in the list as it's
33 * the last queued event. We expect that the new event is close to
34 * this.
35 */
36 if (last->timestamp <= timestamp) {
37 while (last->timestamp <= timestamp) {
38 p = last->list.next;
39 if (p == &oe->events) {
40 list_add_tail(&new->list, &oe->events);
41 oe->max_timestamp = timestamp;
42 return;
43 }
44 last = list_entry(p, struct ordered_event, list);
45 }
46 list_add_tail(&new->list, &last->list);
47 } else {
48 while (last->timestamp > timestamp) {
49 p = last->list.prev;
50 if (p == &oe->events) {
51 list_add(&new->list, &oe->events);
52 return;
53 }
54 last = list_entry(p, struct ordered_event, list);
55 }
56 list_add(&new->list, &last->list);
57 }
58}
59
60#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
61static struct ordered_event *alloc_event(struct ordered_events *oe)
62{
63 struct list_head *cache = &oe->cache;
64 struct ordered_event *new = NULL;
65
66 if (!list_empty(cache)) {
67 new = list_entry(cache->next, struct ordered_event, list);
68 list_del(&new->list);
69 } else if (oe->buffer) {
70 new = oe->buffer + oe->buffer_idx;
71 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
72 oe->buffer = NULL;
73 } else if (oe->cur_alloc_size < oe->max_alloc_size) {
74 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
75
76 oe->buffer = malloc(size);
77 if (!oe->buffer)
78 return NULL;
79
80 pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
81 oe->cur_alloc_size, size, oe->max_alloc_size);
82
83 oe->cur_alloc_size += size;
84 list_add(&oe->buffer->list, &oe->to_free);
85
86 /* First entry is abused to maintain the to_free list. */
87 oe->buffer_idx = 2;
88 new = oe->buffer + 1;
89 } else {
90 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
91 }
92
93 return new;
94}
95
96struct ordered_event *
97ordered_events__new(struct ordered_events *oe, u64 timestamp)
98{
99 struct ordered_event *new;
100
101 new = alloc_event(oe);
102 if (new) {
103 new->timestamp = timestamp;
104 queue_event(oe, new);
105 }
106
107 return new;
108}
109
110void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event)
111{
112 list_move(&event->list, &oe->cache);
113 oe->nr_events--;
114}
115
116static int __ordered_events__flush(struct perf_session *s,
117 struct perf_tool *tool)
118{
119 struct ordered_events *oe = &s->ordered_events;
120 struct list_head *head = &oe->events;
121 struct ordered_event *tmp, *iter;
122 struct perf_sample sample;
123 u64 limit = oe->next_flush;
124 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
125 bool show_progress = limit == ULLONG_MAX;
126 struct ui_progress prog;
127 int ret;
128
129 if (!tool->ordered_events || !limit)
130 return 0;
131
132 if (show_progress)
133 ui_progress__init(&prog, oe->nr_events, "Processing time ordered events...");
134
135 list_for_each_entry_safe(iter, tmp, head, list) {
136 if (session_done())
137 return 0;
138
139 if (iter->timestamp > limit)
140 break;
141
142 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
143 if (ret)
144 pr_err("Can't parse sample, err = %d\n", ret);
145 else {
146 ret = perf_session__deliver_event(s, iter->event, &sample, tool,
147 iter->file_offset);
148 if (ret)
149 return ret;
150 }
151
152 ordered_events__delete(oe, iter);
153 oe->last_flush = iter->timestamp;
154
155 if (show_progress)
156 ui_progress__update(&prog, 1);
157 }
158
159 if (list_empty(head))
160 oe->last = NULL;
161 else if (last_ts <= limit)
162 oe->last = list_entry(head->prev, struct ordered_event, list);
163
164 return 0;
165}
166
167int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
168 enum oe_flush how)
169{
170 struct ordered_events *oe = &s->ordered_events;
171 static const char * const str[] = {
172 "NONE",
173 "FINAL",
174 "ROUND",
175 "HALF ",
176 };
177 int err;
178
179 switch (how) {
180 case OE_FLUSH__FINAL:
181 oe->next_flush = ULLONG_MAX;
182 break;
183
184 case OE_FLUSH__HALF:
185 {
186 struct ordered_event *first, *last;
187 struct list_head *head = &oe->events;
188
189 first = list_entry(head->next, struct ordered_event, list);
190 last = oe->last;
191
192 /* Warn if we are called before any event got allocated. */
193 if (WARN_ONCE(!last || list_empty(head), "empty queue"))
194 return 0;
195
196 oe->next_flush = first->timestamp;
197 oe->next_flush += (last->timestamp - first->timestamp) / 2;
198 break;
199 }
200
201 case OE_FLUSH__ROUND:
202 case OE_FLUSH__NONE:
203 default:
204 break;
205 };
206
207 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush PRE %s, nr_events %u\n",
208 str[how], oe->nr_events);
209 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
210
211 err = __ordered_events__flush(s, tool);
212
213 if (!err) {
214 if (how == OE_FLUSH__ROUND)
215 oe->next_flush = oe->max_timestamp;
216
217 oe->last_flush_type = how;
218 }
219
220 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush POST %s, nr_events %u\n",
221 str[how], oe->nr_events);
222 pr_oe_time(oe->last_flush, "last_flush\n");
223
224 return err;
225}
226
227void ordered_events__init(struct ordered_events *oe)
228{
229 INIT_LIST_HEAD(&oe->events);
230 INIT_LIST_HEAD(&oe->cache);
231 INIT_LIST_HEAD(&oe->to_free);
232 oe->max_alloc_size = (u64) -1;
233 oe->cur_alloc_size = 0;
234}
235
236void ordered_events__free(struct ordered_events *oe)
237{
238 while (!list_empty(&oe->to_free)) {
239 struct ordered_event *event;
240
241 event = list_entry(oe->to_free.next, struct ordered_event, list);
242 list_del(&event->list);
243 free(event);
244 }
245}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
new file mode 100644
index 000000000000..3b2f20542a01
--- /dev/null
+++ b/tools/perf/util/ordered-events.h
@@ -0,0 +1,51 @@
1#ifndef __ORDERED_EVENTS_H
2#define __ORDERED_EVENTS_H
3
4#include <linux/types.h>
5#include "tool.h"
6
7struct perf_session;
8
9struct ordered_event {
10 u64 timestamp;
11 u64 file_offset;
12 union perf_event *event;
13 struct list_head list;
14};
15
16enum oe_flush {
17 OE_FLUSH__NONE,
18 OE_FLUSH__FINAL,
19 OE_FLUSH__ROUND,
20 OE_FLUSH__HALF,
21};
22
23struct ordered_events {
24 u64 last_flush;
25 u64 next_flush;
26 u64 max_timestamp;
27 u64 max_alloc_size;
28 u64 cur_alloc_size;
29 struct list_head events;
30 struct list_head cache;
31 struct list_head to_free;
32 struct ordered_event *buffer;
33 struct ordered_event *last;
34 int buffer_idx;
35 unsigned int nr_events;
36 enum oe_flush last_flush_type;
37};
38
39struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp);
40void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
41int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
42 enum oe_flush how);
43void ordered_events__init(struct ordered_events *oe);
44void ordered_events__free(struct ordered_events *oe);
45
46static inline
47void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
48{
49 oe->max_alloc_size = size;
50}
51#endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1e15df10a88c..d76aa30cb1fb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -10,6 +10,7 @@
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debug.h"
13#include <api/fs/debugfs.h> 14#include <api/fs/debugfs.h>
14#include "parse-events-bison.h" 15#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int 16#define YY_EXTRA_TYPE int
@@ -633,18 +634,28 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
633 char *name, struct list_head *head_config) 634 char *name, struct list_head *head_config)
634{ 635{
635 struct perf_event_attr attr; 636 struct perf_event_attr attr;
637 struct perf_pmu_info info;
636 struct perf_pmu *pmu; 638 struct perf_pmu *pmu;
637 struct perf_evsel *evsel; 639 struct perf_evsel *evsel;
638 const char *unit;
639 double scale;
640 640
641 pmu = perf_pmu__find(name); 641 pmu = perf_pmu__find(name);
642 if (!pmu) 642 if (!pmu)
643 return -EINVAL; 643 return -EINVAL;
644 644
645 memset(&attr, 0, sizeof(attr)); 645 if (pmu->default_config) {
646 memcpy(&attr, pmu->default_config,
647 sizeof(struct perf_event_attr));
648 } else {
649 memset(&attr, 0, sizeof(attr));
650 }
651
652 if (!head_config) {
653 attr.type = pmu->type;
654 evsel = __add_event(list, idx, &attr, NULL, pmu->cpus);
655 return evsel ? 0 : -ENOMEM;
656 }
646 657
647 if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) 658 if (perf_pmu__check_alias(pmu, head_config, &info))
648 return -EINVAL; 659 return -EINVAL;
649 660
650 /* 661 /*
@@ -659,8 +670,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
659 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), 670 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
660 pmu->cpus); 671 pmu->cpus);
661 if (evsel) { 672 if (evsel) {
662 evsel->unit = unit; 673 evsel->unit = info.unit;
663 evsel->scale = scale; 674 evsel->scale = info.scale;
664 } 675 }
665 676
666 return evsel ? 0 : -ENOMEM; 677 return evsel ? 0 : -ENOMEM;
@@ -973,7 +984,7 @@ int parse_filter(const struct option *opt, const char *str,
973 984
974 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 985 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
975 fprintf(stderr, 986 fprintf(stderr,
976 "-F option should follow a -e tracepoint option\n"); 987 "--filter option should follow a -e tracepoint option\n");
977 return -1; 988 return -1;
978 } 989 }
979 990
@@ -1006,9 +1017,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1006 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1017 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1007 char evt_path[MAXPATHLEN]; 1018 char evt_path[MAXPATHLEN];
1008 char dir_path[MAXPATHLEN]; 1019 char dir_path[MAXPATHLEN];
1020 char sbuf[STRERR_BUFSIZE];
1009 1021
1010 if (debugfs_valid_mountpoint(tracing_events_path)) { 1022 if (debugfs_valid_mountpoint(tracing_events_path)) {
1011 printf(" [ Tracepoints not available: %s ]\n", strerror(errno)); 1023 printf(" [ Tracepoints not available: %s ]\n",
1024 strerror_r(errno, sbuf, sizeof(sbuf)));
1012 return; 1025 return;
1013 } 1026 }
1014 1027
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 0bc87ba46bf3..55fab6ad609a 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -210,6 +210,16 @@ PE_NAME '/' event_config '/'
210 parse_events__free_terms($3); 210 parse_events__free_terms($3);
211 $$ = list; 211 $$ = list;
212} 212}
213|
214PE_NAME '/' '/'
215{
216 struct parse_events_evlist *data = _data;
217 struct list_head *list;
218
219 ALLOC_LIST(list);
220 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
221 $$ = list;
222}
213 223
214value_sym: 224value_sym:
215PE_VALUE_SYM_HW 225PE_VALUE_SYM_HW
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 7a811eb61f75..93a41ca96b8e 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2,6 +2,8 @@
2#include <sys/types.h> 2#include <sys/types.h>
3#include <unistd.h> 3#include <unistd.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
6#include <stdarg.h>
5#include <dirent.h> 7#include <dirent.h>
6#include <api/fs/fs.h> 8#include <api/fs/fs.h>
7#include <locale.h> 9#include <locale.h>
@@ -14,8 +16,8 @@
14 16
15struct perf_pmu_alias { 17struct perf_pmu_alias {
16 char *name; 18 char *name;
17 struct list_head terms; 19 struct list_head terms; /* HEAD struct parse_events_term -> list */
18 struct list_head list; 20 struct list_head list; /* ELEM */
19 char unit[UNIT_MAX_LEN+1]; 21 char unit[UNIT_MAX_LEN+1];
20 double scale; 22 double scale;
21}; 23};
@@ -208,6 +210,19 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
208 return 0; 210 return 0;
209} 211}
210 212
213static inline bool pmu_alias_info_file(char *name)
214{
215 size_t len;
216
217 len = strlen(name);
218 if (len > 5 && !strcmp(name + len - 5, ".unit"))
219 return true;
220 if (len > 6 && !strcmp(name + len - 6, ".scale"))
221 return true;
222
223 return false;
224}
225
211/* 226/*
212 * Process all the sysfs attributes located under the directory 227 * Process all the sysfs attributes located under the directory
213 * specified in 'dir' parameter. 228 * specified in 'dir' parameter.
@@ -216,7 +231,6 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
216{ 231{
217 struct dirent *evt_ent; 232 struct dirent *evt_ent;
218 DIR *event_dir; 233 DIR *event_dir;
219 size_t len;
220 int ret = 0; 234 int ret = 0;
221 235
222 event_dir = opendir(dir); 236 event_dir = opendir(dir);
@@ -232,13 +246,9 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
232 continue; 246 continue;
233 247
234 /* 248 /*
235 * skip .unit and .scale info files 249 * skip info files parsed in perf_pmu__new_alias()
236 * parsed in perf_pmu__new_alias()
237 */ 250 */
238 len = strlen(name); 251 if (pmu_alias_info_file(name))
239 if (len > 5 && !strcmp(name + len - 5, ".unit"))
240 continue;
241 if (len > 6 && !strcmp(name + len - 6, ".scale"))
242 continue; 252 continue;
243 253
244 snprintf(path, PATH_MAX, "%s/%s", dir, name); 254 snprintf(path, PATH_MAX, "%s/%s", dir, name);
@@ -387,6 +397,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
387 return cpus; 397 return cpus;
388} 398}
389 399
400struct perf_event_attr *__attribute__((weak))
401perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
402{
403 return NULL;
404}
405
390static struct perf_pmu *pmu_lookup(const char *name) 406static struct perf_pmu *pmu_lookup(const char *name)
391{ 407{
392 struct perf_pmu *pmu; 408 struct perf_pmu *pmu;
@@ -421,6 +437,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
421 pmu->name = strdup(name); 437 pmu->name = strdup(name);
422 pmu->type = type; 438 pmu->type = type;
423 list_add_tail(&pmu->list, &pmus); 439 list_add_tail(&pmu->list, &pmus);
440
441 pmu->default_config = perf_pmu__get_default_config(pmu);
442
424 return pmu; 443 return pmu;
425} 444}
426 445
@@ -479,28 +498,24 @@ pmu_find_format(struct list_head *formats, char *name)
479} 498}
480 499
481/* 500/*
482 * Returns value based on the format definition (format parameter) 501 * Sets value based on the format definition (format parameter)
483 * and unformated value (value parameter). 502 * and unformated value (value parameter).
484 *
485 * TODO maybe optimize a little ;)
486 */ 503 */
487static __u64 pmu_format_value(unsigned long *format, __u64 value) 504static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
505 bool zero)
488{ 506{
489 unsigned long fbit, vbit; 507 unsigned long fbit, vbit;
490 __u64 v = 0;
491 508
492 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 509 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
493 510
494 if (!test_bit(fbit, format)) 511 if (!test_bit(fbit, format))
495 continue; 512 continue;
496 513
497 if (!(value & (1llu << vbit++))) 514 if (value & (1llu << vbit++))
498 continue; 515 *v |= (1llu << fbit);
499 516 else if (zero)
500 v |= (1llu << fbit); 517 *v &= ~(1llu << fbit);
501 } 518 }
502
503 return v;
504} 519}
505 520
506/* 521/*
@@ -509,7 +524,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
509 */ 524 */
510static int pmu_config_term(struct list_head *formats, 525static int pmu_config_term(struct list_head *formats,
511 struct perf_event_attr *attr, 526 struct perf_event_attr *attr,
512 struct parse_events_term *term) 527 struct parse_events_term *term,
528 bool zero)
513{ 529{
514 struct perf_pmu_format *format; 530 struct perf_pmu_format *format;
515 __u64 *vp; 531 __u64 *vp;
@@ -548,18 +564,19 @@ static int pmu_config_term(struct list_head *formats,
548 * non-hardcoded terms, here's the place to translate 564 * non-hardcoded terms, here's the place to translate
549 * them into value. 565 * them into value.
550 */ 566 */
551 *vp |= pmu_format_value(format->bits, term->val.num); 567 pmu_format_value(format->bits, term->val.num, vp, zero);
552 return 0; 568 return 0;
553} 569}
554 570
555int perf_pmu__config_terms(struct list_head *formats, 571int perf_pmu__config_terms(struct list_head *formats,
556 struct perf_event_attr *attr, 572 struct perf_event_attr *attr,
557 struct list_head *head_terms) 573 struct list_head *head_terms,
574 bool zero)
558{ 575{
559 struct parse_events_term *term; 576 struct parse_events_term *term;
560 577
561 list_for_each_entry(term, head_terms, list) 578 list_for_each_entry(term, head_terms, list)
562 if (pmu_config_term(formats, attr, term)) 579 if (pmu_config_term(formats, attr, term, zero))
563 return -EINVAL; 580 return -EINVAL;
564 581
565 return 0; 582 return 0;
@@ -573,8 +590,10 @@ int perf_pmu__config_terms(struct list_head *formats,
573int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 590int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
574 struct list_head *head_terms) 591 struct list_head *head_terms)
575{ 592{
593 bool zero = !!pmu->default_config;
594
576 attr->type = pmu->type; 595 attr->type = pmu->type;
577 return perf_pmu__config_terms(&pmu->format, attr, head_terms); 596 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
578} 597}
579 598
580static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 599static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
@@ -634,7 +653,7 @@ static int check_unit_scale(struct perf_pmu_alias *alias,
634 * defined for the alias 653 * defined for the alias
635 */ 654 */
636int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 655int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
637 const char **unit, double *scale) 656 struct perf_pmu_info *info)
638{ 657{
639 struct parse_events_term *term, *h; 658 struct parse_events_term *term, *h;
640 struct perf_pmu_alias *alias; 659 struct perf_pmu_alias *alias;
@@ -644,8 +663,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
644 * Mark unit and scale as not set 663 * Mark unit and scale as not set
645 * (different from default values, see below) 664 * (different from default values, see below)
646 */ 665 */
647 *unit = NULL; 666 info->unit = NULL;
648 *scale = 0.0; 667 info->scale = 0.0;
649 668
650 list_for_each_entry_safe(term, h, head_terms, list) { 669 list_for_each_entry_safe(term, h, head_terms, list) {
651 alias = pmu_find_alias(pmu, term); 670 alias = pmu_find_alias(pmu, term);
@@ -655,7 +674,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
655 if (ret) 674 if (ret)
656 return ret; 675 return ret;
657 676
658 ret = check_unit_scale(alias, unit, scale); 677 ret = check_unit_scale(alias, &info->unit, &info->scale);
659 if (ret) 678 if (ret)
660 return ret; 679 return ret;
661 680
@@ -668,11 +687,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
668 * set defaults as for evsel 687 * set defaults as for evsel
669 * unit cannot left to NULL 688 * unit cannot left to NULL
670 */ 689 */
671 if (*unit == NULL) 690 if (info->unit == NULL)
672 *unit = ""; 691 info->unit = "";
673 692
674 if (*scale == 0.0) 693 if (info->scale == 0.0)
675 *scale = 1.0; 694 info->scale = 1.0;
676 695
677 return 0; 696 return 0;
678} 697}
@@ -794,3 +813,39 @@ bool pmu_have_event(const char *pname, const char *name)
794 } 813 }
795 return false; 814 return false;
796} 815}
816
817static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
818{
819 struct stat st;
820 char path[PATH_MAX];
821 const char *sysfs;
822
823 sysfs = sysfs__mountpoint();
824 if (!sysfs)
825 return NULL;
826
827 snprintf(path, PATH_MAX,
828 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
829
830 if (stat(path, &st) < 0)
831 return NULL;
832
833 return fopen(path, "r");
834}
835
836int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
837 ...)
838{
839 va_list args;
840 FILE *file;
841 int ret = EOF;
842
843 va_start(args, fmt);
844 file = perf_pmu__open_file(pmu, name);
845 if (file) {
846 ret = vfscanf(file, fmt, args);
847 fclose(file);
848 }
849 va_end(args);
850 return ret;
851}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index c14a543ce1f3..fe90a012c003 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -13,13 +13,21 @@ enum {
13 13
14#define PERF_PMU_FORMAT_BITS 64 14#define PERF_PMU_FORMAT_BITS 64
15 15
16struct perf_event_attr;
17
16struct perf_pmu { 18struct perf_pmu {
17 char *name; 19 char *name;
18 __u32 type; 20 __u32 type;
21 struct perf_event_attr *default_config;
19 struct cpu_map *cpus; 22 struct cpu_map *cpus;
20 struct list_head format; 23 struct list_head format; /* HEAD struct perf_pmu_format -> list */
21 struct list_head aliases; 24 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
22 struct list_head list; 25 struct list_head list; /* ELEM */
26};
27
28struct perf_pmu_info {
29 const char *unit;
30 double scale;
23}; 31};
24 32
25struct perf_pmu *perf_pmu__find(const char *name); 33struct perf_pmu *perf_pmu__find(const char *name);
@@ -27,9 +35,10 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
27 struct list_head *head_terms); 35 struct list_head *head_terms);
28int perf_pmu__config_terms(struct list_head *formats, 36int perf_pmu__config_terms(struct list_head *formats,
29 struct perf_event_attr *attr, 37 struct perf_event_attr *attr,
30 struct list_head *head_terms); 38 struct list_head *head_terms,
39 bool zero);
31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 40int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
32 const char **unit, double *scale); 41 struct perf_pmu_info *info);
33struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 42struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
34 struct list_head *head_terms); 43 struct list_head *head_terms);
35int perf_pmu_wrap(void); 44int perf_pmu_wrap(void);
@@ -45,5 +54,11 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
45void print_pmu_events(const char *event_glob, bool name_only); 54void print_pmu_events(const char *event_glob, bool name_only);
46bool pmu_have_event(const char *pname, const char *name); 55bool pmu_have_event(const char *pname, const char *name);
47 56
57int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
58 ...) __attribute__((format(scanf, 3, 4)));
59
48int perf_pmu__test(void); 60int perf_pmu__test(void);
61
62struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
63
49#endif /* __PMU_H */ 64#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9a0a1839a377..c150ca4343eb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -79,7 +79,7 @@ static int init_symbol_maps(bool user_only)
79 int ret; 79 int ret;
80 80
81 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
82 ret = symbol__init(); 82 ret = symbol__init(NULL);
83 if (ret < 0) { 83 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 84 pr_debug("Failed to init symbol map.\n");
85 goto out; 85 goto out;
@@ -184,7 +184,8 @@ static struct dso *kernel_get_module_dso(const char *module)
184 const char *vmlinux_name; 184 const char *vmlinux_name;
185 185
186 if (module) { 186 if (module) {
187 list_for_each_entry(dso, &host_machine->kernel_dsos, node) { 187 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
188 node) {
188 if (strncmp(dso->short_name + 1, module, 189 if (strncmp(dso->short_name + 1, module,
189 dso->short_name_len - 2) == 0) 190 dso->short_name_len - 2) == 0)
190 goto found; 191 goto found;
@@ -258,21 +259,33 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
258#ifdef HAVE_DWARF_SUPPORT 259#ifdef HAVE_DWARF_SUPPORT
259 260
260/* Open new debuginfo of given module */ 261/* Open new debuginfo of given module */
261static struct debuginfo *open_debuginfo(const char *module) 262static struct debuginfo *open_debuginfo(const char *module, bool silent)
262{ 263{
263 const char *path = module; 264 const char *path = module;
265 struct debuginfo *ret;
264 266
265 if (!module || !strchr(module, '/')) { 267 if (!module || !strchr(module, '/')) {
266 path = kernel_get_module_path(module); 268 path = kernel_get_module_path(module);
267 if (!path) { 269 if (!path) {
268 pr_err("Failed to find path of %s module.\n", 270 if (!silent)
269 module ?: "kernel"); 271 pr_err("Failed to find path of %s module.\n",
272 module ?: "kernel");
270 return NULL; 273 return NULL;
271 } 274 }
272 } 275 }
273 return debuginfo__new(path); 276 ret = debuginfo__new(path);
277 if (!ret && !silent) {
278 pr_warning("The %s file has no debug information.\n", path);
279 if (!module || !strtailcmp(path, ".ko"))
280 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, ");
281 else
282 pr_warning("Rebuild with -g, ");
283 pr_warning("or install an appropriate debuginfo package.\n");
284 }
285 return ret;
274} 286}
275 287
288
276static int get_text_start_address(const char *exec, unsigned long *address) 289static int get_text_start_address(const char *exec, unsigned long *address)
277{ 290{
278 Elf *elf; 291 Elf *elf;
@@ -333,15 +346,13 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
333 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 346 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
334 tp->module ? : "kernel"); 347 tp->module ? : "kernel");
335 348
336 dinfo = open_debuginfo(tp->module); 349 dinfo = open_debuginfo(tp->module, verbose == 0);
337 if (dinfo) { 350 if (dinfo) {
338 ret = debuginfo__find_probe_point(dinfo, 351 ret = debuginfo__find_probe_point(dinfo,
339 (unsigned long)addr, pp); 352 (unsigned long)addr, pp);
340 debuginfo__delete(dinfo); 353 debuginfo__delete(dinfo);
341 } else { 354 } else
342 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", addr);
343 ret = -ENOENT; 355 ret = -ENOENT;
344 }
345 356
346 if (ret > 0) { 357 if (ret > 0) {
347 pp->retprobe = tp->retprobe; 358 pp->retprobe = tp->retprobe;
@@ -457,13 +468,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
457 struct debuginfo *dinfo; 468 struct debuginfo *dinfo;
458 int ntevs, ret = 0; 469 int ntevs, ret = 0;
459 470
460 dinfo = open_debuginfo(target); 471 dinfo = open_debuginfo(target, !need_dwarf);
461 472
462 if (!dinfo) { 473 if (!dinfo) {
463 if (need_dwarf) { 474 if (need_dwarf)
464 pr_warning("Failed to open debuginfo file.\n");
465 return -ENOENT; 475 return -ENOENT;
466 }
467 pr_debug("Could not open debuginfo. Try to use symbols.\n"); 476 pr_debug("Could not open debuginfo. Try to use symbols.\n");
468 return 0; 477 return 0;
469 } 478 }
@@ -565,7 +574,7 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
565 574
566static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 575static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
567{ 576{
568 char buf[LINEBUF_SIZE]; 577 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE];
569 const char *color = show_num ? "" : PERF_COLOR_BLUE; 578 const char *color = show_num ? "" : PERF_COLOR_BLUE;
570 const char *prefix = NULL; 579 const char *prefix = NULL;
571 580
@@ -585,7 +594,8 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
585 return 1; 594 return 1;
586error: 595error:
587 if (ferror(fp)) { 596 if (ferror(fp)) {
588 pr_warning("File read error: %s\n", strerror(errno)); 597 pr_warning("File read error: %s\n",
598 strerror_r(errno, sbuf, sizeof(sbuf)));
589 return -1; 599 return -1;
590 } 600 }
591 return 0; 601 return 0;
@@ -618,13 +628,12 @@ static int __show_line_range(struct line_range *lr, const char *module)
618 FILE *fp; 628 FILE *fp;
619 int ret; 629 int ret;
620 char *tmp; 630 char *tmp;
631 char sbuf[STRERR_BUFSIZE];
621 632
622 /* Search a line range */ 633 /* Search a line range */
623 dinfo = open_debuginfo(module); 634 dinfo = open_debuginfo(module, false);
624 if (!dinfo) { 635 if (!dinfo)
625 pr_warning("Failed to open debuginfo file.\n");
626 return -ENOENT; 636 return -ENOENT;
627 }
628 637
629 ret = debuginfo__find_line_range(dinfo, lr); 638 ret = debuginfo__find_line_range(dinfo, lr);
630 debuginfo__delete(dinfo); 639 debuginfo__delete(dinfo);
@@ -656,7 +665,7 @@ static int __show_line_range(struct line_range *lr, const char *module)
656 fp = fopen(lr->path, "r"); 665 fp = fopen(lr->path, "r");
657 if (fp == NULL) { 666 if (fp == NULL) {
658 pr_warning("Failed to open %s: %s\n", lr->path, 667 pr_warning("Failed to open %s: %s\n", lr->path,
659 strerror(errno)); 668 strerror_r(errno, sbuf, sizeof(sbuf)));
660 return -errno; 669 return -errno;
661 } 670 }
662 /* Skip to starting line number */ 671 /* Skip to starting line number */
@@ -689,11 +698,11 @@ end:
689 return ret; 698 return ret;
690} 699}
691 700
692int show_line_range(struct line_range *lr, const char *module) 701int show_line_range(struct line_range *lr, const char *module, bool user)
693{ 702{
694 int ret; 703 int ret;
695 704
696 ret = init_symbol_maps(false); 705 ret = init_symbol_maps(user);
697 if (ret < 0) 706 if (ret < 0)
698 return ret; 707 return ret;
699 ret = __show_line_range(lr, module); 708 ret = __show_line_range(lr, module);
@@ -768,13 +777,12 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
768 int i, ret = 0; 777 int i, ret = 0;
769 struct debuginfo *dinfo; 778 struct debuginfo *dinfo;
770 779
771 ret = init_symbol_maps(false); 780 ret = init_symbol_maps(pevs->uprobes);
772 if (ret < 0) 781 if (ret < 0)
773 return ret; 782 return ret;
774 783
775 dinfo = open_debuginfo(module); 784 dinfo = open_debuginfo(module, false);
776 if (!dinfo) { 785 if (!dinfo) {
777 pr_warning("Failed to open debuginfo file.\n");
778 ret = -ENOENT; 786 ret = -ENOENT;
779 goto out; 787 goto out;
780 } 788 }
@@ -815,7 +823,8 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
815} 823}
816 824
817int show_line_range(struct line_range *lr __maybe_unused, 825int show_line_range(struct line_range *lr __maybe_unused,
818 const char *module __maybe_unused) 826 const char *module __maybe_unused,
827 bool user __maybe_unused)
819{ 828{
820 pr_warning("Debuginfo-analysis is not supported.\n"); 829 pr_warning("Debuginfo-analysis is not supported.\n");
821 return -ENOSYS; 830 return -ENOSYS;
@@ -1405,8 +1414,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1405 1414
1406 return tmp - buf; 1415 return tmp - buf;
1407error: 1416error:
1408 pr_debug("Failed to synthesize perf probe argument: %s\n", 1417 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
1409 strerror(-ret));
1410 return ret; 1418 return ret;
1411} 1419}
1412 1420
@@ -1455,8 +1463,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1455 1463
1456 return buf; 1464 return buf;
1457error: 1465error:
1458 pr_debug("Failed to synthesize perf probe point: %s\n", 1466 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1459 strerror(-ret));
1460 free(buf); 1467 free(buf);
1461 return NULL; 1468 return NULL;
1462} 1469}
@@ -1780,10 +1787,11 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1780 memset(tev, 0, sizeof(*tev)); 1787 memset(tev, 0, sizeof(*tev));
1781} 1788}
1782 1789
1783static void print_warn_msg(const char *file, bool is_kprobe) 1790static void print_open_warning(int err, bool is_kprobe)
1784{ 1791{
1792 char sbuf[STRERR_BUFSIZE];
1785 1793
1786 if (errno == ENOENT) { 1794 if (err == -ENOENT) {
1787 const char *config; 1795 const char *config;
1788 1796
1789 if (!is_kprobe) 1797 if (!is_kprobe)
@@ -1791,25 +1799,43 @@ static void print_warn_msg(const char *file, bool is_kprobe)
1791 else 1799 else
1792 config = "CONFIG_KPROBE_EVENTS"; 1800 config = "CONFIG_KPROBE_EVENTS";
1793 1801
1794 pr_warning("%s file does not exist - please rebuild kernel" 1802 pr_warning("%cprobe_events file does not exist"
1795 " with %s.\n", file, config); 1803 " - please rebuild kernel with %s.\n",
1796 } else 1804 is_kprobe ? 'k' : 'u', config);
1797 pr_warning("Failed to open %s file: %s\n", file, 1805 } else if (err == -ENOTSUP)
1798 strerror(errno)); 1806 pr_warning("Debugfs is not mounted.\n");
1807 else
1808 pr_warning("Failed to open %cprobe_events: %s\n",
1809 is_kprobe ? 'k' : 'u',
1810 strerror_r(-err, sbuf, sizeof(sbuf)));
1811}
1812
1813static void print_both_open_warning(int kerr, int uerr)
1814{
1815 /* Both kprobes and uprobes are disabled, warn it. */
1816 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1817 pr_warning("Debugfs is not mounted.\n");
1818 else if (kerr == -ENOENT && uerr == -ENOENT)
1819 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1820 "or/and CONFIG_UPROBE_EVENTS.\n");
1821 else {
1822 char sbuf[STRERR_BUFSIZE];
1823 pr_warning("Failed to open kprobe events: %s.\n",
1824 strerror_r(-kerr, sbuf, sizeof(sbuf)));
1825 pr_warning("Failed to open uprobe events: %s.\n",
1826 strerror_r(-uerr, sbuf, sizeof(sbuf)));
1827 }
1799} 1828}
1800 1829
1801static int open_probe_events(const char *trace_file, bool readwrite, 1830static int open_probe_events(const char *trace_file, bool readwrite)
1802 bool is_kprobe)
1803{ 1831{
1804 char buf[PATH_MAX]; 1832 char buf[PATH_MAX];
1805 const char *__debugfs; 1833 const char *__debugfs;
1806 int ret; 1834 int ret;
1807 1835
1808 __debugfs = debugfs_find_mountpoint(); 1836 __debugfs = debugfs_find_mountpoint();
1809 if (__debugfs == NULL) { 1837 if (__debugfs == NULL)
1810 pr_warning("Debugfs is not mounted.\n"); 1838 return -ENOTSUP;
1811 return -ENOENT;
1812 }
1813 1839
1814 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1840 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1815 if (ret >= 0) { 1841 if (ret >= 0) {
@@ -1820,19 +1846,19 @@ static int open_probe_events(const char *trace_file, bool readwrite,
1820 ret = open(buf, O_RDONLY, 0); 1846 ret = open(buf, O_RDONLY, 0);
1821 1847
1822 if (ret < 0) 1848 if (ret < 0)
1823 print_warn_msg(buf, is_kprobe); 1849 ret = -errno;
1824 } 1850 }
1825 return ret; 1851 return ret;
1826} 1852}
1827 1853
1828static int open_kprobe_events(bool readwrite) 1854static int open_kprobe_events(bool readwrite)
1829{ 1855{
1830 return open_probe_events("tracing/kprobe_events", readwrite, true); 1856 return open_probe_events("tracing/kprobe_events", readwrite);
1831} 1857}
1832 1858
1833static int open_uprobe_events(bool readwrite) 1859static int open_uprobe_events(bool readwrite)
1834{ 1860{
1835 return open_probe_events("tracing/uprobe_events", readwrite, false); 1861 return open_probe_events("tracing/uprobe_events", readwrite);
1836} 1862}
1837 1863
1838/* Get raw string list of current kprobe_events or uprobe_events */ 1864/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1857,7 +1883,7 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1857 p[idx] = '\0'; 1883 p[idx] = '\0';
1858 ret = strlist__add(sl, buf); 1884 ret = strlist__add(sl, buf);
1859 if (ret < 0) { 1885 if (ret < 0) {
1860 pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1886 pr_debug("strlist__add failed (%d)\n", ret);
1861 strlist__delete(sl); 1887 strlist__delete(sl);
1862 return NULL; 1888 return NULL;
1863 } 1889 }
@@ -1916,7 +1942,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1916 1942
1917 rawlist = get_probe_trace_command_rawlist(fd); 1943 rawlist = get_probe_trace_command_rawlist(fd);
1918 if (!rawlist) 1944 if (!rawlist)
1919 return -ENOENT; 1945 return -ENOMEM;
1920 1946
1921 strlist__for_each(ent, rawlist) { 1947 strlist__for_each(ent, rawlist) {
1922 ret = parse_probe_trace_command(ent->s, &tev); 1948 ret = parse_probe_trace_command(ent->s, &tev);
@@ -1940,27 +1966,34 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1940/* List up current perf-probe events */ 1966/* List up current perf-probe events */
1941int show_perf_probe_events(void) 1967int show_perf_probe_events(void)
1942{ 1968{
1943 int fd, ret; 1969 int kp_fd, up_fd, ret;
1944 1970
1945 setup_pager(); 1971 setup_pager();
1946 fd = open_kprobe_events(false);
1947
1948 if (fd < 0)
1949 return fd;
1950 1972
1951 ret = init_symbol_maps(false); 1973 ret = init_symbol_maps(false);
1952 if (ret < 0) 1974 if (ret < 0)
1953 return ret; 1975 return ret;
1954 1976
1955 ret = __show_perf_probe_events(fd, true); 1977 kp_fd = open_kprobe_events(false);
1956 close(fd); 1978 if (kp_fd >= 0) {
1979 ret = __show_perf_probe_events(kp_fd, true);
1980 close(kp_fd);
1981 if (ret < 0)
1982 goto out;
1983 }
1957 1984
1958 fd = open_uprobe_events(false); 1985 up_fd = open_uprobe_events(false);
1959 if (fd >= 0) { 1986 if (kp_fd < 0 && up_fd < 0) {
1960 ret = __show_perf_probe_events(fd, false); 1987 print_both_open_warning(kp_fd, up_fd);
1961 close(fd); 1988 ret = kp_fd;
1989 goto out;
1962 } 1990 }
1963 1991
1992 if (up_fd >= 0) {
1993 ret = __show_perf_probe_events(up_fd, false);
1994 close(up_fd);
1995 }
1996out:
1964 exit_symbol_maps(); 1997 exit_symbol_maps();
1965 return ret; 1998 return ret;
1966} 1999}
@@ -1976,6 +2009,8 @@ static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1976 2009
1977 memset(&tev, 0, sizeof(tev)); 2010 memset(&tev, 0, sizeof(tev));
1978 rawlist = get_probe_trace_command_rawlist(fd); 2011 rawlist = get_probe_trace_command_rawlist(fd);
2012 if (!rawlist)
2013 return NULL;
1979 sl = strlist__new(true, NULL); 2014 sl = strlist__new(true, NULL);
1980 strlist__for_each(ent, rawlist) { 2015 strlist__for_each(ent, rawlist) {
1981 ret = parse_probe_trace_command(ent->s, &tev); 2016 ret = parse_probe_trace_command(ent->s, &tev);
@@ -2005,6 +2040,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2005{ 2040{
2006 int ret = 0; 2041 int ret = 0;
2007 char *buf = synthesize_probe_trace_command(tev); 2042 char *buf = synthesize_probe_trace_command(tev);
2043 char sbuf[STRERR_BUFSIZE];
2008 2044
2009 if (!buf) { 2045 if (!buf) {
2010 pr_debug("Failed to synthesize probe trace event.\n"); 2046 pr_debug("Failed to synthesize probe trace event.\n");
@@ -2016,7 +2052,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2016 ret = write(fd, buf, strlen(buf)); 2052 ret = write(fd, buf, strlen(buf));
2017 if (ret <= 0) 2053 if (ret <= 0)
2018 pr_warning("Failed to write event: %s\n", 2054 pr_warning("Failed to write event: %s\n",
2019 strerror(errno)); 2055 strerror_r(errno, sbuf, sizeof(sbuf)));
2020 } 2056 }
2021 free(buf); 2057 free(buf);
2022 return ret; 2058 return ret;
@@ -2030,7 +2066,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2030 /* Try no suffix */ 2066 /* Try no suffix */
2031 ret = e_snprintf(buf, len, "%s", base); 2067 ret = e_snprintf(buf, len, "%s", base);
2032 if (ret < 0) { 2068 if (ret < 0) {
2033 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2069 pr_debug("snprintf() failed: %d\n", ret);
2034 return ret; 2070 return ret;
2035 } 2071 }
2036 if (!strlist__has_entry(namelist, buf)) 2072 if (!strlist__has_entry(namelist, buf))
@@ -2046,7 +2082,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2046 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2082 for (i = 1; i < MAX_EVENT_INDEX; i++) {
2047 ret = e_snprintf(buf, len, "%s_%d", base, i); 2083 ret = e_snprintf(buf, len, "%s_%d", base, i);
2048 if (ret < 0) { 2084 if (ret < 0) {
2049 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2085 pr_debug("snprintf() failed: %d\n", ret);
2050 return ret; 2086 return ret;
2051 } 2087 }
2052 if (!strlist__has_entry(namelist, buf)) 2088 if (!strlist__has_entry(namelist, buf))
@@ -2075,8 +2111,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2075 else 2111 else
2076 fd = open_kprobe_events(true); 2112 fd = open_kprobe_events(true);
2077 2113
2078 if (fd < 0) 2114 if (fd < 0) {
2115 print_open_warning(fd, !pev->uprobes);
2079 return fd; 2116 return fd;
2117 }
2118
2080 /* Get current event names */ 2119 /* Get current event names */
2081 namelist = get_probe_trace_event_names(fd, false); 2120 namelist = get_probe_trace_event_names(fd, false);
2082 if (!namelist) { 2121 if (!namelist) {
@@ -2408,7 +2447,8 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
2408 printf("Removed event: %s\n", ent->s); 2447 printf("Removed event: %s\n", ent->s);
2409 return 0; 2448 return 0;
2410error: 2449error:
2411 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 2450 pr_warning("Failed to delete event: %s\n",
2451 strerror_r(-ret, buf, sizeof(buf)));
2412 return ret; 2452 return ret;
2413} 2453}
2414 2454
@@ -2449,15 +2489,18 @@ int del_perf_probe_events(struct strlist *dellist)
2449 2489
2450 /* Get current event names */ 2490 /* Get current event names */
2451 kfd = open_kprobe_events(true); 2491 kfd = open_kprobe_events(true);
2452 if (kfd < 0) 2492 if (kfd >= 0)
2453 return kfd; 2493 namelist = get_probe_trace_event_names(kfd, true);
2454 2494
2455 namelist = get_probe_trace_event_names(kfd, true);
2456 ufd = open_uprobe_events(true); 2495 ufd = open_uprobe_events(true);
2457
2458 if (ufd >= 0) 2496 if (ufd >= 0)
2459 unamelist = get_probe_trace_event_names(ufd, true); 2497 unamelist = get_probe_trace_event_names(ufd, true);
2460 2498
2499 if (kfd < 0 && ufd < 0) {
2500 print_both_open_warning(kfd, ufd);
2501 goto error;
2502 }
2503
2461 if (namelist == NULL && unamelist == NULL) 2504 if (namelist == NULL && unamelist == NULL)
2462 goto error; 2505 goto error;
2463 2506
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 776c9347a3b6..e01e9943139f 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -128,7 +128,8 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
128 bool force_add); 128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module); 131extern int show_line_range(struct line_range *lr, const char *module,
132 bool user);
132extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 133extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
133 int max_probe_points, const char *module, 134 int max_probe_points, const char *module,
134 struct strfilter *filter, bool externs); 135 struct strfilter *filter, bool externs);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index dca9145d704c..c7918f83b300 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -281,6 +281,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
282 Dwarf_Die type; 282 Dwarf_Die type;
283 char buf[16]; 283 char buf[16];
284 char sbuf[STRERR_BUFSIZE];
284 int bsize, boffs, total; 285 int bsize, boffs, total;
285 int ret; 286 int ret;
286 287
@@ -367,7 +368,7 @@ formatted:
367 if (ret >= 16) 368 if (ret >= 16)
368 ret = -E2BIG; 369 ret = -E2BIG;
369 pr_warning("Failed to convert variable type: %s\n", 370 pr_warning("Failed to convert variable type: %s\n",
370 strerror(-ret)); 371 strerror_r(-ret, sbuf, sizeof(sbuf)));
371 return ret; 372 return ret;
372 } 373 }
373 tvar->type = strdup(buf); 374 tvar->type = strdup(buf);
@@ -608,14 +609,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
608 return -EINVAL; 609 return -EINVAL;
609 } 610 }
610 611
611 /* Get an appropriate symbol from symtab */ 612 symbol = dwarf_diename(sp_die);
612 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
613 if (!symbol) { 613 if (!symbol) {
614 pr_warning("Failed to find symbol at 0x%lx\n", 614 /* Try to get the symbol name from symtab */
615 (unsigned long)paddr); 615 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
616 return -ENOENT; 616 if (!symbol) {
617 pr_warning("Failed to find symbol at 0x%lx\n",
618 (unsigned long)paddr);
619 return -ENOENT;
620 }
621 eaddr = sym.st_value;
617 } 622 }
618 tp->offset = (unsigned long)(paddr - sym.st_value); 623 tp->offset = (unsigned long)(paddr - eaddr);
619 tp->address = (unsigned long)paddr; 624 tp->address = (unsigned long)paddr;
620 tp->symbol = strdup(symbol); 625 tp->symbol = strdup(symbol);
621 if (!tp->symbol) 626 if (!tp->symbol)
@@ -779,10 +784,12 @@ static int find_lazy_match_lines(struct intlist *list,
779 size_t line_len; 784 size_t line_len;
780 ssize_t len; 785 ssize_t len;
781 int count = 0, linenum = 1; 786 int count = 0, linenum = 1;
787 char sbuf[STRERR_BUFSIZE];
782 788
783 fp = fopen(fname, "r"); 789 fp = fopen(fname, "r");
784 if (!fp) { 790 if (!fp) {
785 pr_warning("Failed to open %s: %s\n", fname, strerror(errno)); 791 pr_warning("Failed to open %s: %s\n", fname,
792 strerror_r(errno, sbuf, sizeof(sbuf)));
786 return -errno; 793 return -errno;
787 } 794 }
788 795
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 12aa9b0d0ba1..3dda85ca50c1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -736,7 +736,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
737 return NULL; 737 return NULL;
738 738
739 n = poll(evlist->pollfd, evlist->nr_fds, timeout); 739 n = perf_evlist__poll(evlist, timeout);
740 if (n < 0) { 740 if (n < 0) {
741 PyErr_SetFromErrno(PyExc_OSError); 741 PyErr_SetFromErrno(PyExc_OSError);
742 return NULL; 742 return NULL;
@@ -753,9 +753,9 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
753 PyObject *list = PyList_New(0); 753 PyObject *list = PyList_New(0);
754 int i; 754 int i;
755 755
756 for (i = 0; i < evlist->nr_fds; ++i) { 756 for (i = 0; i < evlist->pollfd.nr; ++i) {
757 PyObject *file; 757 PyObject *file;
758 FILE *fp = fdopen(evlist->pollfd[i].fd, "r"); 758 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
759 759
760 if (fp == NULL) 760 if (fp == NULL)
761 goto free_list; 761 goto free_list;
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index fe8079edbdc1..cf69325b985f 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -14,6 +14,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
14 struct perf_evsel *evsel; 14 struct perf_evsel *evsel;
15 unsigned long flags = perf_event_open_cloexec_flag(); 15 unsigned long flags = perf_event_open_cloexec_flag();
16 int err = -EAGAIN, fd; 16 int err = -EAGAIN, fd;
17 static pid_t pid = -1;
17 18
18 evlist = perf_evlist__new(); 19 evlist = perf_evlist__new();
19 if (!evlist) 20 if (!evlist)
@@ -24,14 +25,22 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
24 25
25 evsel = perf_evlist__first(evlist); 26 evsel = perf_evlist__first(evlist);
26 27
27 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 28 while (1) {
28 if (fd < 0) 29 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
29 goto out_delete; 30 if (fd < 0) {
31 if (pid == -1 && errno == EACCES) {
32 pid = 0;
33 continue;
34 }
35 goto out_delete;
36 }
37 break;
38 }
30 close(fd); 39 close(fd);
31 40
32 fn(evsel); 41 fn(evsel);
33 42
34 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 43 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
35 if (fd < 0) { 44 if (fd < 0) {
36 if (errno == EINVAL) 45 if (errno == EINVAL)
37 err = -EINVAL; 46 err = -EINVAL;
@@ -47,7 +56,7 @@ out_delete:
47 56
48static bool perf_probe_api(setup_probe_fn_t fn) 57static bool perf_probe_api(setup_probe_fn_t fn)
49{ 58{
50 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL}; 59 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
51 struct cpu_map *cpus; 60 struct cpu_map *cpus;
52 int cpu, ret, i = 0; 61 int cpu, ret, i = 0;
53 62
@@ -106,7 +115,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
106 115
107 evlist__for_each(evlist, evsel) { 116 evlist__for_each(evlist, evsel) {
108 perf_evsel__config(evsel, opts); 117 perf_evsel__config(evsel, opts);
109 if (!evsel->idx && use_comm_exec) 118 if (evsel->tracking && use_comm_exec)
110 evsel->attr.comm_exec = 1; 119 evsel->attr.comm_exec = 1;
111 } 120 }
112 121
@@ -201,6 +210,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
201 struct perf_evsel *evsel; 210 struct perf_evsel *evsel;
202 int err, fd, cpu; 211 int err, fd, cpu;
203 bool ret = false; 212 bool ret = false;
213 pid_t pid = -1;
204 214
205 temp_evlist = perf_evlist__new(); 215 temp_evlist = perf_evlist__new();
206 if (!temp_evlist) 216 if (!temp_evlist)
@@ -221,12 +231,20 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
221 cpu = evlist->cpus->map[0]; 231 cpu = evlist->cpus->map[0];
222 } 232 }
223 233
224 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 234 while (1) {
225 perf_event_open_cloexec_flag()); 235 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
226 if (fd >= 0) { 236 perf_event_open_cloexec_flag());
227 close(fd); 237 if (fd < 0) {
228 ret = true; 238 if (pid == -1 && errno == EACCES) {
239 pid = 0;
240 continue;
241 }
242 goto out_delete;
243 }
244 break;
229 } 245 }
246 close(fd);
247 ret = true;
230 248
231out_delete: 249out_delete:
232 perf_evlist__delete(temp_evlist); 250 perf_evlist__delete(temp_evlist);
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index da8e9b285f51..34622b53e733 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -1,6 +1,7 @@
1#include "cache.h" 1#include "cache.h"
2#include "run-command.h" 2#include "run-command.h"
3#include "exec_cmd.h" 3#include "exec_cmd.h"
4#include "debug.h"
4 5
5static inline void close_pair(int fd[2]) 6static inline void close_pair(int fd[2])
6{ 7{
@@ -19,6 +20,7 @@ int start_command(struct child_process *cmd)
19{ 20{
20 int need_in, need_out, need_err; 21 int need_in, need_out, need_err;
21 int fdin[2], fdout[2], fderr[2]; 22 int fdin[2], fdout[2], fderr[2];
23 char sbuf[STRERR_BUFSIZE];
22 24
23 /* 25 /*
24 * In case of errors we must keep the promise to close FDs 26 * In case of errors we must keep the promise to close FDs
@@ -99,7 +101,7 @@ int start_command(struct child_process *cmd)
99 101
100 if (cmd->dir && chdir(cmd->dir)) 102 if (cmd->dir && chdir(cmd->dir))
101 die("exec %s: cd to %s failed (%s)", cmd->argv[0], 103 die("exec %s: cd to %s failed (%s)", cmd->argv[0],
102 cmd->dir, strerror(errno)); 104 cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
103 if (cmd->env) { 105 if (cmd->env) {
104 for (; *cmd->env; cmd->env++) { 106 for (; *cmd->env; cmd->env++) {
105 if (strchr(*cmd->env, '=')) 107 if (strchr(*cmd->env, '='))
@@ -153,6 +155,8 @@ int start_command(struct child_process *cmd)
153 155
154static int wait_or_whine(pid_t pid) 156static int wait_or_whine(pid_t pid)
155{ 157{
158 char sbuf[STRERR_BUFSIZE];
159
156 for (;;) { 160 for (;;) {
157 int status, code; 161 int status, code;
158 pid_t waiting = waitpid(pid, &status, 0); 162 pid_t waiting = waitpid(pid, &status, 0);
@@ -160,7 +164,8 @@ static int wait_or_whine(pid_t pid)
160 if (waiting < 0) { 164 if (waiting < 0) {
161 if (errno == EINTR) 165 if (errno == EINTR)
162 continue; 166 continue;
163 error("waitpid failed (%s)", strerror(errno)); 167 error("waitpid failed (%s)",
168 strerror_r(errno, sbuf, sizeof(sbuf)));
164 return -ERR_RUN_COMMAND_WAITPID; 169 return -ERR_RUN_COMMAND_WAITPID;
165 } 170 }
166 if (waiting != pid) 171 if (waiting != pid)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b2dba9c0a3a1..0a01bac4ce02 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -432,6 +432,11 @@ error:
432 return err; 432 return err;
433} 433}
434 434
435static int perl_flush_script(void)
436{
437 return 0;
438}
439
435/* 440/*
436 * Stop trace script 441 * Stop trace script
437 */ 442 */
@@ -633,6 +638,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
633struct scripting_ops perl_scripting_ops = { 638struct scripting_ops perl_scripting_ops = {
634 .name = "Perl", 639 .name = "Perl",
635 .start_script = perl_start_script, 640 .start_script = perl_start_script,
641 .flush_script = perl_flush_script,
636 .stop_script = perl_stop_script, 642 .stop_script = perl_stop_script,
637 .process_event = perl_process_event, 643 .process_event = perl_process_event,
638 .generate_script = perl_generate_script, 644 .generate_script = perl_generate_script,
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cbce2545da45..56ba07cce549 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -73,6 +73,35 @@ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObj
73 Py_DECREF(val); 73 Py_DECREF(val);
74} 74}
75 75
76static PyObject *get_handler(const char *handler_name)
77{
78 PyObject *handler;
79
80 handler = PyDict_GetItemString(main_dict, handler_name);
81 if (handler && !PyCallable_Check(handler))
82 return NULL;
83 return handler;
84}
85
86static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
87{
88 PyObject *retval;
89
90 retval = PyObject_CallObject(handler, args);
91 if (retval == NULL)
92 handler_call_die(die_msg);
93 Py_DECREF(retval);
94}
95
96static void try_call_object(const char *handler_name, PyObject *args)
97{
98 PyObject *handler;
99
100 handler = get_handler(handler_name);
101 if (handler)
102 call_object(handler, args, handler_name);
103}
104
76static void define_value(enum print_arg_type field_type, 105static void define_value(enum print_arg_type field_type,
77 const char *ev_name, 106 const char *ev_name,
78 const char *field_name, 107 const char *field_name,
@@ -80,7 +109,7 @@ static void define_value(enum print_arg_type field_type,
80 const char *field_str) 109 const char *field_str)
81{ 110{
82 const char *handler_name = "define_flag_value"; 111 const char *handler_name = "define_flag_value";
83 PyObject *handler, *t, *retval; 112 PyObject *t;
84 unsigned long long value; 113 unsigned long long value;
85 unsigned n = 0; 114 unsigned n = 0;
86 115
@@ -98,13 +127,7 @@ static void define_value(enum print_arg_type field_type,
98 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 127 PyTuple_SetItem(t, n++, PyInt_FromLong(value));
99 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 128 PyTuple_SetItem(t, n++, PyString_FromString(field_str));
100 129
101 handler = PyDict_GetItemString(main_dict, handler_name); 130 try_call_object(handler_name, t);
102 if (handler && PyCallable_Check(handler)) {
103 retval = PyObject_CallObject(handler, t);
104 if (retval == NULL)
105 handler_call_die(handler_name);
106 Py_DECREF(retval);
107 }
108 131
109 Py_DECREF(t); 132 Py_DECREF(t);
110} 133}
@@ -127,7 +150,7 @@ static void define_field(enum print_arg_type field_type,
127 const char *delim) 150 const char *delim)
128{ 151{
129 const char *handler_name = "define_flag_field"; 152 const char *handler_name = "define_flag_field";
130 PyObject *handler, *t, *retval; 153 PyObject *t;
131 unsigned n = 0; 154 unsigned n = 0;
132 155
133 if (field_type == PRINT_SYMBOL) 156 if (field_type == PRINT_SYMBOL)
@@ -145,13 +168,7 @@ static void define_field(enum print_arg_type field_type,
145 if (field_type == PRINT_FLAGS) 168 if (field_type == PRINT_FLAGS)
146 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 169 PyTuple_SetItem(t, n++, PyString_FromString(delim));
147 170
148 handler = PyDict_GetItemString(main_dict, handler_name); 171 try_call_object(handler_name, t);
149 if (handler && PyCallable_Check(handler)) {
150 retval = PyObject_CallObject(handler, t);
151 if (retval == NULL)
152 handler_call_die(handler_name);
153 Py_DECREF(retval);
154 }
155 172
156 Py_DECREF(t); 173 Py_DECREF(t);
157} 174}
@@ -362,7 +379,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
362 struct thread *thread, 379 struct thread *thread,
363 struct addr_location *al) 380 struct addr_location *al)
364{ 381{
365 PyObject *handler, *retval, *context, *t, *obj, *callchain; 382 PyObject *handler, *context, *t, *obj, *callchain;
366 PyObject *dict = NULL; 383 PyObject *dict = NULL;
367 static char handler_name[256]; 384 static char handler_name[256];
368 struct format_field *field; 385 struct format_field *field;
@@ -387,9 +404,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
387 404
388 sprintf(handler_name, "%s__%s", event->system, event->name); 405 sprintf(handler_name, "%s__%s", event->system, event->name);
389 406
390 handler = PyDict_GetItemString(main_dict, handler_name); 407 handler = get_handler(handler_name);
391 if (handler && !PyCallable_Check(handler))
392 handler = NULL;
393 if (!handler) { 408 if (!handler) {
394 dict = PyDict_New(); 409 dict = PyDict_New();
395 if (!dict) 410 if (!dict)
@@ -450,19 +465,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
450 Py_FatalError("error resizing Python tuple"); 465 Py_FatalError("error resizing Python tuple");
451 466
452 if (handler) { 467 if (handler) {
453 retval = PyObject_CallObject(handler, t); 468 call_object(handler, t, handler_name);
454 if (retval == NULL)
455 handler_call_die(handler_name);
456 Py_DECREF(retval);
457 } else { 469 } else {
458 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 470 try_call_object("trace_unhandled", t);
459 if (handler && PyCallable_Check(handler)) {
460
461 retval = PyObject_CallObject(handler, t);
462 if (retval == NULL)
463 handler_call_die("trace_unhandled");
464 Py_DECREF(retval);
465 }
466 Py_DECREF(dict); 471 Py_DECREF(dict);
467 } 472 }
468 473
@@ -474,7 +479,7 @@ static void python_process_general_event(struct perf_sample *sample,
474 struct thread *thread, 479 struct thread *thread,
475 struct addr_location *al) 480 struct addr_location *al)
476{ 481{
477 PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; 482 PyObject *handler, *t, *dict, *callchain, *dict_sample;
478 static char handler_name[64]; 483 static char handler_name[64];
479 unsigned n = 0; 484 unsigned n = 0;
480 485
@@ -496,8 +501,8 @@ static void python_process_general_event(struct perf_sample *sample,
496 501
497 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 502 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
498 503
499 handler = PyDict_GetItemString(main_dict, handler_name); 504 handler = get_handler(handler_name);
500 if (!handler || !PyCallable_Check(handler)) 505 if (!handler)
501 goto exit; 506 goto exit;
502 507
503 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 508 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
@@ -539,10 +544,7 @@ static void python_process_general_event(struct perf_sample *sample,
539 if (_PyTuple_Resize(&t, n) == -1) 544 if (_PyTuple_Resize(&t, n) == -1)
540 Py_FatalError("error resizing Python tuple"); 545 Py_FatalError("error resizing Python tuple");
541 546
542 retval = PyObject_CallObject(handler, t); 547 call_object(handler, t, handler_name);
543 if (retval == NULL)
544 handler_call_die(handler_name);
545 Py_DECREF(retval);
546exit: 548exit:
547 Py_DECREF(dict); 549 Py_DECREF(dict);
548 Py_DECREF(t); 550 Py_DECREF(t);
@@ -566,36 +568,24 @@ static void python_process_event(union perf_event *event __maybe_unused,
566 568
567static int run_start_sub(void) 569static int run_start_sub(void)
568{ 570{
569 PyObject *handler, *retval;
570 int err = 0;
571
572 main_module = PyImport_AddModule("__main__"); 571 main_module = PyImport_AddModule("__main__");
573 if (main_module == NULL) 572 if (main_module == NULL)
574 return -1; 573 return -1;
575 Py_INCREF(main_module); 574 Py_INCREF(main_module);
576 575
577 main_dict = PyModule_GetDict(main_module); 576 main_dict = PyModule_GetDict(main_module);
578 if (main_dict == NULL) { 577 if (main_dict == NULL)
579 err = -1;
580 goto error; 578 goto error;
581 }
582 Py_INCREF(main_dict); 579 Py_INCREF(main_dict);
583 580
584 handler = PyDict_GetItemString(main_dict, "trace_begin"); 581 try_call_object("trace_begin", NULL);
585 if (handler == NULL || !PyCallable_Check(handler))
586 goto out;
587 582
588 retval = PyObject_CallObject(handler, NULL); 583 return 0;
589 if (retval == NULL)
590 handler_call_die("trace_begin");
591 584
592 Py_DECREF(retval);
593 return err;
594error: 585error:
595 Py_XDECREF(main_dict); 586 Py_XDECREF(main_dict);
596 Py_XDECREF(main_module); 587 Py_XDECREF(main_module);
597out: 588 return -1;
598 return err;
599} 589}
600 590
601/* 591/*
@@ -649,28 +639,23 @@ error:
649 return err; 639 return err;
650} 640}
651 641
642static int python_flush_script(void)
643{
644 return 0;
645}
646
652/* 647/*
653 * Stop trace script 648 * Stop trace script
654 */ 649 */
655static int python_stop_script(void) 650static int python_stop_script(void)
656{ 651{
657 PyObject *handler, *retval; 652 try_call_object("trace_end", NULL);
658 int err = 0;
659 653
660 handler = PyDict_GetItemString(main_dict, "trace_end");
661 if (handler == NULL || !PyCallable_Check(handler))
662 goto out;
663
664 retval = PyObject_CallObject(handler, NULL);
665 if (retval == NULL)
666 handler_call_die("trace_end");
667 Py_DECREF(retval);
668out:
669 Py_XDECREF(main_dict); 654 Py_XDECREF(main_dict);
670 Py_XDECREF(main_module); 655 Py_XDECREF(main_module);
671 Py_Finalize(); 656 Py_Finalize();
672 657
673 return err; 658 return 0;
674} 659}
675 660
676static int python_generate_script(struct pevent *pevent, const char *outfile) 661static int python_generate_script(struct pevent *pevent, const char *outfile)
@@ -843,6 +828,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
843struct scripting_ops python_scripting_ops = { 828struct scripting_ops python_scripting_ops = {
844 .name = "Python", 829 .name = "Python",
845 .start_script = python_start_script, 830 .start_script = python_start_script,
831 .flush_script = python_flush_script,
846 .stop_script = python_stop_script, 832 .stop_script = python_stop_script,
847 .process_event = python_process_event, 833 .process_event = python_process_event,
848 .generate_script = python_generate_script, 834 .generate_script = python_generate_script,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 88dfef70c13d..883406f4b381 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
14#include "util.h" 14#include "util.h"
15#include "cpumap.h" 15#include "cpumap.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h"
17 18
18static int perf_session__open(struct perf_session *session) 19static int perf_session__open(struct perf_session *session)
19{ 20{
@@ -66,6 +67,25 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session)
66 machines__destroy_kernel_maps(&session->machines); 67 machines__destroy_kernel_maps(&session->machines);
67} 68}
68 69
70static bool perf_session__has_comm_exec(struct perf_session *session)
71{
72 struct perf_evsel *evsel;
73
74 evlist__for_each(session->evlist, evsel) {
75 if (evsel->attr.comm_exec)
76 return true;
77 }
78
79 return false;
80}
81
82static void perf_session__set_comm_exec(struct perf_session *session)
83{
84 bool comm_exec = perf_session__has_comm_exec(session);
85
86 machines__set_comm_exec(&session->machines, comm_exec);
87}
88
69struct perf_session *perf_session__new(struct perf_data_file *file, 89struct perf_session *perf_session__new(struct perf_data_file *file,
70 bool repipe, struct perf_tool *tool) 90 bool repipe, struct perf_tool *tool)
71{ 91{
@@ -75,9 +95,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
75 goto out; 95 goto out;
76 96
77 session->repipe = repipe; 97 session->repipe = repipe;
78 INIT_LIST_HEAD(&session->ordered_samples.samples); 98 ordered_events__init(&session->ordered_events);
79 INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
80 INIT_LIST_HEAD(&session->ordered_samples.to_free);
81 machines__init(&session->machines); 99 machines__init(&session->machines);
82 100
83 if (file) { 101 if (file) {
@@ -91,6 +109,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
91 goto out_close; 109 goto out_close;
92 110
93 perf_session__set_id_hdr_size(session); 111 perf_session__set_id_hdr_size(session);
112 perf_session__set_comm_exec(session);
94 } 113 }
95 } 114 }
96 115
@@ -100,13 +119,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
100 * kernel MMAP event, in perf_event__process_mmap(). 119 * kernel MMAP event, in perf_event__process_mmap().
101 */ 120 */
102 if (perf_session__create_kernel_maps(session) < 0) 121 if (perf_session__create_kernel_maps(session) < 0)
103 goto out_delete; 122 pr_warning("Cannot read kernel map\n");
104 } 123 }
105 124
106 if (tool && tool->ordering_requires_timestamps && 125 if (tool && tool->ordering_requires_timestamps &&
107 tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { 126 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
108 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 127 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
109 tool->ordered_samples = false; 128 tool->ordered_events = false;
110 } 129 }
111 130
112 return session; 131 return session;
@@ -238,7 +257,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
238 if (tool->build_id == NULL) 257 if (tool->build_id == NULL)
239 tool->build_id = process_finished_round_stub; 258 tool->build_id = process_finished_round_stub;
240 if (tool->finished_round == NULL) { 259 if (tool->finished_round == NULL) {
241 if (tool->ordered_samples) 260 if (tool->ordered_events)
242 tool->finished_round = process_finished_round; 261 tool->finished_round = process_finished_round;
243 else 262 else
244 tool->finished_round = process_finished_round_stub; 263 tool->finished_round = process_finished_round_stub;
@@ -444,87 +463,6 @@ static perf_event__swap_op perf_event__swap_ops[] = {
444 [PERF_RECORD_HEADER_MAX] = NULL, 463 [PERF_RECORD_HEADER_MAX] = NULL,
445}; 464};
446 465
447struct sample_queue {
448 u64 timestamp;
449 u64 file_offset;
450 union perf_event *event;
451 struct list_head list;
452};
453
454static void perf_session_free_sample_buffers(struct perf_session *session)
455{
456 struct ordered_samples *os = &session->ordered_samples;
457
458 while (!list_empty(&os->to_free)) {
459 struct sample_queue *sq;
460
461 sq = list_entry(os->to_free.next, struct sample_queue, list);
462 list_del(&sq->list);
463 free(sq);
464 }
465}
466
467static int perf_session_deliver_event(struct perf_session *session,
468 union perf_event *event,
469 struct perf_sample *sample,
470 struct perf_tool *tool,
471 u64 file_offset);
472
473static int flush_sample_queue(struct perf_session *s,
474 struct perf_tool *tool)
475{
476 struct ordered_samples *os = &s->ordered_samples;
477 struct list_head *head = &os->samples;
478 struct sample_queue *tmp, *iter;
479 struct perf_sample sample;
480 u64 limit = os->next_flush;
481 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
482 bool show_progress = limit == ULLONG_MAX;
483 struct ui_progress prog;
484 int ret;
485
486 if (!tool->ordered_samples || !limit)
487 return 0;
488
489 if (show_progress)
490 ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
491
492 list_for_each_entry_safe(iter, tmp, head, list) {
493 if (session_done())
494 return 0;
495
496 if (iter->timestamp > limit)
497 break;
498
499 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
500 if (ret)
501 pr_err("Can't parse sample, err = %d\n", ret);
502 else {
503 ret = perf_session_deliver_event(s, iter->event, &sample, tool,
504 iter->file_offset);
505 if (ret)
506 return ret;
507 }
508
509 os->last_flush = iter->timestamp;
510 list_del(&iter->list);
511 list_add(&iter->list, &os->sample_cache);
512 os->nr_samples--;
513
514 if (show_progress)
515 ui_progress__update(&prog, 1);
516 }
517
518 if (list_empty(head)) {
519 os->last_sample = NULL;
520 } else if (last_ts <= limit) {
521 os->last_sample =
522 list_entry(head->prev, struct sample_queue, list);
523 }
524
525 return 0;
526}
527
528/* 466/*
529 * When perf record finishes a pass on every buffers, it records this pseudo 467 * When perf record finishes a pass on every buffers, it records this pseudo
530 * event. 468 * event.
@@ -568,99 +506,43 @@ static int process_finished_round(struct perf_tool *tool,
568 union perf_event *event __maybe_unused, 506 union perf_event *event __maybe_unused,
569 struct perf_session *session) 507 struct perf_session *session)
570{ 508{
571 int ret = flush_sample_queue(session, tool); 509 return ordered_events__flush(session, tool, OE_FLUSH__ROUND);
572 if (!ret)
573 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
574
575 return ret;
576}
577
578/* The queue is ordered by time */
579static void __queue_event(struct sample_queue *new, struct perf_session *s)
580{
581 struct ordered_samples *os = &s->ordered_samples;
582 struct sample_queue *sample = os->last_sample;
583 u64 timestamp = new->timestamp;
584 struct list_head *p;
585
586 ++os->nr_samples;
587 os->last_sample = new;
588
589 if (!sample) {
590 list_add(&new->list, &os->samples);
591 os->max_timestamp = timestamp;
592 return;
593 }
594
595 /*
596 * last_sample might point to some random place in the list as it's
597 * the last queued event. We expect that the new event is close to
598 * this.
599 */
600 if (sample->timestamp <= timestamp) {
601 while (sample->timestamp <= timestamp) {
602 p = sample->list.next;
603 if (p == &os->samples) {
604 list_add_tail(&new->list, &os->samples);
605 os->max_timestamp = timestamp;
606 return;
607 }
608 sample = list_entry(p, struct sample_queue, list);
609 }
610 list_add_tail(&new->list, &sample->list);
611 } else {
612 while (sample->timestamp > timestamp) {
613 p = sample->list.prev;
614 if (p == &os->samples) {
615 list_add(&new->list, &os->samples);
616 return;
617 }
618 sample = list_entry(p, struct sample_queue, list);
619 }
620 list_add(&new->list, &sample->list);
621 }
622} 510}
623 511
624#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
625
626int perf_session_queue_event(struct perf_session *s, union perf_event *event, 512int perf_session_queue_event(struct perf_session *s, union perf_event *event,
627 struct perf_sample *sample, u64 file_offset) 513 struct perf_tool *tool, struct perf_sample *sample,
514 u64 file_offset)
628{ 515{
629 struct ordered_samples *os = &s->ordered_samples; 516 struct ordered_events *oe = &s->ordered_events;
630 struct list_head *sc = &os->sample_cache;
631 u64 timestamp = sample->time; 517 u64 timestamp = sample->time;
632 struct sample_queue *new; 518 struct ordered_event *new;
633 519
634 if (!timestamp || timestamp == ~0ULL) 520 if (!timestamp || timestamp == ~0ULL)
635 return -ETIME; 521 return -ETIME;
636 522
637 if (timestamp < s->ordered_samples.last_flush) { 523 if (timestamp < oe->last_flush) {
638 printf("Warning: Timestamp below last timeslice flush\n"); 524 WARN_ONCE(1, "Timestamp below last timeslice flush\n");
639 return -EINVAL; 525
526 pr_oe_time(timestamp, "out of order event");
527 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
528 oe->last_flush_type);
529
530 /* We could get out of order messages after forced flush. */
531 if (oe->last_flush_type != OE_FLUSH__HALF)
532 return -EINVAL;
640 } 533 }
641 534
642 if (!list_empty(sc)) { 535 new = ordered_events__new(oe, timestamp);
643 new = list_entry(sc->next, struct sample_queue, list); 536 if (!new) {
644 list_del(&new->list); 537 ordered_events__flush(s, tool, OE_FLUSH__HALF);
645 } else if (os->sample_buffer) { 538 new = ordered_events__new(oe, timestamp);
646 new = os->sample_buffer + os->sample_buffer_idx;
647 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
648 os->sample_buffer = NULL;
649 } else {
650 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
651 if (!os->sample_buffer)
652 return -ENOMEM;
653 list_add(&os->sample_buffer->list, &os->to_free);
654 os->sample_buffer_idx = 2;
655 new = os->sample_buffer + 1;
656 } 539 }
657 540
658 new->timestamp = timestamp; 541 if (!new)
542 return -ENOMEM;
543
659 new->file_offset = file_offset; 544 new->file_offset = file_offset;
660 new->event = event; 545 new->event = event;
661
662 __queue_event(new, s);
663
664 return 0; 546 return 0;
665} 547}
666 548
@@ -920,11 +802,10 @@ perf_session__deliver_sample(struct perf_session *session,
920 &sample->read.one, machine); 802 &sample->read.one, machine);
921} 803}
922 804
923static int perf_session_deliver_event(struct perf_session *session, 805int perf_session__deliver_event(struct perf_session *session,
924 union perf_event *event, 806 union perf_event *event,
925 struct perf_sample *sample, 807 struct perf_sample *sample,
926 struct perf_tool *tool, 808 struct perf_tool *tool, u64 file_offset)
927 u64 file_offset)
928{ 809{
929 struct perf_evsel *evsel; 810 struct perf_evsel *evsel;
930 struct machine *machine; 811 struct machine *machine;
@@ -1005,8 +886,10 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1005 switch (event->header.type) { 886 switch (event->header.type) {
1006 case PERF_RECORD_HEADER_ATTR: 887 case PERF_RECORD_HEADER_ATTR:
1007 err = tool->attr(tool, event, &session->evlist); 888 err = tool->attr(tool, event, &session->evlist);
1008 if (err == 0) 889 if (err == 0) {
1009 perf_session__set_id_hdr_size(session); 890 perf_session__set_id_hdr_size(session);
891 perf_session__set_comm_exec(session);
892 }
1010 return err; 893 return err;
1011 case PERF_RECORD_HEADER_EVENT_TYPE: 894 case PERF_RECORD_HEADER_EVENT_TYPE:
1012 /* 895 /*
@@ -1036,6 +919,61 @@ static void event_swap(union perf_event *event, bool sample_id_all)
1036 swap(event, sample_id_all); 919 swap(event, sample_id_all);
1037} 920}
1038 921
922int perf_session__peek_event(struct perf_session *session, off_t file_offset,
923 void *buf, size_t buf_sz,
924 union perf_event **event_ptr,
925 struct perf_sample *sample)
926{
927 union perf_event *event;
928 size_t hdr_sz, rest;
929 int fd;
930
931 if (session->one_mmap && !session->header.needs_swap) {
932 event = file_offset - session->one_mmap_offset +
933 session->one_mmap_addr;
934 goto out_parse_sample;
935 }
936
937 if (perf_data_file__is_pipe(session->file))
938 return -1;
939
940 fd = perf_data_file__fd(session->file);
941 hdr_sz = sizeof(struct perf_event_header);
942
943 if (buf_sz < hdr_sz)
944 return -1;
945
946 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
947 readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz)
948 return -1;
949
950 event = (union perf_event *)buf;
951
952 if (session->header.needs_swap)
953 perf_event_header__bswap(&event->header);
954
955 if (event->header.size < hdr_sz)
956 return -1;
957
958 rest = event->header.size - hdr_sz;
959
960 if (readn(fd, &buf, rest) != (ssize_t)rest)
961 return -1;
962
963 if (session->header.needs_swap)
964 event_swap(event, perf_evlist__sample_id_all(session->evlist));
965
966out_parse_sample:
967
968 if (sample && event->header.type < PERF_RECORD_USER_TYPE_START &&
969 perf_evlist__parse_sample(session->evlist, event, sample))
970 return -1;
971
972 *event_ptr = event;
973
974 return 0;
975}
976
1039static s64 perf_session__process_event(struct perf_session *session, 977static s64 perf_session__process_event(struct perf_session *session,
1040 union perf_event *event, 978 union perf_event *event,
1041 struct perf_tool *tool, 979 struct perf_tool *tool,
@@ -1062,15 +1000,15 @@ static s64 perf_session__process_event(struct perf_session *session,
1062 if (ret) 1000 if (ret)
1063 return ret; 1001 return ret;
1064 1002
1065 if (tool->ordered_samples) { 1003 if (tool->ordered_events) {
1066 ret = perf_session_queue_event(session, event, &sample, 1004 ret = perf_session_queue_event(session, event, tool, &sample,
1067 file_offset); 1005 file_offset);
1068 if (ret != -ETIME) 1006 if (ret != -ETIME)
1069 return ret; 1007 return ret;
1070 } 1008 }
1071 1009
1072 return perf_session_deliver_event(session, event, &sample, tool, 1010 return perf_session__deliver_event(session, event, &sample, tool,
1073 file_offset); 1011 file_offset);
1074} 1012}
1075 1013
1076void perf_event_header__bswap(struct perf_event_header *hdr) 1014void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1222,12 +1160,11 @@ more:
1222 goto more; 1160 goto more;
1223done: 1161done:
1224 /* do the final flush for ordered samples */ 1162 /* do the final flush for ordered samples */
1225 session->ordered_samples.next_flush = ULLONG_MAX; 1163 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1226 err = flush_sample_queue(session, tool);
1227out_err: 1164out_err:
1228 free(buf); 1165 free(buf);
1229 perf_session__warn_about_errors(session, tool); 1166 perf_session__warn_about_errors(session, tool);
1230 perf_session_free_sample_buffers(session); 1167 ordered_events__free(&session->ordered_events);
1231 return err; 1168 return err;
1232} 1169}
1233 1170
@@ -1368,12 +1305,11 @@ more:
1368 1305
1369out: 1306out:
1370 /* do the final flush for ordered samples */ 1307 /* do the final flush for ordered samples */
1371 session->ordered_samples.next_flush = ULLONG_MAX; 1308 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1372 err = flush_sample_queue(session, tool);
1373out_err: 1309out_err:
1374 ui_progress__finish(); 1310 ui_progress__finish();
1375 perf_session__warn_about_errors(session, tool); 1311 perf_session__warn_about_errors(session, tool);
1376 perf_session_free_sample_buffers(session); 1312 ordered_events__free(&session->ordered_events);
1377 session->one_mmap = false; 1313 session->one_mmap = false;
1378 return err; 1314 return err;
1379} 1315}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0321013bd9fd..ffb440462008 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -9,26 +9,13 @@
9#include "symbol.h" 9#include "symbol.h"
10#include "thread.h" 10#include "thread.h"
11#include "data.h" 11#include "data.h"
12#include "ordered-events.h"
12#include <linux/rbtree.h> 13#include <linux/rbtree.h>
13#include <linux/perf_event.h> 14#include <linux/perf_event.h>
14 15
15struct sample_queue;
16struct ip_callchain; 16struct ip_callchain;
17struct thread; 17struct thread;
18 18
19struct ordered_samples {
20 u64 last_flush;
21 u64 next_flush;
22 u64 max_timestamp;
23 struct list_head samples;
24 struct list_head sample_cache;
25 struct list_head to_free;
26 struct sample_queue *sample_buffer;
27 struct sample_queue *last_sample;
28 int sample_buffer_idx;
29 unsigned int nr_samples;
30};
31
32struct perf_session { 19struct perf_session {
33 struct perf_header header; 20 struct perf_header header;
34 struct machines machines; 21 struct machines machines;
@@ -39,7 +26,7 @@ struct perf_session {
39 bool one_mmap; 26 bool one_mmap;
40 void *one_mmap_addr; 27 void *one_mmap_addr;
41 u64 one_mmap_offset; 28 u64 one_mmap_offset;
42 struct ordered_samples ordered_samples; 29 struct ordered_events ordered_events;
43 struct perf_data_file *file; 30 struct perf_data_file *file;
44}; 31};
45 32
@@ -58,6 +45,11 @@ void perf_session__delete(struct perf_session *session);
58 45
59void perf_event_header__bswap(struct perf_event_header *hdr); 46void perf_event_header__bswap(struct perf_event_header *hdr);
60 47
48int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 void *buf, size_t buf_sz,
50 union perf_event **event_ptr,
51 struct perf_sample *sample);
52
61int __perf_session__process_events(struct perf_session *session, 53int __perf_session__process_events(struct perf_session *session,
62 u64 data_offset, u64 data_size, u64 size, 54 u64 data_offset, u64 data_size, u64 size,
63 struct perf_tool *tool); 55 struct perf_tool *tool);
@@ -65,10 +57,16 @@ int perf_session__process_events(struct perf_session *session,
65 struct perf_tool *tool); 57 struct perf_tool *tool);
66 58
67int perf_session_queue_event(struct perf_session *s, union perf_event *event, 59int perf_session_queue_event(struct perf_session *s, union perf_event *event,
68 struct perf_sample *sample, u64 file_offset); 60 struct perf_tool *tool, struct perf_sample *sample,
61 u64 file_offset);
69 62
70void perf_tool__fill_defaults(struct perf_tool *tool); 63void perf_tool__fill_defaults(struct perf_tool *tool);
71 64
65int perf_session__deliver_event(struct perf_session *session,
66 union perf_event *event,
67 struct perf_sample *sample,
68 struct perf_tool *tool, u64 file_offset);
69
72int perf_session__resolve_callchain(struct perf_session *session, 70int perf_session__resolve_callchain(struct perf_session *session,
73 struct perf_evsel *evsel, 71 struct perf_evsel *evsel,
74 struct thread *thread, 72 struct thread *thread,
@@ -128,5 +126,5 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
128 126
129extern volatile int session_done; 127extern volatile int session_done;
130 128
131#define session_done() (*(volatile int *)(&session_done)) 129#define session_done() ACCESS_ONCE(session_done)
132#endif /* __PERF_SESSION_H */ 130#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 14e5a039bc45..289df9d1e65a 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -70,12 +70,14 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
70 size_t size, unsigned int width) 70 size_t size, unsigned int width)
71{ 71{
72 const char *comm = thread__comm_str(he->thread); 72 const char *comm = thread__comm_str(he->thread);
73 return repsep_snprintf(bf, size, "%*s:%5d", width - 6, 73
74 comm ?: "", he->thread->tid); 74 width = max(7U, width) - 6;
75 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
76 width, width, comm ?: "");
75} 77}
76 78
77struct sort_entry sort_thread = { 79struct sort_entry sort_thread = {
78 .se_header = "Command: Pid", 80 .se_header = " Pid:Command",
79 .se_cmp = sort__thread_cmp, 81 .se_cmp = sort__thread_cmp,
80 .se_snprintf = hist_entry__thread_snprintf, 82 .se_snprintf = hist_entry__thread_snprintf,
81 .se_width_idx = HISTC_THREAD, 83 .se_width_idx = HISTC_THREAD,
@@ -106,7 +108,7 @@ sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
106static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, 108static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
107 size_t size, unsigned int width) 109 size_t size, unsigned int width)
108{ 110{
109 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm)); 111 return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
110} 112}
111 113
112struct sort_entry sort_comm = { 114struct sort_entry sort_comm = {
@@ -152,10 +154,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
152 if (map && map->dso) { 154 if (map && map->dso) {
153 const char *dso_name = !verbose ? map->dso->short_name : 155 const char *dso_name = !verbose ? map->dso->short_name :
154 map->dso->long_name; 156 map->dso->long_name;
155 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 157 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
156 } 158 }
157 159
158 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 160 return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
159} 161}
160 162
161static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, 163static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
@@ -257,7 +259,10 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
257 width - ret, ""); 259 width - ret, "");
258 } 260 }
259 261
260 return ret; 262 if (ret > width)
263 bf[width] = '\0';
264
265 return width;
261} 266}
262 267
263static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, 268static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
@@ -302,10 +307,9 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
302} 307}
303 308
304static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 309static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
305 size_t size, 310 size_t size, unsigned int width)
306 unsigned int width __maybe_unused)
307{ 311{
308 return repsep_snprintf(bf, size, "%s", he->srcline); 312 return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline);
309} 313}
310 314
311struct sort_entry sort_srcline = { 315struct sort_entry sort_srcline = {
@@ -332,7 +336,7 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
332static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, 336static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
333 size_t size, unsigned int width) 337 size_t size, unsigned int width)
334{ 338{
335 return repsep_snprintf(bf, size, "%-*s", width, 339 return repsep_snprintf(bf, size, "%-*.*s", width, width,
336 he->parent ? he->parent->name : "[other]"); 340 he->parent ? he->parent->name : "[other]");
337} 341}
338 342
@@ -354,7 +358,7 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
354static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, 358static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
355 size_t size, unsigned int width) 359 size_t size, unsigned int width)
356{ 360{
357 return repsep_snprintf(bf, size, "%*d", width, he->cpu); 361 return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
358} 362}
359 363
360struct sort_entry sort_cpu = { 364struct sort_entry sort_cpu = {
@@ -484,7 +488,7 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
484 else if (he->branch_info->flags.mispred) 488 else if (he->branch_info->flags.mispred)
485 out = "Y"; 489 out = "Y";
486 490
487 return repsep_snprintf(bf, size, "%-*s", width, out); 491 return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
488} 492}
489 493
490/* --sort daddr_sym */ 494/* --sort daddr_sym */
@@ -1194,7 +1198,7 @@ bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1194 return hse_a->se == hse_b->se; 1198 return hse_a->se == hse_b->se;
1195} 1199}
1196 1200
1197void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) 1201void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1198{ 1202{
1199 struct hpp_sort_entry *hse; 1203 struct hpp_sort_entry *hse;
1200 1204
@@ -1202,20 +1206,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1202 return; 1206 return;
1203 1207
1204 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1208 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1205 hists__new_col_len(hists, hse->se->se_width_idx, 1209 hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
1206 strlen(hse->se->se_header));
1207} 1210}
1208 1211
1209static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1212static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1210 struct perf_evsel *evsel) 1213 struct perf_evsel *evsel)
1211{ 1214{
1212 struct hpp_sort_entry *hse; 1215 struct hpp_sort_entry *hse;
1213 size_t len; 1216 size_t len = fmt->user_len;
1214 1217
1215 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1218 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1216 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1217 1219
1218 return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header); 1220 if (!len)
1221 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1222
1223 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1219} 1224}
1220 1225
1221static int __sort__hpp_width(struct perf_hpp_fmt *fmt, 1226static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
@@ -1223,20 +1228,26 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1223 struct perf_evsel *evsel) 1228 struct perf_evsel *evsel)
1224{ 1229{
1225 struct hpp_sort_entry *hse; 1230 struct hpp_sort_entry *hse;
1231 size_t len = fmt->user_len;
1226 1232
1227 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1233 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1228 1234
1229 return hists__col_len(&evsel->hists, hse->se->se_width_idx); 1235 if (!len)
1236 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1237
1238 return len;
1230} 1239}
1231 1240
1232static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1241static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1233 struct hist_entry *he) 1242 struct hist_entry *he)
1234{ 1243{
1235 struct hpp_sort_entry *hse; 1244 struct hpp_sort_entry *hse;
1236 size_t len; 1245 size_t len = fmt->user_len;
1237 1246
1238 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1247 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1239 len = hists__col_len(he->hists, hse->se->se_width_idx); 1248
1249 if (!len)
1250 len = hists__col_len(he->hists, hse->se->se_width_idx);
1240 1251
1241 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 1252 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1242} 1253}
@@ -1253,6 +1264,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1253 } 1264 }
1254 1265
1255 hse->se = sd->entry; 1266 hse->se = sd->entry;
1267 hse->hpp.name = sd->entry->se_header;
1256 hse->hpp.header = __sort__hpp_header; 1268 hse->hpp.header = __sort__hpp_header;
1257 hse->hpp.width = __sort__hpp_width; 1269 hse->hpp.width = __sort__hpp_width;
1258 hse->hpp.entry = __sort__hpp_entry; 1270 hse->hpp.entry = __sort__hpp_entry;
@@ -1265,6 +1277,8 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1265 INIT_LIST_HEAD(&hse->hpp.list); 1277 INIT_LIST_HEAD(&hse->hpp.list);
1266 INIT_LIST_HEAD(&hse->hpp.sort_list); 1278 INIT_LIST_HEAD(&hse->hpp.sort_list);
1267 hse->hpp.elide = false; 1279 hse->hpp.elide = false;
1280 hse->hpp.len = 0;
1281 hse->hpp.user_len = 0;
1268 1282
1269 return hse; 1283 return hse;
1270} 1284}
@@ -1432,14 +1446,49 @@ static const char *get_default_sort_order(void)
1432 return default_sort_orders[sort__mode]; 1446 return default_sort_orders[sort__mode];
1433} 1447}
1434 1448
1449static int setup_sort_order(void)
1450{
1451 char *new_sort_order;
1452
1453 /*
1454 * Append '+'-prefixed sort order to the default sort
1455 * order string.
1456 */
1457 if (!sort_order || is_strict_order(sort_order))
1458 return 0;
1459
1460 if (sort_order[1] == '\0') {
1461 error("Invalid --sort key: `+'");
1462 return -EINVAL;
1463 }
1464
1465 /*
1466 * We allocate new sort_order string, but we never free it,
1467 * because it's checked over the rest of the code.
1468 */
1469 if (asprintf(&new_sort_order, "%s,%s",
1470 get_default_sort_order(), sort_order + 1) < 0) {
1471 error("Not enough memory to set up --sort");
1472 return -ENOMEM;
1473 }
1474
1475 sort_order = new_sort_order;
1476 return 0;
1477}
1478
1435static int __setup_sorting(void) 1479static int __setup_sorting(void)
1436{ 1480{
1437 char *tmp, *tok, *str; 1481 char *tmp, *tok, *str;
1438 const char *sort_keys = sort_order; 1482 const char *sort_keys;
1439 int ret = 0; 1483 int ret = 0;
1440 1484
1485 ret = setup_sort_order();
1486 if (ret)
1487 return ret;
1488
1489 sort_keys = sort_order;
1441 if (sort_keys == NULL) { 1490 if (sort_keys == NULL) {
1442 if (field_order) { 1491 if (is_strict_order(field_order)) {
1443 /* 1492 /*
1444 * If user specified field order but no sort order, 1493 * If user specified field order but no sort order,
1445 * we'll honor it and not add default sort orders. 1494 * we'll honor it and not add default sort orders.
@@ -1625,23 +1674,36 @@ static void reset_dimensions(void)
1625 memory_sort_dimensions[i].taken = 0; 1674 memory_sort_dimensions[i].taken = 0;
1626} 1675}
1627 1676
1677bool is_strict_order(const char *order)
1678{
1679 return order && (*order != '+');
1680}
1681
1628static int __setup_output_field(void) 1682static int __setup_output_field(void)
1629{ 1683{
1630 char *tmp, *tok, *str; 1684 char *tmp, *tok, *str, *strp;
1631 int ret = 0; 1685 int ret = -EINVAL;
1632 1686
1633 if (field_order == NULL) 1687 if (field_order == NULL)
1634 return 0; 1688 return 0;
1635 1689
1636 reset_dimensions(); 1690 reset_dimensions();
1637 1691
1638 str = strdup(field_order); 1692 strp = str = strdup(field_order);
1639 if (str == NULL) { 1693 if (str == NULL) {
1640 error("Not enough memory to setup output fields"); 1694 error("Not enough memory to setup output fields");
1641 return -ENOMEM; 1695 return -ENOMEM;
1642 } 1696 }
1643 1697
1644 for (tok = strtok_r(str, ", ", &tmp); 1698 if (!is_strict_order(field_order))
1699 strp++;
1700
1701 if (!strlen(strp)) {
1702 error("Invalid --fields key: `+'");
1703 goto out;
1704 }
1705
1706 for (tok = strtok_r(strp, ", ", &tmp);
1645 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1707 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1646 ret = output_field_add(tok); 1708 ret = output_field_add(tok);
1647 if (ret == -EINVAL) { 1709 if (ret == -EINVAL) {
@@ -1653,6 +1715,7 @@ static int __setup_output_field(void)
1653 } 1715 }
1654 } 1716 }
1655 1717
1718out:
1656 free(str); 1719 free(str);
1657 return ret; 1720 return ret;
1658} 1721}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 041f0c9cea2b..c03e4ff8beff 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -218,4 +218,5 @@ void perf_hpp__set_elide(int idx, bool elide);
218 218
219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
220 220
221bool is_strict_order(const char *order);
221#endif /* __PERF_SORT_H */ 222#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index d75349979e65..1e23a5bfb044 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include "machine.h"
9#include "vdso.h" 10#include "vdso.h"
10#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
11#include "debug.h" 12#include "debug.h"
@@ -680,6 +681,11 @@ static u64 ref_reloc(struct kmap *kmap)
680 return 0; 681 return 0;
681} 682}
682 683
684static bool want_demangle(bool is_kernel_sym)
685{
686 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
687}
688
683int dso__load_sym(struct dso *dso, struct map *map, 689int dso__load_sym(struct dso *dso, struct map *map,
684 struct symsrc *syms_ss, struct symsrc *runtime_ss, 690 struct symsrc *syms_ss, struct symsrc *runtime_ss,
685 symbol_filter_t filter, int kmodule) 691 symbol_filter_t filter, int kmodule)
@@ -712,6 +718,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
712 symbols__delete(&dso->symbols[map->type]); 718 symbols__delete(&dso->symbols[map->type]);
713 719
714 if (!syms_ss->symtab) { 720 if (!syms_ss->symtab) {
721 /*
722 * If the vmlinux is stripped, fail so we will fall back
723 * to using kallsyms. The vmlinux runtime symbols aren't
724 * of much use.
725 */
726 if (dso->kernel)
727 goto out_elf_end;
728
715 syms_ss->symtab = syms_ss->dynsym; 729 syms_ss->symtab = syms_ss->dynsym;
716 syms_ss->symshdr = syms_ss->dynshdr; 730 syms_ss->symshdr = syms_ss->dynshdr;
717 } 731 }
@@ -736,7 +750,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
736 if (symstrs == NULL) 750 if (symstrs == NULL)
737 goto out_elf_end; 751 goto out_elf_end;
738 752
739 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 753 sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx);
740 if (sec_strndx == NULL) 754 if (sec_strndx == NULL)
741 goto out_elf_end; 755 goto out_elf_end;
742 756
@@ -916,7 +930,11 @@ int dso__load_sym(struct dso *dso, struct map *map,
916 } 930 }
917 curr_dso->symtab_type = dso->symtab_type; 931 curr_dso->symtab_type = dso->symtab_type;
918 map_groups__insert(kmap->kmaps, curr_map); 932 map_groups__insert(kmap->kmaps, curr_map);
919 dsos__add(&dso->node, curr_dso); 933 /*
934 * The new DSO should go to the kernel DSOS
935 */
936 dsos__add(&map->groups->machine->kernel_dsos,
937 curr_dso);
920 dso__set_loaded(curr_dso, map->type); 938 dso__set_loaded(curr_dso, map->type);
921 } else 939 } else
922 curr_dso = curr_map->dso; 940 curr_dso = curr_map->dso;
@@ -938,9 +956,12 @@ new_symbol:
938 * DWARF DW_compile_unit has this, but we don't always have access 956 * DWARF DW_compile_unit has this, but we don't always have access
939 * to it... 957 * to it...
940 */ 958 */
941 if (symbol_conf.demangle) { 959 if (want_demangle(dso->kernel || kmodule)) {
942 demangled = bfd_demangle(NULL, elf_name, 960 int demangle_flags = DMGL_NO_OPTS;
943 DMGL_PARAMS | DMGL_ANSI); 961 if (verbose)
962 demangle_flags = DMGL_PARAMS | DMGL_ANSI;
963
964 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
944 if (demangled != NULL) 965 if (demangled != NULL)
945 elf_name = demangled; 966 elf_name = demangled;
946 } 967 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index eb06746b06b2..be84f7a9838b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,6 +15,7 @@
15#include "machine.h" 15#include "machine.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
18#include "header.h"
18 19
19#include <elf.h> 20#include <elf.h>
20#include <limits.h> 21#include <limits.h>
@@ -33,6 +34,7 @@ struct symbol_conf symbol_conf = {
33 .try_vmlinux_path = true, 34 .try_vmlinux_path = true,
34 .annotate_src = true, 35 .annotate_src = true,
35 .demangle = true, 36 .demangle = true,
37 .demangle_kernel = false,
36 .cumulate_callchain = true, 38 .cumulate_callchain = true,
37 .show_hist_headers = true, 39 .show_hist_headers = true,
38 .symfs = "", 40 .symfs = "",
@@ -523,10 +525,15 @@ struct process_kallsyms_args {
523 struct dso *dso; 525 struct dso *dso;
524}; 526};
525 527
528/*
529 * These are symbols in the kernel image, so make sure that
530 * sym is from a kernel DSO.
531 */
526bool symbol__is_idle(struct symbol *sym) 532bool symbol__is_idle(struct symbol *sym)
527{ 533{
528 const char * const idle_symbols[] = { 534 const char * const idle_symbols[] = {
529 "cpu_idle", 535 "cpu_idle",
536 "cpu_startup_entry",
530 "intel_idle", 537 "intel_idle",
531 "default_idle", 538 "default_idle",
532 "native_safe_halt", 539 "native_safe_halt",
@@ -1468,8 +1475,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1468 if (vmlinux[0] == '/') 1475 if (vmlinux[0] == '/')
1469 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux); 1476 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux);
1470 else 1477 else
1471 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1478 symbol__join_symfs(symfs_vmlinux, vmlinux);
1472 symbol_conf.symfs, vmlinux);
1473 1479
1474 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1480 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1475 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1481 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
@@ -1745,12 +1751,13 @@ static void vmlinux_path__exit(void)
1745 zfree(&vmlinux_path); 1751 zfree(&vmlinux_path);
1746} 1752}
1747 1753
1748static int vmlinux_path__init(void) 1754static int vmlinux_path__init(struct perf_session_env *env)
1749{ 1755{
1750 struct utsname uts; 1756 struct utsname uts;
1751 char bf[PATH_MAX]; 1757 char bf[PATH_MAX];
1758 char *kernel_version;
1752 1759
1753 vmlinux_path = malloc(sizeof(char *) * 5); 1760 vmlinux_path = malloc(sizeof(char *) * 6);
1754 if (vmlinux_path == NULL) 1761 if (vmlinux_path == NULL)
1755 return -1; 1762 return -1;
1756 1763
@@ -1763,25 +1770,37 @@ static int vmlinux_path__init(void)
1763 goto out_fail; 1770 goto out_fail;
1764 ++vmlinux_path__nr_entries; 1771 ++vmlinux_path__nr_entries;
1765 1772
1766 /* only try running kernel version if no symfs was given */ 1773 /* only try kernel version if no symfs was given */
1767 if (symbol_conf.symfs[0] != 0) 1774 if (symbol_conf.symfs[0] != 0)
1768 return 0; 1775 return 0;
1769 1776
1770 if (uname(&uts) < 0) 1777 if (env) {
1771 return -1; 1778 kernel_version = env->os_release;
1779 } else {
1780 if (uname(&uts) < 0)
1781 goto out_fail;
1772 1782
1773 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 1783 kernel_version = uts.release;
1784 }
1785
1786 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version);
1774 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1787 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1775 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1788 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1776 goto out_fail; 1789 goto out_fail;
1777 ++vmlinux_path__nr_entries; 1790 ++vmlinux_path__nr_entries;
1778 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); 1791 snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s",
1792 kernel_version);
1793 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1794 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1795 goto out_fail;
1796 ++vmlinux_path__nr_entries;
1797 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
1779 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1798 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1780 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1799 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1781 goto out_fail; 1800 goto out_fail;
1782 ++vmlinux_path__nr_entries; 1801 ++vmlinux_path__nr_entries;
1783 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", 1802 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1784 uts.release); 1803 kernel_version);
1785 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1804 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1786 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1805 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1787 goto out_fail; 1806 goto out_fail;
@@ -1827,7 +1846,7 @@ static bool symbol__read_kptr_restrict(void)
1827 return value; 1846 return value;
1828} 1847}
1829 1848
1830int symbol__init(void) 1849int symbol__init(struct perf_session_env *env)
1831{ 1850{
1832 const char *symfs; 1851 const char *symfs;
1833 1852
@@ -1842,7 +1861,7 @@ int symbol__init(void)
1842 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 1861 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
1843 sizeof(struct symbol)); 1862 sizeof(struct symbol));
1844 1863
1845 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 1864 if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0)
1846 return -1; 1865 return -1;
1847 1866
1848 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 1867 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e7295e93cff9..bec4b7bd09de 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,6 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15#include "event.h" 15#include "event.h"
16#include "util.h"
16 17
17#ifdef HAVE_LIBELF_SUPPORT 18#ifdef HAVE_LIBELF_SUPPORT
18#include <libelf.h> 19#include <libelf.h>
@@ -59,6 +60,7 @@ extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
59#endif 60#endif
60 61
61#ifndef DMGL_PARAMS 62#ifndef DMGL_PARAMS
63#define DMGL_NO_OPTS 0 /* For readability... */
62#define DMGL_PARAMS (1 << 0) /* Include function args */ 64#define DMGL_PARAMS (1 << 0) /* Include function args */
63#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 65#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
64#endif 66#endif
@@ -118,6 +120,7 @@ struct symbol_conf {
118 annotate_src, 120 annotate_src,
119 event_group, 121 event_group,
120 demangle, 122 demangle,
123 demangle_kernel,
121 filter_relative, 124 filter_relative,
122 show_hist_headers; 125 show_hist_headers;
123 const char *vmlinux_name, 126 const char *vmlinux_name,
@@ -143,6 +146,14 @@ struct symbol_conf {
143}; 146};
144 147
145extern struct symbol_conf symbol_conf; 148extern struct symbol_conf symbol_conf;
149
150static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
151{
152 return path__join(bf, size, symbol_conf.symfs, path);
153}
154
155#define symbol__join_symfs(bf, path) __symbol__join_symfs(bf, sizeof(bf), path)
156
146extern int vmlinux_path__nr_entries; 157extern int vmlinux_path__nr_entries;
147extern char **vmlinux_path; 158extern char **vmlinux_path;
148 159
@@ -253,7 +264,8 @@ int modules__parse(const char *filename, void *arg,
253int filename__read_debuglink(const char *filename, char *debuglink, 264int filename__read_debuglink(const char *filename, char *debuglink,
254 size_t size); 265 size_t size);
255 266
256int symbol__init(void); 267struct perf_session_env;
268int symbol__init(struct perf_session_env *env);
257void symbol__exit(void); 269void symbol__exit(void);
258void symbol__elf_init(void); 270void symbol__elf_init(void);
259struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 271struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 12c7a253a63c..a9df7f2c6dc9 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -42,7 +42,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
42 goto err_thread; 42 goto err_thread;
43 43
44 snprintf(comm_str, 32, ":%d", tid); 44 snprintf(comm_str, 32, ":%d", tid);
45 comm = comm__new(comm_str, 0); 45 comm = comm__new(comm_str, 0, false);
46 free(comm_str); 46 free(comm_str);
47 if (!comm) 47 if (!comm)
48 goto err_thread; 48 goto err_thread;
@@ -81,19 +81,33 @@ struct comm *thread__comm(const struct thread *thread)
81 return list_first_entry(&thread->comm_list, struct comm, list); 81 return list_first_entry(&thread->comm_list, struct comm, list);
82} 82}
83 83
84struct comm *thread__exec_comm(const struct thread *thread)
85{
86 struct comm *comm, *last = NULL;
87
88 list_for_each_entry(comm, &thread->comm_list, list) {
89 if (comm->exec)
90 return comm;
91 last = comm;
92 }
93
94 return last;
95}
96
84/* CHECKME: time should always be 0 if event aren't ordered */ 97/* CHECKME: time should always be 0 if event aren't ordered */
85int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 98int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
99 bool exec)
86{ 100{
87 struct comm *new, *curr = thread__comm(thread); 101 struct comm *new, *curr = thread__comm(thread);
88 int err; 102 int err;
89 103
90 /* Override latest entry if it had no specific time coverage */ 104 /* Override latest entry if it had no specific time coverage */
91 if (!curr->start) { 105 if (!curr->start && !curr->exec) {
92 err = comm__override(curr, str, timestamp); 106 err = comm__override(curr, str, timestamp, exec);
93 if (err) 107 if (err)
94 return err; 108 return err;
95 } else { 109 } else {
96 new = comm__new(str, timestamp); 110 new = comm__new(str, timestamp, exec);
97 if (!new) 111 if (!new)
98 return -ENOMEM; 112 return -ENOMEM;
99 list_add(&new->list, &thread->comm_list); 113 list_add(&new->list, &thread->comm_list);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 716b7723cce2..8c75fa774706 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -38,9 +38,17 @@ static inline void thread__exited(struct thread *thread)
38 thread->dead = true; 38 thread->dead = true;
39} 39}
40 40
41int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp); 41int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
42 bool exec);
43static inline int thread__set_comm(struct thread *thread, const char *comm,
44 u64 timestamp)
45{
46 return __thread__set_comm(thread, comm, timestamp, false);
47}
48
42int thread__comm_len(struct thread *thread); 49int thread__comm_len(struct thread *thread);
43struct comm *thread__comm(const struct thread *thread); 50struct comm *thread__comm(const struct thread *thread);
51struct comm *thread__exec_comm(const struct thread *thread);
44const char *thread__comm_str(const struct thread *thread); 52const char *thread__comm_str(const struct thread *thread);
45void thread__insert_map(struct thread *thread, struct map *map); 53void thread__insert_map(struct thread *thread, struct map *map);
46int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 54int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 4385816d3d49..f11636966a0f 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -40,7 +40,7 @@ struct perf_tool {
40 event_op2 tracing_data; 40 event_op2 tracing_data;
41 event_op2 finished_round, 41 event_op2 finished_round,
42 build_id; 42 build_id;
43 bool ordered_samples; 43 bool ordered_events;
44 bool ordering_requires_timestamps; 44 bool ordering_requires_timestamps;
45}; 45};
46 46
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 57aaccc1692e..5c9bdd1591a9 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -30,6 +30,11 @@
30 30
31struct scripting_context *scripting_context; 31struct scripting_context *scripting_context;
32 32
33static int flush_script_unsupported(void)
34{
35 return 0;
36}
37
33static int stop_script_unsupported(void) 38static int stop_script_unsupported(void)
34{ 39{
35 return 0; 40 return 0;
@@ -74,6 +79,7 @@ static int python_generate_script_unsupported(struct pevent *pevent
74struct scripting_ops python_scripting_unsupported_ops = { 79struct scripting_ops python_scripting_unsupported_ops = {
75 .name = "Python", 80 .name = "Python",
76 .start_script = python_start_script_unsupported, 81 .start_script = python_start_script_unsupported,
82 .flush_script = flush_script_unsupported,
77 .stop_script = stop_script_unsupported, 83 .stop_script = stop_script_unsupported,
78 .process_event = process_event_unsupported, 84 .process_event = process_event_unsupported,
79 .generate_script = python_generate_script_unsupported, 85 .generate_script = python_generate_script_unsupported,
@@ -137,6 +143,7 @@ static int perl_generate_script_unsupported(struct pevent *pevent
137struct scripting_ops perl_scripting_unsupported_ops = { 143struct scripting_ops perl_scripting_unsupported_ops = {
138 .name = "Perl", 144 .name = "Perl",
139 .start_script = perl_start_script_unsupported, 145 .start_script = perl_start_script_unsupported,
146 .flush_script = flush_script_unsupported,
140 .stop_script = stop_script_unsupported, 147 .stop_script = stop_script_unsupported,
141 .process_event = process_event_unsupported, 148 .process_event = process_event_unsupported,
142 .generate_script = perl_generate_script_unsupported, 149 .generate_script = perl_generate_script_unsupported,
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 7b6d68688327..52aaa19e1eb1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -64,6 +64,7 @@ struct perf_session;
64struct scripting_ops { 64struct scripting_ops {
65 const char *name; 65 const char *name;
66 int (*start_script) (const char *script, int argc, const char **argv); 66 int (*start_script) (const char *script, int argc, const char **argv);
67 int (*flush_script) (void);
67 int (*stop_script) (void); 68 int (*stop_script) (void);
68 void (*process_event) (union perf_event *event, 69 void (*process_event) (union perf_event *event,
69 struct perf_sample *sample, 70 struct perf_sample *sample,
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index e52e7461911b..24e8d871b74e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -13,6 +13,7 @@
13#include <limits.h> 13#include <limits.h>
14#include <byteswap.h> 14#include <byteswap.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <unistd.h>
16 17
17/* 18/*
18 * XXX We need to find a better place for these things... 19 * XXX We need to find a better place for these things...
@@ -282,6 +283,18 @@ void get_term_dimensions(struct winsize *ws)
282 ws->ws_col = 80; 283 ws->ws_col = 80;
283} 284}
284 285
286void set_term_quiet_input(struct termios *old)
287{
288 struct termios tc;
289
290 tcgetattr(0, old);
291 tc = *old;
292 tc.c_lflag &= ~(ICANON | ECHO);
293 tc.c_cc[VMIN] = 0;
294 tc.c_cc[VTIME] = 0;
295 tcsetattr(0, TCSANOW, &tc);
296}
297
285static void set_tracing_events_path(const char *mountpoint) 298static void set_tracing_events_path(const char *mountpoint)
286{ 299{
287 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 300 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -443,6 +456,7 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
443 size_t size = 0, alloc_size = 0; 456 size_t size = 0, alloc_size = 0;
444 void *bf = NULL, *nbf; 457 void *bf = NULL, *nbf;
445 int fd, n, err = 0; 458 int fd, n, err = 0;
459 char sbuf[STRERR_BUFSIZE];
446 460
447 fd = open(filename, O_RDONLY); 461 fd = open(filename, O_RDONLY);
448 if (fd < 0) 462 if (fd < 0)
@@ -463,8 +477,8 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
463 n = read(fd, bf + size, alloc_size - size); 477 n = read(fd, bf + size, alloc_size - size);
464 if (n < 0) { 478 if (n < 0) {
465 if (size) { 479 if (size) {
466 pr_warning("read failed %d: %s\n", 480 pr_warning("read failed %d: %s\n", errno,
467 errno, strerror(errno)); 481 strerror_r(errno, sbuf, sizeof(sbuf)));
468 err = 0; 482 err = 0;
469 } else 483 } else
470 err = -errno; 484 err = -errno;
@@ -536,3 +550,39 @@ void mem_bswap_64(void *src, int byte_size)
536 ++m; 550 ++m;
537 } 551 }
538} 552}
553
554bool find_process(const char *name)
555{
556 size_t len = strlen(name);
557 DIR *dir;
558 struct dirent *d;
559 int ret = -1;
560
561 dir = opendir(procfs__mountpoint());
562 if (!dir)
563 return -1;
564
565 /* Walk through the directory. */
566 while (ret && (d = readdir(dir)) != NULL) {
567 char path[PATH_MAX];
568 char *data;
569 size_t size;
570
571 if ((d->d_type != DT_DIR) ||
572 !strcmp(".", d->d_name) ||
573 !strcmp("..", d->d_name))
574 continue;
575
576 scnprintf(path, sizeof(path), "%s/%s/comm",
577 procfs__mountpoint(), d->d_name);
578
579 if (filename__read_str(path, &data, &size))
580 continue;
581
582 ret = strncmp(name, data, len);
583 free(data);
584 }
585
586 closedir(dir);
587 return ret ? false : true;
588}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 66864364ccb4..80bfdaa0e2a4 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -39,6 +39,8 @@
39 39
40#define _ALL_SOURCE 1 40#define _ALL_SOURCE 1
41#define _BSD_SOURCE 1 41#define _BSD_SOURCE 1
42/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
43#define _DEFAULT_SOURCE 1
42#define HAS_BOOL 44#define HAS_BOOL
43 45
44#include <unistd.h> 46#include <unistd.h>
@@ -64,16 +66,18 @@
64#include <regex.h> 66#include <regex.h>
65#include <utime.h> 67#include <utime.h>
66#include <sys/wait.h> 68#include <sys/wait.h>
67#include <sys/poll.h> 69#include <poll.h>
68#include <sys/socket.h> 70#include <sys/socket.h>
69#include <sys/ioctl.h> 71#include <sys/ioctl.h>
70#include <inttypes.h> 72#include <inttypes.h>
73#include <linux/kernel.h>
71#include <linux/magic.h> 74#include <linux/magic.h>
72#include <linux/types.h> 75#include <linux/types.h>
73#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
74#include <api/fs/debugfs.h> 77#include <api/fs/debugfs.h>
75#include <termios.h> 78#include <termios.h>
76#include <linux/bitops.h> 79#include <linux/bitops.h>
80#include <termios.h>
77 81
78extern const char *graph_line; 82extern const char *graph_line;
79extern const char *graph_dotted_line; 83extern const char *graph_dotted_line;
@@ -307,6 +311,7 @@ extern unsigned int page_size;
307extern int cacheline_size; 311extern int cacheline_size;
308 312
309void get_term_dimensions(struct winsize *ws); 313void get_term_dimensions(struct winsize *ws);
314void set_term_quiet_input(struct termios *old);
310 315
311struct parse_tag { 316struct parse_tag {
312 char tag; 317 char tag;
@@ -317,6 +322,21 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
317 322
318#define SRCLINE_UNKNOWN ((char *) "??:0") 323#define SRCLINE_UNKNOWN ((char *) "??:0")
319 324
325static inline int path__join(char *bf, size_t size,
326 const char *path1, const char *path2)
327{
328 return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
329}
330
331static inline int path__join3(char *bf, size_t size,
332 const char *path1, const char *path2,
333 const char *path3)
334{
335 return scnprintf(bf, size, "%s%s%s%s%s",
336 path1, path1[0] ? "/" : "",
337 path2, path2[0] ? "/" : "", path3);
338}
339
320struct dso; 340struct dso;
321 341
322char *get_srcline(struct dso *dso, unsigned long addr); 342char *get_srcline(struct dso *dso, unsigned long addr);
@@ -330,4 +350,5 @@ void mem_bswap_64(void *src, int byte_size);
330void mem_bswap_32(void *src, int byte_size); 350void mem_bswap_32(void *src, int byte_size);
331 351
332const char *get_filename_for_perf_kvm(void); 352const char *get_filename_for_perf_kvm(void);
353bool find_process(const char *name);
333#endif /* GIT_COMPAT_UTIL_H */ 354#endif /* GIT_COMPAT_UTIL_H */