aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/lib/traceevent/Makefile2
-rw-r--r--tools/perf/Documentation/perf-trace.txt16
-rw-r--r--tools/perf/Makefile6
-rw-r--r--tools/perf/builtin-kvm.c1
-rw-r--r--tools/perf/builtin-trace.c379
-rw-r--r--tools/perf/util/evlist.c3
-rw-r--r--tools/perf/util/evsel.c93
-rw-r--r--tools/perf/util/machine.c50
-rw-r--r--tools/perf/util/python.c20
-rw-r--r--tools/perf/util/thread.c3
-rw-r--r--tools/perf/util/thread.h8
11 files changed, 488 insertions, 93 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 0794acca46a3..ca6cb779876a 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -60,7 +60,7 @@ ifeq ($(BUILD_SRC),)
60ifneq ($(BUILD_OUTPUT),) 60ifneq ($(BUILD_OUTPUT),)
61 61
62define build_output 62define build_output
63 $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \ 63 $(if $(VERBOSE:1=),@)+$(MAKE) -C $(BUILD_OUTPUT) \
64 BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1 64 BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
65endef 65endef
66 66
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 3b3552a8959e..fe19811faf90 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -23,29 +23,45 @@ analysis phases.
23OPTIONS 23OPTIONS
24------- 24-------
25 25
26-a::
26--all-cpus:: 27--all-cpus::
27 System-wide collection from all CPUs. 28 System-wide collection from all CPUs.
28 29
29-e:: 30-e::
30--expr:: 31--expr::
31 List of events to show, currently only syscall names. 32 List of events to show, currently only syscall names.
33 Prefixing with ! shows all syscalls but the ones specified. You may
34 need to escape it.
35
36-o::
37--output=::
38 Output file name.
32 39
33-p:: 40-p::
34--pid=:: 41--pid=::
35 Record events on existing process ID (comma separated list). 42 Record events on existing process ID (comma separated list).
36 43
44-t::
37--tid=:: 45--tid=::
38 Record events on existing thread ID (comma separated list). 46 Record events on existing thread ID (comma separated list).
39 47
48-u::
40--uid=:: 49--uid=::
41 Record events in threads owned by uid. Name or number. 50 Record events in threads owned by uid. Name or number.
42 51
52-v::
53--verbose=::
54 Verbosity level.
55
56-i::
43--no-inherit:: 57--no-inherit::
44 Child tasks do not inherit counters. 58 Child tasks do not inherit counters.
45 59
60-m::
46--mmap-pages=:: 61--mmap-pages=::
47 Number of mmap data pages. Must be a power of two. 62 Number of mmap data pages. Must be a power of two.
48 63
64-C::
49--cpu:: 65--cpu::
50Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a 66Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a
51comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. 67comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e0d3d9f96771..7d30a7ddcc88 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -766,17 +766,21 @@ check: $(OUTPUT)common-cmds.h
766install-bin: all 766install-bin: all
767 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 767 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
768 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)' 768 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
769 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
770ifndef NO_LIBPERL
769 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' 771 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
770 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin' 772 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
771 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
772 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' 773 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
773 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl' 774 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
774 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin' 775 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
776endif
777ifndef NO_LIBPYTHON
775 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace' 778 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
776 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 779 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
777 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace' 780 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
778 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python' 781 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
779 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 782 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
783endif
780 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d' 784 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'
781 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 785 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
782 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests' 786 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index fa2f3d79886a..6cd4de59be21 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1305,7 +1305,6 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1305 const char * const record_args[] = { 1305 const char * const record_args[] = {
1306 "record", 1306 "record",
1307 "-R", 1307 "-R",
1308 "-f",
1309 "-m", "1024", 1308 "-m", "1024",
1310 "-c", "1", 1309 "-c", "1",
1311 }; 1310 };
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 120fdfb3d920..b72afc73f9a7 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1,6 +1,7 @@
1#include <traceevent/event-parse.h> 1#include <traceevent/event-parse.h>
2#include "builtin.h" 2#include "builtin.h"
3#include "util/color.h" 3#include "util/color.h"
4#include "util/debug.h"
4#include "util/evlist.h" 5#include "util/evlist.h"
5#include "util/machine.h" 6#include "util/machine.h"
6#include "util/thread.h" 7#include "util/thread.h"
@@ -10,27 +11,166 @@
10 11
11#include <libaudit.h> 12#include <libaudit.h>
12#include <stdlib.h> 13#include <stdlib.h>
14#include <sys/mman.h>
15
16static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, unsigned long arg)
17{
18 return scnprintf(bf, size, "%#lx", arg);
19}
20
21#define SCA_HEX syscall_arg__scnprintf_hex
22
23static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, unsigned long arg)
24{
25 int printed = 0, prot = arg;
26
27 if (prot == PROT_NONE)
28 return scnprintf(bf, size, "NONE");
29#define P_MMAP_PROT(n) \
30 if (prot & PROT_##n) { \
31 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
32 prot &= ~PROT_##n; \
33 }
34
35 P_MMAP_PROT(EXEC);
36 P_MMAP_PROT(READ);
37 P_MMAP_PROT(WRITE);
38#ifdef PROT_SEM
39 P_MMAP_PROT(SEM);
40#endif
41 P_MMAP_PROT(GROWSDOWN);
42 P_MMAP_PROT(GROWSUP);
43#undef P_MMAP_PROT
44
45 if (prot)
46 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
47
48 return printed;
49}
50
51#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
52
53static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, unsigned long arg)
54{
55 int printed = 0, flags = arg;
56
57#define P_MMAP_FLAG(n) \
58 if (flags & MAP_##n) { \
59 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
60 flags &= ~MAP_##n; \
61 }
62
63 P_MMAP_FLAG(SHARED);
64 P_MMAP_FLAG(PRIVATE);
65 P_MMAP_FLAG(32BIT);
66 P_MMAP_FLAG(ANONYMOUS);
67 P_MMAP_FLAG(DENYWRITE);
68 P_MMAP_FLAG(EXECUTABLE);
69 P_MMAP_FLAG(FILE);
70 P_MMAP_FLAG(FIXED);
71 P_MMAP_FLAG(GROWSDOWN);
72 P_MMAP_FLAG(HUGETLB);
73 P_MMAP_FLAG(LOCKED);
74 P_MMAP_FLAG(NONBLOCK);
75 P_MMAP_FLAG(NORESERVE);
76 P_MMAP_FLAG(POPULATE);
77 P_MMAP_FLAG(STACK);
78#ifdef MAP_UNINITIALIZED
79 P_MMAP_FLAG(UNINITIALIZED);
80#endif
81#undef P_MMAP_FLAG
82
83 if (flags)
84 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
85
86 return printed;
87}
88
89#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
90
91static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, unsigned long arg)
92{
93 int behavior = arg;
94
95 switch (behavior) {
96#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
97 P_MADV_BHV(NORMAL);
98 P_MADV_BHV(RANDOM);
99 P_MADV_BHV(SEQUENTIAL);
100 P_MADV_BHV(WILLNEED);
101 P_MADV_BHV(DONTNEED);
102 P_MADV_BHV(REMOVE);
103 P_MADV_BHV(DONTFORK);
104 P_MADV_BHV(DOFORK);
105 P_MADV_BHV(HWPOISON);
106#ifdef MADV_SOFT_OFFLINE
107 P_MADV_BHV(SOFT_OFFLINE);
108#endif
109 P_MADV_BHV(MERGEABLE);
110 P_MADV_BHV(UNMERGEABLE);
111 P_MADV_BHV(HUGEPAGE);
112 P_MADV_BHV(NOHUGEPAGE);
113#ifdef MADV_DONTDUMP
114 P_MADV_BHV(DONTDUMP);
115#endif
116#ifdef MADV_DODUMP
117 P_MADV_BHV(DODUMP);
118#endif
119#undef P_MADV_PHV
120 default: break;
121 }
122
123 return scnprintf(bf, size, "%#x", behavior);
124}
125
126#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
13 127
14static struct syscall_fmt { 128static struct syscall_fmt {
15 const char *name; 129 const char *name;
16 const char *alias; 130 const char *alias;
131 size_t (*arg_scnprintf[6])(char *bf, size_t size, unsigned long arg);
17 bool errmsg; 132 bool errmsg;
18 bool timeout; 133 bool timeout;
134 bool hexret;
19} syscall_fmts[] = { 135} syscall_fmts[] = {
20 { .name = "access", .errmsg = true, }, 136 { .name = "access", .errmsg = true, },
21 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 137 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
138 { .name = "brk", .hexret = true,
139 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
140 { .name = "mmap", .hexret = true, },
22 { .name = "connect", .errmsg = true, }, 141 { .name = "connect", .errmsg = true, },
23 { .name = "fstat", .errmsg = true, .alias = "newfstat", }, 142 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
24 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, 143 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
25 { .name = "futex", .errmsg = true, }, 144 { .name = "futex", .errmsg = true, },
145 { .name = "ioctl", .errmsg = true,
146 .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
147 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
148 { .name = "madvise", .errmsg = true,
149 .arg_scnprintf = { [0] = SCA_HEX, /* start */
150 [2] = SCA_MADV_BHV, /* behavior */ }, },
151 { .name = "mmap", .hexret = true,
152 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
153 [2] = SCA_MMAP_PROT, /* prot */
154 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
155 { .name = "mprotect", .errmsg = true,
156 .arg_scnprintf = { [0] = SCA_HEX, /* start */
157 [2] = SCA_MMAP_PROT, /* prot */ }, },
158 { .name = "mremap", .hexret = true,
159 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
160 [4] = SCA_HEX, /* new_addr */ }, },
161 { .name = "munmap", .errmsg = true,
162 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
26 { .name = "open", .errmsg = true, }, 163 { .name = "open", .errmsg = true, },
27 { .name = "poll", .errmsg = true, .timeout = true, }, 164 { .name = "poll", .errmsg = true, .timeout = true, },
28 { .name = "ppoll", .errmsg = true, .timeout = true, }, 165 { .name = "ppoll", .errmsg = true, .timeout = true, },
166 { .name = "pread", .errmsg = true, .alias = "pread64", },
167 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
29 { .name = "read", .errmsg = true, }, 168 { .name = "read", .errmsg = true, },
30 { .name = "recvfrom", .errmsg = true, }, 169 { .name = "recvfrom", .errmsg = true, },
31 { .name = "select", .errmsg = true, .timeout = true, }, 170 { .name = "select", .errmsg = true, .timeout = true, },
32 { .name = "socket", .errmsg = true, }, 171 { .name = "socket", .errmsg = true, },
33 { .name = "stat", .errmsg = true, .alias = "newstat", }, 172 { .name = "stat", .errmsg = true, .alias = "newstat", },
173 { .name = "uname", .errmsg = true, .alias = "newuname", },
34}; 174};
35 175
36static int syscall_fmt__cmp(const void *name, const void *fmtp) 176static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -50,6 +190,7 @@ struct syscall {
50 const char *name; 190 const char *name;
51 bool filtered; 191 bool filtered;
52 struct syscall_fmt *fmt; 192 struct syscall_fmt *fmt;
193 size_t (**arg_scnprintf)(char *bf, size_t size, unsigned long arg);
53}; 194};
54 195
55static size_t fprintf_duration(unsigned long t, FILE *fp) 196static size_t fprintf_duration(unsigned long t, FILE *fp)
@@ -63,7 +204,7 @@ static size_t fprintf_duration(unsigned long t, FILE *fp)
63 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration); 204 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
64 else 205 else
65 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration); 206 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
66 return printed + fprintf(stdout, "): "); 207 return printed + fprintf(fp, "): ");
67} 208}
68 209
69struct thread_trace { 210struct thread_trace {
@@ -80,7 +221,7 @@ static struct thread_trace *thread_trace__new(void)
80 return zalloc(sizeof(struct thread_trace)); 221 return zalloc(sizeof(struct thread_trace));
81} 222}
82 223
83static struct thread_trace *thread__trace(struct thread *thread) 224static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
84{ 225{
85 struct thread_trace *ttrace; 226 struct thread_trace *ttrace;
86 227
@@ -98,12 +239,13 @@ static struct thread_trace *thread__trace(struct thread *thread)
98 239
99 return ttrace; 240 return ttrace;
100fail: 241fail:
101 color_fprintf(stdout, PERF_COLOR_RED, 242 color_fprintf(fp, PERF_COLOR_RED,
102 "WARNING: not enough memory, dropping samples!\n"); 243 "WARNING: not enough memory, dropping samples!\n");
103 return NULL; 244 return NULL;
104} 245}
105 246
106struct trace { 247struct trace {
248 struct perf_tool tool;
107 int audit_machine; 249 int audit_machine;
108 struct { 250 struct {
109 int max; 251 int max;
@@ -112,8 +254,10 @@ struct trace {
112 struct perf_record_opts opts; 254 struct perf_record_opts opts;
113 struct machine host; 255 struct machine host;
114 u64 base_time; 256 u64 base_time;
115 struct strlist *ev_qualifier; 257 FILE *output;
116 unsigned long nr_events; 258 unsigned long nr_events;
259 struct strlist *ev_qualifier;
260 bool not_ev_qualifier;
117 bool sched; 261 bool sched;
118 bool multiple_threads; 262 bool multiple_threads;
119 double duration_filter; 263 double duration_filter;
@@ -151,13 +295,14 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
151 return printed; 295 return printed;
152} 296}
153 297
154static int trace__process_event(struct machine *machine, union perf_event *event) 298static int trace__process_event(struct trace *trace, struct machine *machine,
299 union perf_event *event)
155{ 300{
156 int ret = 0; 301 int ret = 0;
157 302
158 switch (event->header.type) { 303 switch (event->header.type) {
159 case PERF_RECORD_LOST: 304 case PERF_RECORD_LOST:
160 color_fprintf(stdout, PERF_COLOR_RED, 305 color_fprintf(trace->output, PERF_COLOR_RED,
161 "LOST %" PRIu64 " events!\n", event->lost.lost); 306 "LOST %" PRIu64 " events!\n", event->lost.lost);
162 ret = machine__process_lost_event(machine, event); 307 ret = machine__process_lost_event(machine, event);
163 default: 308 default:
@@ -168,12 +313,13 @@ static int trace__process_event(struct machine *machine, union perf_event *event
168 return ret; 313 return ret;
169} 314}
170 315
171static int trace__tool_process(struct perf_tool *tool __maybe_unused, 316static int trace__tool_process(struct perf_tool *tool,
172 union perf_event *event, 317 union perf_event *event,
173 struct perf_sample *sample __maybe_unused, 318 struct perf_sample *sample __maybe_unused,
174 struct machine *machine) 319 struct machine *machine)
175{ 320{
176 return trace__process_event(machine, event); 321 struct trace *trace = container_of(tool, struct trace, tool);
322 return trace__process_event(trace, machine, event);
177} 323}
178 324
179static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 325static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
@@ -187,11 +333,11 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
187 machine__create_kernel_maps(&trace->host); 333 machine__create_kernel_maps(&trace->host);
188 334
189 if (perf_target__has_task(&trace->opts.target)) { 335 if (perf_target__has_task(&trace->opts.target)) {
190 err = perf_event__synthesize_thread_map(NULL, evlist->threads, 336 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
191 trace__tool_process, 337 trace__tool_process,
192 &trace->host); 338 &trace->host);
193 } else { 339 } else {
194 err = perf_event__synthesize_threads(NULL, trace__tool_process, 340 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
195 &trace->host); 341 &trace->host);
196 } 342 }
197 343
@@ -201,6 +347,26 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
201 return err; 347 return err;
202} 348}
203 349
350static int syscall__set_arg_fmts(struct syscall *sc)
351{
352 struct format_field *field;
353 int idx = 0;
354
355 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *));
356 if (sc->arg_scnprintf == NULL)
357 return -1;
358
359 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
360 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
361 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
362 else if (field->flags & FIELD_IS_POINTER)
363 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
364 ++idx;
365 }
366
367 return 0;
368}
369
204static int trace__read_syscall_info(struct trace *trace, int id) 370static int trace__read_syscall_info(struct trace *trace, int id)
205{ 371{
206 char tp_name[128]; 372 char tp_name[128];
@@ -230,13 +396,17 @@ static int trace__read_syscall_info(struct trace *trace, int id)
230 sc = trace->syscalls.table + id; 396 sc = trace->syscalls.table + id;
231 sc->name = name; 397 sc->name = name;
232 398
233 if (trace->ev_qualifier && !strlist__find(trace->ev_qualifier, name)) { 399 if (trace->ev_qualifier) {
234 sc->filtered = true; 400 bool in = strlist__find(trace->ev_qualifier, name) != NULL;
235 /* 401
236 * No need to do read tracepoint information since this will be 402 if (!(in ^ trace->not_ev_qualifier)) {
237 * filtered out. 403 sc->filtered = true;
238 */ 404 /*
239 return 0; 405 * No need to do read tracepoint information since this will be
406 * filtered out.
407 */
408 return 0;
409 }
240 } 410 }
241 411
242 sc->fmt = syscall_fmt__find(sc->name); 412 sc->fmt = syscall_fmt__find(sc->name);
@@ -249,7 +419,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)
249 sc->tp_format = event_format__new("syscalls", tp_name); 419 sc->tp_format = event_format__new("syscalls", tp_name);
250 } 420 }
251 421
252 return sc->tp_format != NULL ? 0 : -1; 422 if (sc->tp_format == NULL)
423 return -1;
424
425 return syscall__set_arg_fmts(sc);
253} 426}
254 427
255static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 428static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
@@ -263,8 +436,14 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
263 436
264 for (field = sc->tp_format->format.fields->next; field; field = field->next) { 437 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
265 printed += scnprintf(bf + printed, size - printed, 438 printed += scnprintf(bf + printed, size - printed,
266 "%s%s: %ld", printed ? ", " : "", 439 "%s%s: ", printed ? ", " : "", field->name);
267 field->name, args[i++]); 440
441 if (sc->arg_scnprintf && sc->arg_scnprintf[i])
442 printed += sc->arg_scnprintf[i](bf + printed, size - printed, args[i]);
443 else
444 printed += scnprintf(bf + printed, size - printed,
445 "%ld", args[i]);
446 ++i;
268 } 447 }
269 } else { 448 } else {
270 while (i < 6) { 449 while (i < 6) {
@@ -288,7 +467,22 @@ static struct syscall *trace__syscall_info(struct trace *trace,
288 int id = perf_evsel__intval(evsel, sample, "id"); 467 int id = perf_evsel__intval(evsel, sample, "id");
289 468
290 if (id < 0) { 469 if (id < 0) {
291 printf("Invalid syscall %d id, skipping...\n", id); 470
471 /*
472 * XXX: Noticed on x86_64, reproduced as far back as 3.0.36, haven't tried
473 * before that, leaving at a higher verbosity level till that is
474 * explained. Reproduced with plain ftrace with:
475 *
476 * echo 1 > /t/events/raw_syscalls/sys_exit/enable
477 * grep "NR -1 " /t/trace_pipe
478 *
479 * After generating some load on the machine.
480 */
481 if (verbose > 1) {
482 static u64 n;
483 fprintf(trace->output, "Invalid syscall %d id, skipping (%s, %" PRIu64 ") ...\n",
484 id, perf_evsel__name(evsel), ++n);
485 }
292 return NULL; 486 return NULL;
293 } 487 }
294 488
@@ -302,10 +496,12 @@ static struct syscall *trace__syscall_info(struct trace *trace,
302 return &trace->syscalls.table[id]; 496 return &trace->syscalls.table[id];
303 497
304out_cant_read: 498out_cant_read:
305 printf("Problems reading syscall %d", id); 499 if (verbose) {
306 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL) 500 fprintf(trace->output, "Problems reading syscall %d", id);
307 printf("(%s)", trace->syscalls.table[id].name); 501 if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
308 puts(" information"); 502 fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
503 fputs(" information\n", trace->output);
504 }
309 return NULL; 505 return NULL;
310} 506}
311 507
@@ -326,13 +522,13 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
326 return 0; 522 return 0;
327 523
328 thread = machine__findnew_thread(&trace->host, sample->tid); 524 thread = machine__findnew_thread(&trace->host, sample->tid);
329 ttrace = thread__trace(thread); 525 ttrace = thread__trace(thread, trace->output);
330 if (ttrace == NULL) 526 if (ttrace == NULL)
331 return -1; 527 return -1;
332 528
333 args = perf_evsel__rawptr(evsel, sample, "args"); 529 args = perf_evsel__rawptr(evsel, sample, "args");
334 if (args == NULL) { 530 if (args == NULL) {
335 printf("Problems reading syscall arguments\n"); 531 fprintf(trace->output, "Problems reading syscall arguments\n");
336 return -1; 532 return -1;
337 } 533 }
338 534
@@ -352,8 +548,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
352 548
353 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { 549 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
354 if (!trace->duration_filter) { 550 if (!trace->duration_filter) {
355 trace__fprintf_entry_head(trace, thread, 1, sample->time, stdout); 551 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
356 printf("%-70s\n", ttrace->entry_str); 552 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
357 } 553 }
358 } else 554 } else
359 ttrace->entry_pending = true; 555 ttrace->entry_pending = true;
@@ -377,7 +573,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
377 return 0; 573 return 0;
378 574
379 thread = machine__findnew_thread(&trace->host, sample->tid); 575 thread = machine__findnew_thread(&trace->host, sample->tid);
380 ttrace = thread__trace(thread); 576 ttrace = thread__trace(thread, trace->output);
381 if (ttrace == NULL) 577 if (ttrace == NULL)
382 return -1; 578 return -1;
383 579
@@ -394,28 +590,33 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
394 } else if (trace->duration_filter) 590 } else if (trace->duration_filter)
395 goto out; 591 goto out;
396 592
397 trace__fprintf_entry_head(trace, thread, duration, sample->time, stdout); 593 trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
398 594
399 if (ttrace->entry_pending) { 595 if (ttrace->entry_pending) {
400 printf("%-70s", ttrace->entry_str); 596 fprintf(trace->output, "%-70s", ttrace->entry_str);
401 } else { 597 } else {
402 printf(" ... ["); 598 fprintf(trace->output, " ... [");
403 color_fprintf(stdout, PERF_COLOR_YELLOW, "continued"); 599 color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
404 printf("]: %s()", sc->name); 600 fprintf(trace->output, "]: %s()", sc->name);
405 } 601 }
406 602
407 if (ret < 0 && sc->fmt && sc->fmt->errmsg) { 603 if (sc->fmt == NULL) {
604signed_print:
605 fprintf(trace->output, ") = %d", ret);
606 } else if (ret < 0 && sc->fmt->errmsg) {
408 char bf[256]; 607 char bf[256];
409 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 608 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
410 *e = audit_errno_to_name(-ret); 609 *e = audit_errno_to_name(-ret);
411 610
412 printf(") = -1 %s %s", e, emsg); 611 fprintf(trace->output, ") = -1 %s %s", e, emsg);
413 } else if (ret == 0 && sc->fmt && sc->fmt->timeout) 612 } else if (ret == 0 && sc->fmt->timeout)
414 printf(") = 0 Timeout"); 613 fprintf(trace->output, ") = 0 Timeout");
614 else if (sc->fmt->hexret)
615 fprintf(trace->output, ") = %#x", ret);
415 else 616 else
416 printf(") = %d", ret); 617 goto signed_print;
417 618
418 putchar('\n'); 619 fputc('\n', trace->output);
419out: 620out:
420 ttrace->entry_pending = false; 621 ttrace->entry_pending = false;
421 622
@@ -428,7 +629,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
428 u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 629 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
429 double runtime_ms = (double)runtime / NSEC_PER_MSEC; 630 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
430 struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); 631 struct thread *thread = machine__findnew_thread(&trace->host, sample->tid);
431 struct thread_trace *ttrace = thread__trace(thread); 632 struct thread_trace *ttrace = thread__trace(thread, trace->output);
432 633
433 if (ttrace == NULL) 634 if (ttrace == NULL)
434 goto out_dump; 635 goto out_dump;
@@ -438,7 +639,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
438 return 0; 639 return 0;
439 640
440out_dump: 641out_dump:
441 printf("%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n", 642 fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
442 evsel->name, 643 evsel->name,
443 perf_evsel__strval(evsel, sample, "comm"), 644 perf_evsel__strval(evsel, sample, "comm"),
444 (pid_t)perf_evsel__intval(evsel, sample, "pid"), 645 (pid_t)perf_evsel__intval(evsel, sample, "pid"),
@@ -456,32 +657,32 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
456 const bool forks = argc > 0; 657 const bool forks = argc > 0;
457 658
458 if (evlist == NULL) { 659 if (evlist == NULL) {
459 printf("Not enough memory to run!\n"); 660 fprintf(trace->output, "Not enough memory to run!\n");
460 goto out; 661 goto out;
461 } 662 }
462 663
463 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) || 664 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
464 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) { 665 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
465 printf("Couldn't read the raw_syscalls tracepoints information!\n"); 666 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
466 goto out_delete_evlist; 667 goto out_delete_evlist;
467 } 668 }
468 669
469 if (trace->sched && 670 if (trace->sched &&
470 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 671 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
471 trace__sched_stat_runtime)) { 672 trace__sched_stat_runtime)) {
472 printf("Couldn't read the sched_stat_runtime tracepoint information!\n"); 673 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
473 goto out_delete_evlist; 674 goto out_delete_evlist;
474 } 675 }
475 676
476 err = perf_evlist__create_maps(evlist, &trace->opts.target); 677 err = perf_evlist__create_maps(evlist, &trace->opts.target);
477 if (err < 0) { 678 if (err < 0) {
478 printf("Problems parsing the target to trace, check your options!\n"); 679 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
479 goto out_delete_evlist; 680 goto out_delete_evlist;
480 } 681 }
481 682
482 err = trace__symbols_init(trace, evlist); 683 err = trace__symbols_init(trace, evlist);
483 if (err < 0) { 684 if (err < 0) {
484 printf("Problems initializing symbol libraries!\n"); 685 fprintf(trace->output, "Problems initializing symbol libraries!\n");
485 goto out_delete_maps; 686 goto out_delete_maps;
486 } 687 }
487 688
@@ -494,20 +695,20 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
494 err = perf_evlist__prepare_workload(evlist, &trace->opts.target, 695 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
495 argv, false, false); 696 argv, false, false);
496 if (err < 0) { 697 if (err < 0) {
497 printf("Couldn't run the workload!\n"); 698 fprintf(trace->output, "Couldn't run the workload!\n");
498 goto out_delete_maps; 699 goto out_delete_maps;
499 } 700 }
500 } 701 }
501 702
502 err = perf_evlist__open(evlist); 703 err = perf_evlist__open(evlist);
503 if (err < 0) { 704 if (err < 0) {
504 printf("Couldn't create the events: %s\n", strerror(errno)); 705 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
505 goto out_delete_maps; 706 goto out_delete_maps;
506 } 707 }
507 708
508 err = perf_evlist__mmap(evlist, UINT_MAX, false); 709 err = perf_evlist__mmap(evlist, UINT_MAX, false);
509 if (err < 0) { 710 if (err < 0) {
510 printf("Couldn't mmap the events: %s\n", strerror(errno)); 711 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
511 goto out_close_evlist; 712 goto out_close_evlist;
512 } 713 }
513 714
@@ -532,7 +733,7 @@ again:
532 733
533 err = perf_evlist__parse_sample(evlist, event, &sample); 734 err = perf_evlist__parse_sample(evlist, event, &sample);
534 if (err) { 735 if (err) {
535 printf("Can't parse sample, err = %d, skipping...\n", err); 736 fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
536 continue; 737 continue;
537 } 738 }
538 739
@@ -540,18 +741,18 @@ again:
540 trace->base_time = sample.time; 741 trace->base_time = sample.time;
541 742
542 if (type != PERF_RECORD_SAMPLE) { 743 if (type != PERF_RECORD_SAMPLE) {
543 trace__process_event(&trace->host, event); 744 trace__process_event(trace, &trace->host, event);
544 continue; 745 continue;
545 } 746 }
546 747
547 evsel = perf_evlist__id2evsel(evlist, sample.id); 748 evsel = perf_evlist__id2evsel(evlist, sample.id);
548 if (evsel == NULL) { 749 if (evsel == NULL) {
549 printf("Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); 750 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
550 continue; 751 continue;
551 } 752 }
552 753
553 if (sample.raw_data == NULL) { 754 if (sample.raw_data == NULL) {
554 printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", 755 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
555 perf_evsel__name(evsel), sample.tid, 756 perf_evsel__name(evsel), sample.tid,
556 sample.cpu, sample.raw_size); 757 sample.cpu, sample.raw_size);
557 continue; 758 continue;
@@ -640,6 +841,23 @@ static int trace__set_duration(const struct option *opt, const char *str,
640 return 0; 841 return 0;
641} 842}
642 843
844static int trace__open_output(struct trace *trace, const char *filename)
845{
846 struct stat st;
847
848 if (!stat(filename, &st) && st.st_size) {
849 char oldname[PATH_MAX];
850
851 scnprintf(oldname, sizeof(oldname), "%s.old", filename);
852 unlink(oldname);
853 rename(filename, oldname);
854 }
855
856 trace->output = fopen(filename, "w");
857
858 return trace->output == NULL ? -errno : 0;
859}
860
643int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 861int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
644{ 862{
645 const char * const trace_usage[] = { 863 const char * const trace_usage[] = {
@@ -662,29 +880,33 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
662 .no_delay = true, 880 .no_delay = true,
663 .mmap_pages = 1024, 881 .mmap_pages = 1024,
664 }, 882 },
883 .output = stdout,
665 }; 884 };
885 const char *output_name = NULL;
666 const char *ev_qualifier_str = NULL; 886 const char *ev_qualifier_str = NULL;
667 const struct option trace_options[] = { 887 const struct option trace_options[] = {
668 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 888 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
669 "list of events to trace"), 889 "list of events to trace"),
890 OPT_STRING('o', "output", &output_name, "file", "output file name"),
670 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid", 891 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
671 "trace events on existing process id"), 892 "trace events on existing process id"),
672 OPT_STRING(0, "tid", &trace.opts.target.tid, "tid", 893 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
673 "trace events on existing thread id"), 894 "trace events on existing thread id"),
674 OPT_BOOLEAN(0, "all-cpus", &trace.opts.target.system_wide, 895 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
675 "system-wide collection from all CPUs"), 896 "system-wide collection from all CPUs"),
676 OPT_STRING(0, "cpu", &trace.opts.target.cpu_list, "cpu", 897 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
677 "list of cpus to monitor"), 898 "list of cpus to monitor"),
678 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit, 899 OPT_BOOLEAN('i', "no-inherit", &trace.opts.no_inherit,
679 "child tasks do not inherit counters"), 900 "child tasks do not inherit counters"),
680 OPT_UINTEGER(0, "mmap-pages", &trace.opts.mmap_pages, 901 OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages,
681 "number of mmap data pages"), 902 "number of mmap data pages"),
682 OPT_STRING(0, "uid", &trace.opts.target.uid_str, "user", 903 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
683 "user to profile"), 904 "user to profile"),
684 OPT_CALLBACK(0, "duration", &trace, "float", 905 OPT_CALLBACK(0, "duration", &trace, "float",
685 "show only events with duration > N.M ms", 906 "show only events with duration > N.M ms",
686 trace__set_duration), 907 trace__set_duration),
687 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"), 908 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
909 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
688 OPT_END() 910 OPT_END()
689 }; 911 };
690 int err; 912 int err;
@@ -692,26 +914,41 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
692 914
693 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 915 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
694 916
917 if (output_name != NULL) {
918 err = trace__open_output(&trace, output_name);
919 if (err < 0) {
920 perror("failed to create output file");
921 goto out;
922 }
923 }
924
695 if (ev_qualifier_str != NULL) { 925 if (ev_qualifier_str != NULL) {
696 trace.ev_qualifier = strlist__new(true, ev_qualifier_str); 926 const char *s = ev_qualifier_str;
927
928 trace.not_ev_qualifier = *s == '!';
929 if (trace.not_ev_qualifier)
930 ++s;
931 trace.ev_qualifier = strlist__new(true, s);
697 if (trace.ev_qualifier == NULL) { 932 if (trace.ev_qualifier == NULL) {
698 puts("Not enough memory to parse event qualifier"); 933 fputs("Not enough memory to parse event qualifier",
699 return -ENOMEM; 934 trace.output);
935 err = -ENOMEM;
936 goto out_close;
700 } 937 }
701 } 938 }
702 939
703 err = perf_target__validate(&trace.opts.target); 940 err = perf_target__validate(&trace.opts.target);
704 if (err) { 941 if (err) {
705 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); 942 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
706 printf("%s", bf); 943 fprintf(trace.output, "%s", bf);
707 return err; 944 goto out_close;
708 } 945 }
709 946
710 err = perf_target__parse_uid(&trace.opts.target); 947 err = perf_target__parse_uid(&trace.opts.target);
711 if (err) { 948 if (err) {
712 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf)); 949 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
713 printf("%s", bf); 950 fprintf(trace.output, "%s", bf);
714 return err; 951 goto out_close;
715 } 952 }
716 953
717 if (!argc && perf_target__none(&trace.opts.target)) 954 if (!argc && perf_target__none(&trace.opts.target))
@@ -720,7 +957,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
720 err = trace__run(&trace, argc, argv); 957 err = trace__run(&trace, argc, argv);
721 958
722 if (trace.sched && !err) 959 if (trace.sched && !err)
723 trace__fprintf_thread_summary(&trace, stdout); 960 trace__fprintf_thread_summary(&trace, trace.output);
724 961
962out_close:
963 if (output_name != NULL)
964 fclose(trace.output);
965out:
725 return err; 966 return err;
726} 967}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index c7d111f74553..1f5105ac5c85 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -14,6 +14,7 @@
14#include "target.h" 14#include "target.h"
15#include "evlist.h" 15#include "evlist.h"
16#include "evsel.h" 16#include "evsel.h"
17#include "debug.h"
17#include <unistd.h> 18#include <unistd.h>
18 19
19#include "parse-events.h" 20#include "parse-events.h"
@@ -486,6 +487,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m
486 int nr_cpus = cpu_map__nr(evlist->cpus); 487 int nr_cpus = cpu_map__nr(evlist->cpus);
487 int nr_threads = thread_map__nr(evlist->threads); 488 int nr_threads = thread_map__nr(evlist->threads);
488 489
490 pr_debug2("perf event ring buffer mmapped per cpu\n");
489 for (cpu = 0; cpu < nr_cpus; cpu++) { 491 for (cpu = 0; cpu < nr_cpus; cpu++) {
490 int output = -1; 492 int output = -1;
491 493
@@ -524,6 +526,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
524 int thread; 526 int thread;
525 int nr_threads = thread_map__nr(evlist->threads); 527 int nr_threads = thread_map__nr(evlist->threads);
526 528
529 pr_debug2("perf event ring buffer mmapped per thread\n");
527 for (thread = 0; thread < nr_threads; thread++) { 530 for (thread = 0; thread < nr_threads; thread++) {
528 int output = -1; 531 int output = -1;
529 532
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 960394ea1e3a..47cbe1e58b73 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -13,6 +13,7 @@
13#include <traceevent/event-parse.h> 13#include <traceevent/event-parse.h>
14#include <linux/hw_breakpoint.h> 14#include <linux/hw_breakpoint.h>
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16#include <sys/resource.h>
16#include "asm/bug.h" 17#include "asm/bug.h"
17#include "evsel.h" 18#include "evsel.h"
18#include "evlist.h" 19#include "evlist.h"
@@ -21,6 +22,7 @@
21#include "thread_map.h" 22#include "thread_map.h"
22#include "target.h" 23#include "target.h"
23#include "perf_regs.h" 24#include "perf_regs.h"
25#include "debug.h"
24 26
25static struct { 27static struct {
26 bool sample_id_all; 28 bool sample_id_all;
@@ -861,12 +863,72 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
861 return fd; 863 return fd;
862} 864}
863 865
866#define __PRINT_ATTR(fmt, cast, field) \
867 fprintf(fp, " %-19s "fmt"\n", #field, cast attr->field)
868
869#define PRINT_ATTR_U32(field) __PRINT_ATTR("%u" , , field)
870#define PRINT_ATTR_X32(field) __PRINT_ATTR("%#x", , field)
871#define PRINT_ATTR_U64(field) __PRINT_ATTR("%" PRIu64, (uint64_t), field)
872#define PRINT_ATTR_X64(field) __PRINT_ATTR("%#"PRIx64, (uint64_t), field)
873
874#define PRINT_ATTR2N(name1, field1, name2, field2) \
875 fprintf(fp, " %-19s %u %-19s %u\n", \
876 name1, attr->field1, name2, attr->field2)
877
878#define PRINT_ATTR2(field1, field2) \
879 PRINT_ATTR2N(#field1, field1, #field2, field2)
880
881static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
882{
883 size_t ret = 0;
884
885 ret += fprintf(fp, "%.60s\n", graph_dotted_line);
886 ret += fprintf(fp, "perf_event_attr:\n");
887
888 ret += PRINT_ATTR_U32(type);
889 ret += PRINT_ATTR_U32(size);
890 ret += PRINT_ATTR_X64(config);
891 ret += PRINT_ATTR_U64(sample_period);
892 ret += PRINT_ATTR_U64(sample_freq);
893 ret += PRINT_ATTR_X64(sample_type);
894 ret += PRINT_ATTR_X64(read_format);
895
896 ret += PRINT_ATTR2(disabled, inherit);
897 ret += PRINT_ATTR2(pinned, exclusive);
898 ret += PRINT_ATTR2(exclude_user, exclude_kernel);
899 ret += PRINT_ATTR2(exclude_hv, exclude_idle);
900 ret += PRINT_ATTR2(mmap, comm);
901 ret += PRINT_ATTR2(freq, inherit_stat);
902 ret += PRINT_ATTR2(enable_on_exec, task);
903 ret += PRINT_ATTR2(watermark, precise_ip);
904 ret += PRINT_ATTR2(mmap_data, sample_id_all);
905 ret += PRINT_ATTR2(exclude_host, exclude_guest);
906 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
907 "excl.callchain_user", exclude_callchain_user);
908
909 ret += PRINT_ATTR_U32(wakeup_events);
910 ret += PRINT_ATTR_U32(wakeup_watermark);
911 ret += PRINT_ATTR_X32(bp_type);
912 ret += PRINT_ATTR_X64(bp_addr);
913 ret += PRINT_ATTR_X64(config1);
914 ret += PRINT_ATTR_U64(bp_len);
915 ret += PRINT_ATTR_X64(config2);
916 ret += PRINT_ATTR_X64(branch_sample_type);
917 ret += PRINT_ATTR_X64(sample_regs_user);
918 ret += PRINT_ATTR_U32(sample_stack_user);
919
920 ret += fprintf(fp, "%.60s\n", graph_dotted_line);
921
922 return ret;
923}
924
864static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 925static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
865 struct thread_map *threads) 926 struct thread_map *threads)
866{ 927{
867 int cpu, thread; 928 int cpu, thread;
868 unsigned long flags = 0; 929 unsigned long flags = 0;
869 int pid = -1, err; 930 int pid = -1, err;
931 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
870 932
871 if (evsel->fd == NULL && 933 if (evsel->fd == NULL &&
872 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 934 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
@@ -884,6 +946,9 @@ retry_sample_id:
884 if (perf_missing_features.sample_id_all) 946 if (perf_missing_features.sample_id_all)
885 evsel->attr.sample_id_all = 0; 947 evsel->attr.sample_id_all = 0;
886 948
949 if (verbose >= 2)
950 perf_event_attr__fprintf(&evsel->attr, stderr);
951
887 for (cpu = 0; cpu < cpus->nr; cpu++) { 952 for (cpu = 0; cpu < cpus->nr; cpu++) {
888 953
889 for (thread = 0; thread < threads->nr; thread++) { 954 for (thread = 0; thread < threads->nr; thread++) {
@@ -893,6 +958,9 @@ retry_sample_id:
893 pid = threads->map[thread]; 958 pid = threads->map[thread];
894 959
895 group_fd = get_group_fd(evsel, cpu, thread); 960 group_fd = get_group_fd(evsel, cpu, thread);
961retry_open:
962 pr_debug2("perf_event_open: pid %d cpu %d group_fd %d flags %#lx\n",
963 pid, cpus->map[cpu], group_fd, flags);
896 964
897 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 965 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
898 pid, 966 pid,
@@ -902,12 +970,37 @@ retry_sample_id:
902 err = -errno; 970 err = -errno;
903 goto try_fallback; 971 goto try_fallback;
904 } 972 }
973 set_rlimit = NO_CHANGE;
905 } 974 }
906 } 975 }
907 976
908 return 0; 977 return 0;
909 978
910try_fallback: 979try_fallback:
980 /*
981 * perf stat needs between 5 and 22 fds per CPU. When we run out
982 * of them try to increase the limits.
983 */
984 if (err == -EMFILE && set_rlimit < INCREASED_MAX) {
985 struct rlimit l;
986 int old_errno = errno;
987
988 if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
989 if (set_rlimit == NO_CHANGE)
990 l.rlim_cur = l.rlim_max;
991 else {
992 l.rlim_cur = l.rlim_max + 1000;
993 l.rlim_max = l.rlim_cur;
994 }
995 if (setrlimit(RLIMIT_NOFILE, &l) == 0) {
996 set_rlimit++;
997 errno = old_errno;
998 goto retry_open;
999 }
1000 }
1001 errno = old_errno;
1002 }
1003
911 if (err != -EINVAL || cpu > 0 || thread > 0) 1004 if (err != -EINVAL || cpu > 0 || thread > 0)
912 goto out_close; 1005 goto out_close;
913 1006
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 4514e7e9b659..59486c180626 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -253,7 +253,8 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
253 return; 253 return;
254} 254}
255 255
256static struct thread *__machine__findnew_thread(struct machine *machine, pid_t tid, 256static struct thread *__machine__findnew_thread(struct machine *machine,
257 pid_t pid, pid_t tid,
257 bool create) 258 bool create)
258{ 259{
259 struct rb_node **p = &machine->threads.rb_node; 260 struct rb_node **p = &machine->threads.rb_node;
@@ -265,8 +266,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t t
265 * so most of the time we dont have to look up 266 * so most of the time we dont have to look up
266 * the full rbtree: 267 * the full rbtree:
267 */ 268 */
268 if (machine->last_match && machine->last_match->tid == tid) 269 if (machine->last_match && machine->last_match->tid == tid) {
270 if (pid && pid != machine->last_match->pid_)
271 machine->last_match->pid_ = pid;
269 return machine->last_match; 272 return machine->last_match;
273 }
270 274
271 while (*p != NULL) { 275 while (*p != NULL) {
272 parent = *p; 276 parent = *p;
@@ -274,6 +278,8 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t t
274 278
275 if (th->tid == tid) { 279 if (th->tid == tid) {
276 machine->last_match = th; 280 machine->last_match = th;
281 if (pid && pid != th->pid_)
282 th->pid_ = pid;
277 return th; 283 return th;
278 } 284 }
279 285
@@ -286,7 +292,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t t
286 if (!create) 292 if (!create)
287 return NULL; 293 return NULL;
288 294
289 th = thread__new(tid); 295 th = thread__new(pid, tid);
290 if (th != NULL) { 296 if (th != NULL) {
291 rb_link_node(&th->rb_node, parent, p); 297 rb_link_node(&th->rb_node, parent, p);
292 rb_insert_color(&th->rb_node, &machine->threads); 298 rb_insert_color(&th->rb_node, &machine->threads);
@@ -298,12 +304,12 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t t
298 304
299struct thread *machine__findnew_thread(struct machine *machine, pid_t tid) 305struct thread *machine__findnew_thread(struct machine *machine, pid_t tid)
300{ 306{
301 return __machine__findnew_thread(machine, tid, true); 307 return __machine__findnew_thread(machine, 0, tid, true);
302} 308}
303 309
304struct thread *machine__find_thread(struct machine *machine, pid_t tid) 310struct thread *machine__find_thread(struct machine *machine, pid_t tid)
305{ 311{
306 return __machine__findnew_thread(machine, tid, false); 312 return __machine__findnew_thread(machine, 0, tid, false);
307} 313}
308 314
309int machine__process_comm_event(struct machine *machine, union perf_event *event) 315int machine__process_comm_event(struct machine *machine, union perf_event *event)
@@ -1031,11 +1037,27 @@ out_problem:
1031 return 0; 1037 return 0;
1032} 1038}
1033 1039
1040static void machine__remove_thread(struct machine *machine, struct thread *th)
1041{
1042 machine->last_match = NULL;
1043 rb_erase(&th->rb_node, &machine->threads);
1044 /*
1045 * We may have references to this thread, for instance in some hist_entry
1046 * instances, so just move them to a separate list.
1047 */
1048 list_add_tail(&th->node, &machine->dead_threads);
1049}
1050
1034int machine__process_fork_event(struct machine *machine, union perf_event *event) 1051int machine__process_fork_event(struct machine *machine, union perf_event *event)
1035{ 1052{
1036 struct thread *thread = machine__findnew_thread(machine, event->fork.tid); 1053 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1037 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid); 1054 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
1038 1055
1056 /* if a thread currently exists for the thread id remove it */
1057 if (thread != NULL)
1058 machine__remove_thread(machine, thread);
1059
1060 thread = machine__findnew_thread(machine, event->fork.tid);
1039 if (dump_trace) 1061 if (dump_trace)
1040 perf_event__fprintf_task(event, stdout); 1062 perf_event__fprintf_task(event, stdout);
1041 1063
@@ -1048,18 +1070,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1048 return 0; 1070 return 0;
1049} 1071}
1050 1072
1051static void machine__remove_thread(struct machine *machine, struct thread *th) 1073int machine__process_exit_event(struct machine *machine __maybe_unused,
1052{ 1074 union perf_event *event)
1053 machine->last_match = NULL;
1054 rb_erase(&th->rb_node, &machine->threads);
1055 /*
1056 * We may have references to this thread, for instance in some hist_entry
1057 * instances, so just move them to a separate list.
1058 */
1059 list_add_tail(&th->node, &machine->dead_threads);
1060}
1061
1062int machine__process_exit_event(struct machine *machine, union perf_event *event)
1063{ 1075{
1064 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1076 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1065 1077
@@ -1067,7 +1079,7 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event
1067 perf_event__fprintf_task(event, stdout); 1079 perf_event__fprintf_task(event, stdout);
1068 1080
1069 if (thread != NULL) 1081 if (thread != NULL)
1070 machine__remove_thread(machine, thread); 1082 thread__exited(thread);
1071 1083
1072 return 0; 1084 return 0;
1073} 1085}
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 925e0c3e6d91..381f4fda9654 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -8,6 +8,26 @@
8#include "cpumap.h" 8#include "cpumap.h"
9#include "thread_map.h" 9#include "thread_map.h"
10 10
11/*
12 * Support debug printing even though util/debug.c is not linked. That means
13 * implementing 'verbose' and 'eprintf'.
14 */
15int verbose;
16
17int eprintf(int level, const char *fmt, ...)
18{
19 va_list args;
20 int ret = 0;
21
22 if (verbose >= level) {
23 va_start(args, fmt);
24 ret = vfprintf(stderr, fmt, args);
25 va_end(args);
26 }
27
28 return ret;
29}
30
11/* Define PyVarObject_HEAD_INIT for python 2.5 */ 31/* Define PyVarObject_HEAD_INIT for python 2.5 */
12#ifndef PyVarObject_HEAD_INIT 32#ifndef PyVarObject_HEAD_INIT
13# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 33# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 6feeb88eb5b0..e3d4a550a703 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,12 +7,13 @@
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9 9
10struct thread *thread__new(pid_t tid) 10struct thread *thread__new(pid_t pid, pid_t tid)
11{ 11{
12 struct thread *self = zalloc(sizeof(*self)); 12 struct thread *self = zalloc(sizeof(*self));
13 13
14 if (self != NULL) { 14 if (self != NULL) {
15 map_groups__init(&self->mg); 15 map_groups__init(&self->mg);
16 self->pid_ = pid;
16 self->tid = tid; 17 self->tid = tid;
17 self->ppid = -1; 18 self->ppid = -1;
18 self->comm = malloc(32); 19 self->comm = malloc(32);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 13c62c909392..4ebbb40d46d4 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -12,10 +12,12 @@ struct thread {
12 struct list_head node; 12 struct list_head node;
13 }; 13 };
14 struct map_groups mg; 14 struct map_groups mg;
15 pid_t pid_; /* Not all tools update this */
15 pid_t tid; 16 pid_t tid;
16 pid_t ppid; 17 pid_t ppid;
17 char shortname[3]; 18 char shortname[3];
18 bool comm_set; 19 bool comm_set;
20 bool dead; /* if set thread has exited */
19 char *comm; 21 char *comm;
20 int comm_len; 22 int comm_len;
21 23
@@ -24,8 +26,12 @@ struct thread {
24 26
25struct machine; 27struct machine;
26 28
27struct thread *thread__new(pid_t tid); 29struct thread *thread__new(pid_t pid, pid_t tid);
28void thread__delete(struct thread *self); 30void thread__delete(struct thread *self);
31static inline void thread__exited(struct thread *thread)
32{
33 thread->dead = true;
34}
29 35
30int thread__set_comm(struct thread *self, const char *comm); 36int thread__set_comm(struct thread *self, const char *comm);
31int thread__comm_len(struct thread *self); 37int thread__comm_len(struct thread *self);