aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/api/fs/debugfs.c43
-rw-r--r--tools/lib/api/fs/debugfs.h3
-rw-r--r--tools/lib/traceevent/event-parse.c328
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt2
-rw-r--r--tools/perf/Documentation/perf-list.txt13
-rw-r--r--tools/perf/Documentation/perf-mem.txt9
-rw-r--r--tools/perf/Documentation/perf-record.txt19
-rw-r--r--tools/perf/Documentation/perf-script.txt28
-rw-r--r--tools/perf/Documentation/perf-stat.txt20
-rw-r--r--tools/perf/bench/futex.h13
-rw-r--r--tools/perf/builtin-buildid-cache.c4
-rw-r--r--tools/perf/builtin-diff.c248
-rw-r--r--tools/perf/builtin-inject.c5
-rw-r--r--tools/perf/builtin-mem.c131
-rw-r--r--tools/perf/builtin-record.c70
-rw-r--r--tools/perf/builtin-report.c16
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/builtin-trace.c106
-rw-r--r--tools/perf/config/Makefile6
-rw-r--r--tools/perf/config/feature-checks/Makefile4
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c14
-rw-r--r--tools/perf/tests/attr.py1
-rw-r--r--tools/perf/tests/hists_cumulate.c2
-rw-r--r--tools/perf/tests/hists_output.c2
-rw-r--r--tools/perf/tests/make1
-rw-r--r--tools/perf/tests/parse-events.c60
-rw-r--r--tools/perf/tests/sample-parsing.c2
-rw-r--r--tools/perf/ui/browsers/annotate.c3
-rw-r--r--tools/perf/ui/hist.c12
-rw-r--r--tools/perf/ui/progress.h4
-rw-r--r--tools/perf/ui/tui/helpline.c3
-rw-r--r--tools/perf/ui/tui/setup.c3
-rw-r--r--tools/perf/util/annotate.c2
-rw-r--r--tools/perf/util/color.c126
-rw-r--r--tools/perf/util/color.h2
-rw-r--r--tools/perf/util/dso.c6
-rw-r--r--tools/perf/util/dso.h1
-rw-r--r--tools/perf/util/evlist.c27
-rw-r--r--tools/perf/util/evlist.h1
-rw-r--r--tools/perf/util/evsel.c4
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.c48
-rw-r--r--tools/perf/util/hist.h11
-rw-r--r--tools/perf/util/parse-events.c27
-rw-r--r--tools/perf/util/parse-events.h3
-rw-r--r--tools/perf/util/parse-events.l1
-rw-r--r--tools/perf/util/parse-events.y26
-rw-r--r--tools/perf/util/parse-options.c2
-rw-r--r--tools/perf/util/pmu.c102
-rw-r--r--tools/perf/util/python.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
-rw-r--r--tools/perf/util/session.c8
-rw-r--r--tools/perf/util/session.h3
-rw-r--r--tools/perf/util/sort.c37
-rw-r--r--tools/perf/util/symbol-elf.c13
-rw-r--r--tools/perf/util/symbol.c2
-rw-r--r--tools/perf/util/unwind-libunwind.c31
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/cpus2use.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh18
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh9
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-build.sh20
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-console.sh2
64 files changed, 1213 insertions, 511 deletions
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
index 86ea2d7b8845..d2b18e887071 100644
--- a/tools/lib/api/fs/debugfs.c
+++ b/tools/lib/api/fs/debugfs.c
@@ -1,3 +1,4 @@
1#define _GNU_SOURCE
1#include <errno.h> 2#include <errno.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -98,3 +99,45 @@ char *debugfs_mount(const char *mountpoint)
98out: 99out:
99 return debugfs_mountpoint; 100 return debugfs_mountpoint;
100} 101}
102
103int debugfs__strerror_open(int err, char *buf, size_t size, const char *filename)
104{
105 char sbuf[128];
106
107 switch (err) {
108 case ENOENT:
109 if (debugfs_found) {
110 snprintf(buf, size,
111 "Error:\tFile %s/%s not found.\n"
112 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
113 debugfs_mountpoint, filename);
114 break;
115 }
116 snprintf(buf, size, "%s",
117 "Error:\tUnable to find debugfs\n"
118 "Hint:\tWas your kernel compiled with debugfs support?\n"
119 "Hint:\tIs the debugfs filesystem mounted?\n"
120 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
121 break;
122 case EACCES:
123 snprintf(buf, size,
124 "Error:\tNo permissions to read %s/%s\n"
125 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
126 debugfs_mountpoint, filename, debugfs_mountpoint);
127 break;
128 default:
129 snprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
130 break;
131 }
132
133 return 0;
134}
135
136int debugfs__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
137{
138 char path[PATH_MAX];
139
140 snprintf(path, PATH_MAX, "tracing/events/%s/%s", sys, name ?: "*");
141
142 return debugfs__strerror_open(err, buf, size, path);
143}
diff --git a/tools/lib/api/fs/debugfs.h b/tools/lib/api/fs/debugfs.h
index f19d3df9609d..0739881a9897 100644
--- a/tools/lib/api/fs/debugfs.h
+++ b/tools/lib/api/fs/debugfs.h
@@ -26,4 +26,7 @@ char *debugfs_mount(const char *mountpoint);
26 26
27extern char debugfs_mountpoint[]; 27extern char debugfs_mountpoint[];
28 28
29int debugfs__strerror_open(int err, char *buf, size_t size, const char *filename);
30int debugfs__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name);
31
29#endif /* __API_DEBUGFS_H__ */ 32#endif /* __API_DEBUGFS_H__ */
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index cf3a44bf1ec3..afe20ed9fac8 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -32,6 +32,7 @@
32#include <stdint.h> 32#include <stdint.h>
33#include <limits.h> 33#include <limits.h>
34 34
35#include <netinet/ip6.h>
35#include "event-parse.h" 36#include "event-parse.h"
36#include "event-utils.h" 37#include "event-utils.h"
37 38
@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
4149 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); 4150 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
4150} 4151}
4151 4152
4153static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf)
4154{
4155 const char *fmt;
4156
4157 if (i == 'i')
4158 fmt = "%03d.%03d.%03d.%03d";
4159 else
4160 fmt = "%d.%d.%d.%d";
4161
4162 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
4163}
4164
4165static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
4166{
4167 return ((unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
4168 (unsigned long)(a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0UL;
4169}
4170
4171static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
4172{
4173 return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
4174}
4175
4176static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
4177{
4178 int i, j, range;
4179 unsigned char zerolength[8];
4180 int longest = 1;
4181 int colonpos = -1;
4182 uint16_t word;
4183 uint8_t hi, lo;
4184 bool needcolon = false;
4185 bool useIPv4;
4186 struct in6_addr in6;
4187
4188 memcpy(&in6, addr, sizeof(struct in6_addr));
4189
4190 useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
4191
4192 memset(zerolength, 0, sizeof(zerolength));
4193
4194 if (useIPv4)
4195 range = 6;
4196 else
4197 range = 8;
4198
4199 /* find position of longest 0 run */
4200 for (i = 0; i < range; i++) {
4201 for (j = i; j < range; j++) {
4202 if (in6.s6_addr16[j] != 0)
4203 break;
4204 zerolength[i]++;
4205 }
4206 }
4207 for (i = 0; i < range; i++) {
4208 if (zerolength[i] > longest) {
4209 longest = zerolength[i];
4210 colonpos = i;
4211 }
4212 }
4213 if (longest == 1) /* don't compress a single 0 */
4214 colonpos = -1;
4215
4216 /* emit address */
4217 for (i = 0; i < range; i++) {
4218 if (i == colonpos) {
4219 if (needcolon || i == 0)
4220 trace_seq_printf(s, ":");
4221 trace_seq_printf(s, ":");
4222 needcolon = false;
4223 i += longest - 1;
4224 continue;
4225 }
4226 if (needcolon) {
4227 trace_seq_printf(s, ":");
4228 needcolon = false;
4229 }
4230 /* hex u16 without leading 0s */
4231 word = ntohs(in6.s6_addr16[i]);
4232 hi = word >> 8;
4233 lo = word & 0xff;
4234 if (hi)
4235 trace_seq_printf(s, "%x%02x", hi, lo);
4236 else
4237 trace_seq_printf(s, "%x", lo);
4238
4239 needcolon = true;
4240 }
4241
4242 if (useIPv4) {
4243 if (needcolon)
4244 trace_seq_printf(s, ":");
4245 print_ip4_addr(s, 'I', &in6.s6_addr[12]);
4246 }
4247
4248 return;
4249}
4250
4251static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
4252{
4253 int j;
4254
4255 for (j = 0; j < 16; j += 2) {
4256 trace_seq_printf(s, "%02x%02x", buf[j], buf[j+1]);
4257 if (i == 'I' && j < 14)
4258 trace_seq_printf(s, ":");
4259 }
4260}
4261
4262/*
4263 * %pi4 print an IPv4 address with leading zeros
4264 * %pI4 print an IPv4 address without leading zeros
4265 * %pi6 print an IPv6 address without colons
4266 * %pI6 print an IPv6 address with colons
4267 * %pI6c print an IPv6 address in compressed form with colons
4268 * %pISpc print an IP address based on sockaddr; p adds port.
4269 */
4270static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i,
4271 void *data, int size, struct event_format *event,
4272 struct print_arg *arg)
4273{
4274 unsigned char *buf;
4275
4276 if (arg->type == PRINT_FUNC) {
4277 process_defined_func(s, data, size, event, arg);
4278 return 0;
4279 }
4280
4281 if (arg->type != PRINT_FIELD) {
4282 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
4283 return 0;
4284 }
4285
4286 if (!arg->field.field) {
4287 arg->field.field =
4288 pevent_find_any_field(event, arg->field.name);
4289 if (!arg->field.field) {
4290 do_warning("%s: field %s not found",
4291 __func__, arg->field.name);
4292 return 0;
4293 }
4294 }
4295
4296 buf = data + arg->field.field->offset;
4297
4298 if (arg->field.field->size != 4) {
4299 trace_seq_printf(s, "INVALIDIPv4");
4300 return 0;
4301 }
4302 print_ip4_addr(s, i, buf);
4303
4304 return 0;
4305}
4306
4307static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i,
4308 void *data, int size, struct event_format *event,
4309 struct print_arg *arg)
4310{
4311 char have_c = 0;
4312 unsigned char *buf;
4313 int rc = 0;
4314
4315 /* pI6c */
4316 if (i == 'I' && *ptr == 'c') {
4317 have_c = 1;
4318 ptr++;
4319 rc++;
4320 }
4321
4322 if (arg->type == PRINT_FUNC) {
4323 process_defined_func(s, data, size, event, arg);
4324 return rc;
4325 }
4326
4327 if (arg->type != PRINT_FIELD) {
4328 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
4329 return rc;
4330 }
4331
4332 if (!arg->field.field) {
4333 arg->field.field =
4334 pevent_find_any_field(event, arg->field.name);
4335 if (!arg->field.field) {
4336 do_warning("%s: field %s not found",
4337 __func__, arg->field.name);
4338 return rc;
4339 }
4340 }
4341
4342 buf = data + arg->field.field->offset;
4343
4344 if (arg->field.field->size != 16) {
4345 trace_seq_printf(s, "INVALIDIPv6");
4346 return rc;
4347 }
4348
4349 if (have_c)
4350 print_ip6c_addr(s, buf);
4351 else
4352 print_ip6_addr(s, i, buf);
4353
4354 return rc;
4355}
4356
4357static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i,
4358 void *data, int size, struct event_format *event,
4359 struct print_arg *arg)
4360{
4361 char have_c = 0, have_p = 0;
4362 unsigned char *buf;
4363 struct sockaddr_storage *sa;
4364 int rc = 0;
4365
4366 /* pISpc */
4367 if (i == 'I') {
4368 if (*ptr == 'p') {
4369 have_p = 1;
4370 ptr++;
4371 rc++;
4372 }
4373 if (*ptr == 'c') {
4374 have_c = 1;
4375 ptr++;
4376 rc++;
4377 }
4378 }
4379
4380 if (arg->type == PRINT_FUNC) {
4381 process_defined_func(s, data, size, event, arg);
4382 return rc;
4383 }
4384
4385 if (arg->type != PRINT_FIELD) {
4386 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
4387 return rc;
4388 }
4389
4390 if (!arg->field.field) {
4391 arg->field.field =
4392 pevent_find_any_field(event, arg->field.name);
4393 if (!arg->field.field) {
4394 do_warning("%s: field %s not found",
4395 __func__, arg->field.name);
4396 return rc;
4397 }
4398 }
4399
4400 sa = (struct sockaddr_storage *) (data + arg->field.field->offset);
4401
4402 if (sa->ss_family == AF_INET) {
4403 struct sockaddr_in *sa4 = (struct sockaddr_in *) sa;
4404
4405 if (arg->field.field->size < sizeof(struct sockaddr_in)) {
4406 trace_seq_printf(s, "INVALIDIPv4");
4407 return rc;
4408 }
4409
4410 print_ip4_addr(s, i, (unsigned char *) &sa4->sin_addr);
4411 if (have_p)
4412 trace_seq_printf(s, ":%d", ntohs(sa4->sin_port));
4413
4414
4415 } else if (sa->ss_family == AF_INET6) {
4416 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
4417
4418 if (arg->field.field->size < sizeof(struct sockaddr_in6)) {
4419 trace_seq_printf(s, "INVALIDIPv6");
4420 return rc;
4421 }
4422
4423 if (have_p)
4424 trace_seq_printf(s, "[");
4425
4426 buf = (unsigned char *) &sa6->sin6_addr;
4427 if (have_c)
4428 print_ip6c_addr(s, buf);
4429 else
4430 print_ip6_addr(s, i, buf);
4431
4432 if (have_p)
4433 trace_seq_printf(s, "]:%d", ntohs(sa6->sin6_port));
4434 }
4435
4436 return rc;
4437}
4438
4439static int print_ip_arg(struct trace_seq *s, const char *ptr,
4440 void *data, int size, struct event_format *event,
4441 struct print_arg *arg)
4442{
4443 char i = *ptr; /* 'i' or 'I' */
4444 char ver;
4445 int rc = 0;
4446
4447 ptr++;
4448 rc++;
4449
4450 ver = *ptr;
4451 ptr++;
4452 rc++;
4453
4454 switch (ver) {
4455 case '4':
4456 rc += print_ipv4_arg(s, ptr, i, data, size, event, arg);
4457 break;
4458 case '6':
4459 rc += print_ipv6_arg(s, ptr, i, data, size, event, arg);
4460 break;
4461 case 'S':
4462 rc += print_ipsa_arg(s, ptr, i, data, size, event, arg);
4463 break;
4464 default:
4465 return 0;
4466 }
4467
4468 return rc;
4469}
4470
4152static int is_printable_array(char *p, unsigned int len) 4471static int is_printable_array(char *p, unsigned int len)
4153{ 4472{
4154 unsigned int i; 4473 unsigned int i;
@@ -4337,6 +4656,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4337 ptr++; 4656 ptr++;
4338 arg = arg->next; 4657 arg = arg->next;
4339 break; 4658 break;
4659 } else if (*(ptr+1) == 'I' || *(ptr+1) == 'i') {
4660 int n;
4661
4662 n = print_ip_arg(s, ptr+1, data, size, event, arg);
4663 if (n > 0) {
4664 ptr += n;
4665 arg = arg->next;
4666 break;
4667 }
4340 } 4668 }
4341 4669
4342 /* fall through */ 4670 /* fall through */
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index fd77d81ea748..0294c57b1f5e 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -38,7 +38,7 @@ OPTIONS
38--remove=:: 38--remove=::
39 Remove specified file from the cache. 39 Remove specified file from the cache.
40-M:: 40-M::
41--missing=:: 41--missing=::
42 List missing build ids in the cache for the specified file. 42 List missing build ids in the cache for the specified file.
43-u:: 43-u::
44--update:: 44--update::
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index cbb4f743d921..3e2aec94f806 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -89,6 +89,19 @@ raw encoding of 0x1A8 can be used:
89You should refer to the processor specific documentation for getting these 89You should refer to the processor specific documentation for getting these
90details. Some of them are referenced in the SEE ALSO section below. 90details. Some of them are referenced in the SEE ALSO section below.
91 91
92PARAMETERIZED EVENTS
93--------------------
94
95Some pmu events listed by 'perf-list' will be displayed with '?' in them. For
96example:
97
98 hv_gpci/dtbp_ptitc,phys_processor_idx=?/
99
100This means that when provided as an event, a value for '?' must
101also be supplied. For example:
102
103 perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
104
92OPTIONS 105OPTIONS
93------- 106-------
94 107
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 1d78a4064da4..43310d8661fe 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -12,11 +12,12 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15"perf mem -t <TYPE> record" runs a command and gathers memory operation data 15"perf mem record" runs a command and gathers memory operation data
16from it, into perf.data. Perf record options are accepted and are passed through. 16from it, into perf.data. Perf record options are accepted and are passed through.
17 17
18"perf mem -t <TYPE> report" displays the result. It invokes perf report with the 18"perf mem report" displays the result. It invokes perf report with the
19right set of options to display a memory access profile. 19right set of options to display a memory access profile. By default, loads
20and stores are sampled. Use the -t option to limit to loads or stores.
20 21
21Note that on Intel systems the memory latency reported is the use-latency, 22Note that on Intel systems the memory latency reported is the use-latency,
22not the pure load (or store latency). Use latency includes any pipeline 23not the pure load (or store latency). Use latency includes any pipeline
@@ -29,7 +30,7 @@ OPTIONS
29 30
30-t:: 31-t::
31--type=:: 32--type=::
32 Select the memory operation type: load or store (default: load) 33 Select the memory operation type: load or store (default: load,store)
33 34
34-D:: 35-D::
35--dump-raw-samples=:: 36--dump-raw-samples=::
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index af9a54ece024..31e977459c51 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -33,12 +33,27 @@ OPTIONS
33 - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a 33 - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
34 hexadecimal event descriptor. 34 hexadecimal event descriptor.
35 35
36 - a hardware breakpoint event in the form of '\mem:addr[:access]' 36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
37 'param1', 'param2', etc are defined as formats for the PMU in
38 /sys/bus/event_sources/devices/<pmu>/format/*.
39
40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
41
42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable
43 values for each of 'config', 'config1' and 'config2' are defined by
44 corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/*
45 param1 and param2 are defined as formats for the PMU in:
46 /sys/bus/event_sources/devices/<pmu>/format/*
47
48 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]'
37 where addr is the address in memory you want to break in. 49 where addr is the address in memory you want to break in.
38 Access is the memory access type (read, write, execute) it can 50 Access is the memory access type (read, write, execute) it can
39 be passed as follows: '\mem:addr[:[r][w][x]]'. 51 be passed as follows: '\mem:addr[:[r][w][x]]'. len is the range,
52 number of bytes from specified addr, which the breakpoint will cover.
40 If you want to profile read-write accesses in 0x1000, just set 53 If you want to profile read-write accesses in 0x1000, just set
41 'mem:0x1000:rw'. 54 'mem:0x1000:rw'.
55 If you want to profile write accesses in [0x1000~1008), just set
56 'mem:0x1000/8:w'.
42 57
43--filter=<filter>:: 58--filter=<filter>::
44 Event filter. 59 Event filter.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 21494806c0ab..a21eec05bc42 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -125,46 +125,46 @@ OPTIONS
125 is equivalent to: 125 is equivalent to:
126 126
127 perf script -f trace:<fields> -f sw:<fields> -f hw:<fields> 127 perf script -f trace:<fields> -f sw:<fields> -f hw:<fields>
128 128
129 i.e., the specified fields apply to all event types if the type string 129 i.e., the specified fields apply to all event types if the type string
130 is not given. 130 is not given.
131 131
132 The arguments are processed in the order received. A later usage can 132 The arguments are processed in the order received. A later usage can
133 reset a prior request. e.g.: 133 reset a prior request. e.g.:
134 134
135 -f trace: -f comm,tid,time,ip,sym 135 -f trace: -f comm,tid,time,ip,sym
136 136
137 The first -f suppresses trace events (field list is ""), but then the 137 The first -f suppresses trace events (field list is ""), but then the
138 second invocation sets the fields to comm,tid,time,ip,sym. In this case a 138 second invocation sets the fields to comm,tid,time,ip,sym. In this case a
139 warning is given to the user: 139 warning is given to the user:
140 140
141 "Overriding previous field request for all events." 141 "Overriding previous field request for all events."
142 142
143 Alternatively, consider the order: 143 Alternatively, consider the order:
144 144
145 -f comm,tid,time,ip,sym -f trace: 145 -f comm,tid,time,ip,sym -f trace:
146 146
147 The first -f sets the fields for all events and the second -f 147 The first -f sets the fields for all events and the second -f
148 suppresses trace events. The user is given a warning message about 148 suppresses trace events. The user is given a warning message about
149 the override, and the result of the above is that only S/W and H/W 149 the override, and the result of the above is that only S/W and H/W
150 events are displayed with the given fields. 150 events are displayed with the given fields.
151 151
152 For the 'wildcard' option if a user selected field is invalid for an 152 For the 'wildcard' option if a user selected field is invalid for an
153 event type, a message is displayed to the user that the option is 153 event type, a message is displayed to the user that the option is
154 ignored for that type. For example: 154 ignored for that type. For example:
155 155
156 $ perf script -f comm,tid,trace 156 $ perf script -f comm,tid,trace
157 'trace' not valid for hardware events. Ignoring. 157 'trace' not valid for hardware events. Ignoring.
158 'trace' not valid for software events. Ignoring. 158 'trace' not valid for software events. Ignoring.
159 159
160 Alternatively, if the type is given an invalid field is specified it 160 Alternatively, if the type is given an invalid field is specified it
161 is an error. For example: 161 is an error. For example:
162 162
163 perf script -v -f sw:comm,tid,trace 163 perf script -v -f sw:comm,tid,trace
164 'trace' not valid for software events. 164 'trace' not valid for software events.
165 165
166 At this point usage is displayed, and perf-script exits. 166 At this point usage is displayed, and perf-script exits.
167 167
168 Finally, a user may not set fields to none for all event types. 168 Finally, a user may not set fields to none for all event types.
169 i.e., -f "" is not allowed. 169 i.e., -f "" is not allowed.
170 170
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 29ee857c09c6..04e150d83e7d 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -25,10 +25,22 @@ OPTIONS
25 25
26-e:: 26-e::
27--event=:: 27--event=::
28 Select the PMU event. Selection can be a symbolic event name 28 Select the PMU event. Selection can be:
29 (use 'perf list' to list all events) or a raw PMU 29
30 event (eventsel+umask) in the form of rNNN where NNN is a 30 - a symbolic event name (use 'perf list' to list all events)
31 hexadecimal event descriptor. 31
32 - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
33 hexadecimal event descriptor.
34
35 - a symbolically formed event like 'pmu/param1=0x3,param2/' where
36 param1 and param2 are defined as formats for the PMU in
37 /sys/bus/event_sources/devices/<pmu>/format/*
38
39 - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/'
40 where M, N, K are numbers (in decimal, hex, octal format).
41 Acceptable values for each of 'config', 'config1' and 'config2'
42 parameters are defined by corresponding entries in
43 /sys/bus/event_sources/devices/<pmu>/format/*
32 44
33-i:: 45-i::
34--no-inherit:: 46--no-inherit::
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index 71f2844cf97f..7ed22ff1e1ac 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -68,4 +68,17 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
68 val, opflags); 68 val, opflags);
69} 69}
70 70
71#ifndef HAVE_PTHREAD_ATTR_SETAFFINITY_NP
72#include <pthread.h>
73static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr,
74 size_t cpusetsize,
75 cpu_set_t *cpuset)
76{
77 attr = attr;
78 cpusetsize = cpusetsize;
79 cpuset = cpuset;
80 return 0;
81}
82#endif
83
71#endif /* _FUTEX_H */ 84#endif /* _FUTEX_H */
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 77d5cae54c6a..50e6b66aea1f 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -236,10 +236,10 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
236 if (errno == ENOENT) 236 if (errno == ENOENT)
237 return false; 237 return false;
238 238
239 pr_warning("Problems with %s file, consider removing it from the cache\n", 239 pr_warning("Problems with %s file, consider removing it from the cache\n",
240 filename); 240 filename);
241 } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) { 241 } else if (memcmp(dso->build_id, build_id, sizeof(dso->build_id))) {
242 pr_warning("Problems with %s file, consider removing it from the cache\n", 242 pr_warning("Problems with %s file, consider removing it from the cache\n",
243 filename); 243 filename);
244 } 244 }
245 245
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 1fd96c13f199..74aada554b12 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -390,6 +390,15 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
390 } 390 }
391} 391}
392 392
393static struct data__file *fmt_to_data_file(struct perf_hpp_fmt *fmt)
394{
395 struct diff_hpp_fmt *dfmt = container_of(fmt, struct diff_hpp_fmt, fmt);
396 void *ptr = dfmt - dfmt->idx;
397 struct data__file *d = container_of(ptr, struct data__file, fmt);
398
399 return d;
400}
401
393static struct hist_entry* 402static struct hist_entry*
394get_pair_data(struct hist_entry *he, struct data__file *d) 403get_pair_data(struct hist_entry *he, struct data__file *d)
395{ 404{
@@ -407,8 +416,7 @@ get_pair_data(struct hist_entry *he, struct data__file *d)
407static struct hist_entry* 416static struct hist_entry*
408get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt) 417get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
409{ 418{
410 void *ptr = dfmt - dfmt->idx; 419 struct data__file *d = fmt_to_data_file(&dfmt->fmt);
411 struct data__file *d = container_of(ptr, struct data__file, fmt);
412 420
413 return get_pair_data(he, d); 421 return get_pair_data(he, d);
414} 422}
@@ -430,7 +438,7 @@ static void hists__baseline_only(struct hists *hists)
430 next = rb_next(&he->rb_node_in); 438 next = rb_next(&he->rb_node_in);
431 if (!hist_entry__next_pair(he)) { 439 if (!hist_entry__next_pair(he)) {
432 rb_erase(&he->rb_node_in, root); 440 rb_erase(&he->rb_node_in, root);
433 hist_entry__free(he); 441 hist_entry__delete(he);
434 } 442 }
435 } 443 }
436} 444}
@@ -448,26 +456,30 @@ static void hists__precompute(struct hists *hists)
448 next = rb_first(root); 456 next = rb_first(root);
449 while (next != NULL) { 457 while (next != NULL) {
450 struct hist_entry *he, *pair; 458 struct hist_entry *he, *pair;
459 struct data__file *d;
460 int i;
451 461
452 he = rb_entry(next, struct hist_entry, rb_node_in); 462 he = rb_entry(next, struct hist_entry, rb_node_in);
453 next = rb_next(&he->rb_node_in); 463 next = rb_next(&he->rb_node_in);
454 464
455 pair = get_pair_data(he, &data__files[sort_compute]); 465 data__for_each_file_new(i, d) {
456 if (!pair) 466 pair = get_pair_data(he, d);
457 continue; 467 if (!pair)
468 continue;
458 469
459 switch (compute) { 470 switch (compute) {
460 case COMPUTE_DELTA: 471 case COMPUTE_DELTA:
461 compute_delta(he, pair); 472 compute_delta(he, pair);
462 break; 473 break;
463 case COMPUTE_RATIO: 474 case COMPUTE_RATIO:
464 compute_ratio(he, pair); 475 compute_ratio(he, pair);
465 break; 476 break;
466 case COMPUTE_WEIGHTED_DIFF: 477 case COMPUTE_WEIGHTED_DIFF:
467 compute_wdiff(he, pair); 478 compute_wdiff(he, pair);
468 break; 479 break;
469 default: 480 default:
470 BUG_ON(1); 481 BUG_ON(1);
482 }
471 } 483 }
472 } 484 }
473} 485}
@@ -517,7 +529,7 @@ __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
517 529
518static int64_t 530static int64_t
519hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, 531hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
520 int c) 532 int c, int sort_idx)
521{ 533{
522 bool pairs_left = hist_entry__has_pairs(left); 534 bool pairs_left = hist_entry__has_pairs(left);
523 bool pairs_right = hist_entry__has_pairs(right); 535 bool pairs_right = hist_entry__has_pairs(right);
@@ -529,8 +541,8 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
529 if (!pairs_left || !pairs_right) 541 if (!pairs_left || !pairs_right)
530 return pairs_left ? -1 : 1; 542 return pairs_left ? -1 : 1;
531 543
532 p_left = get_pair_data(left, &data__files[sort_compute]); 544 p_left = get_pair_data(left, &data__files[sort_idx]);
533 p_right = get_pair_data(right, &data__files[sort_compute]); 545 p_right = get_pair_data(right, &data__files[sort_idx]);
534 546
535 if (!p_left && !p_right) 547 if (!p_left && !p_right)
536 return 0; 548 return 0;
@@ -546,90 +558,102 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
546} 558}
547 559
548static int64_t 560static int64_t
549hist_entry__cmp_nop(struct hist_entry *left __maybe_unused, 561hist_entry__cmp_compute_idx(struct hist_entry *left, struct hist_entry *right,
562 int c, int sort_idx)
563{
564 struct hist_entry *p_right, *p_left;
565
566 p_left = get_pair_data(left, &data__files[sort_idx]);
567 p_right = get_pair_data(right, &data__files[sort_idx]);
568
569 if (!p_left && !p_right)
570 return 0;
571
572 if (!p_left || !p_right)
573 return p_left ? -1 : 1;
574
575 if (c != COMPUTE_DELTA) {
576 /*
577 * The delta can be computed without the baseline, but
578 * others are not. Put those entries which have no
579 * values below.
580 */
581 if (left->dummy && right->dummy)
582 return 0;
583
584 if (left->dummy || right->dummy)
585 return left->dummy ? 1 : -1;
586 }
587
588 return __hist_entry__cmp_compute(p_left, p_right, c);
589}
590
591static int64_t
592hist_entry__cmp_nop(struct perf_hpp_fmt *fmt __maybe_unused,
593 struct hist_entry *left __maybe_unused,
550 struct hist_entry *right __maybe_unused) 594 struct hist_entry *right __maybe_unused)
551{ 595{
552 return 0; 596 return 0;
553} 597}
554 598
555static int64_t 599static int64_t
556hist_entry__cmp_baseline(struct hist_entry *left, struct hist_entry *right) 600hist_entry__cmp_baseline(struct perf_hpp_fmt *fmt __maybe_unused,
601 struct hist_entry *left, struct hist_entry *right)
557{ 602{
558 if (sort_compute)
559 return 0;
560
561 if (left->stat.period == right->stat.period) 603 if (left->stat.period == right->stat.period)
562 return 0; 604 return 0;
563 return left->stat.period > right->stat.period ? 1 : -1; 605 return left->stat.period > right->stat.period ? 1 : -1;
564} 606}
565 607
566static int64_t 608static int64_t
567hist_entry__cmp_delta(struct hist_entry *left, struct hist_entry *right) 609hist_entry__cmp_delta(struct perf_hpp_fmt *fmt,
610 struct hist_entry *left, struct hist_entry *right)
568{ 611{
569 return hist_entry__cmp_compute(right, left, COMPUTE_DELTA); 612 struct data__file *d = fmt_to_data_file(fmt);
613
614 return hist_entry__cmp_compute(right, left, COMPUTE_DELTA, d->idx);
570} 615}
571 616
572static int64_t 617static int64_t
573hist_entry__cmp_ratio(struct hist_entry *left, struct hist_entry *right) 618hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt,
619 struct hist_entry *left, struct hist_entry *right)
574{ 620{
575 return hist_entry__cmp_compute(right, left, COMPUTE_RATIO); 621 struct data__file *d = fmt_to_data_file(fmt);
622
623 return hist_entry__cmp_compute(right, left, COMPUTE_RATIO, d->idx);
576} 624}
577 625
578static int64_t 626static int64_t
579hist_entry__cmp_wdiff(struct hist_entry *left, struct hist_entry *right) 627hist_entry__cmp_wdiff(struct perf_hpp_fmt *fmt,
628 struct hist_entry *left, struct hist_entry *right)
580{ 629{
581 return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF); 630 struct data__file *d = fmt_to_data_file(fmt);
631
632 return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF, d->idx);
582} 633}
583 634
584static void insert_hist_entry_by_compute(struct rb_root *root, 635static int64_t
585 struct hist_entry *he, 636hist_entry__cmp_delta_idx(struct perf_hpp_fmt *fmt __maybe_unused,
586 int c) 637 struct hist_entry *left, struct hist_entry *right)
587{ 638{
588 struct rb_node **p = &root->rb_node; 639 return hist_entry__cmp_compute_idx(right, left, COMPUTE_DELTA,
589 struct rb_node *parent = NULL; 640 sort_compute);
590 struct hist_entry *iter;
591
592 while (*p != NULL) {
593 parent = *p;
594 iter = rb_entry(parent, struct hist_entry, rb_node);
595 if (hist_entry__cmp_compute(he, iter, c) < 0)
596 p = &(*p)->rb_left;
597 else
598 p = &(*p)->rb_right;
599 }
600
601 rb_link_node(&he->rb_node, parent, p);
602 rb_insert_color(&he->rb_node, root);
603} 641}
604 642
605static void hists__compute_resort(struct hists *hists) 643static int64_t
644hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused,
645 struct hist_entry *left, struct hist_entry *right)
606{ 646{
607 struct rb_root *root; 647 return hist_entry__cmp_compute_idx(right, left, COMPUTE_RATIO,
608 struct rb_node *next; 648 sort_compute);
609 649}
610 if (sort__need_collapse)
611 root = &hists->entries_collapsed;
612 else
613 root = hists->entries_in;
614
615 hists->entries = RB_ROOT;
616 next = rb_first(root);
617
618 hists__reset_stats(hists);
619 hists__reset_col_len(hists);
620
621 while (next != NULL) {
622 struct hist_entry *he;
623
624 he = rb_entry(next, struct hist_entry, rb_node_in);
625 next = rb_next(&he->rb_node_in);
626
627 insert_hist_entry_by_compute(&hists->entries, he, compute);
628 hists__inc_stats(hists, he);
629 650
630 if (!he->filtered) 651static int64_t
631 hists__calc_col_len(hists, he); 652hist_entry__cmp_wdiff_idx(struct perf_hpp_fmt *fmt __maybe_unused,
632 } 653 struct hist_entry *left, struct hist_entry *right)
654{
655 return hist_entry__cmp_compute_idx(right, left, COMPUTE_WEIGHTED_DIFF,
656 sort_compute);
633} 657}
634 658
635static void hists__process(struct hists *hists) 659static void hists__process(struct hists *hists)
@@ -637,12 +661,8 @@ static void hists__process(struct hists *hists)
637 if (show_baseline_only) 661 if (show_baseline_only)
638 hists__baseline_only(hists); 662 hists__baseline_only(hists);
639 663
640 if (sort_compute) { 664 hists__precompute(hists);
641 hists__precompute(hists); 665 hists__output_resort(hists, NULL);
642 hists__compute_resort(hists);
643 } else {
644 hists__output_resort(hists, NULL);
645 }
646 666
647 hists__fprintf(hists, true, 0, 0, 0, stdout); 667 hists__fprintf(hists, true, 0, 0, 0, stdout);
648} 668}
@@ -841,7 +861,7 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
841 char pfmt[20] = " "; 861 char pfmt[20] = " ";
842 862
843 if (!pair) 863 if (!pair)
844 goto dummy_print; 864 goto no_print;
845 865
846 switch (comparison_method) { 866 switch (comparison_method) {
847 case COMPUTE_DELTA: 867 case COMPUTE_DELTA:
@@ -850,8 +870,6 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
850 else 870 else
851 diff = compute_delta(he, pair); 871 diff = compute_delta(he, pair);
852 872
853 if (fabs(diff) < 0.01)
854 goto dummy_print;
855 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1); 873 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1);
856 return percent_color_snprintf(hpp->buf, hpp->size, 874 return percent_color_snprintf(hpp->buf, hpp->size,
857 pfmt, diff); 875 pfmt, diff);
@@ -883,6 +901,9 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
883 } 901 }
884dummy_print: 902dummy_print:
885 return scnprintf(hpp->buf, hpp->size, "%*s", 903 return scnprintf(hpp->buf, hpp->size, "%*s",
904 dfmt->header_width, "N/A");
905no_print:
906 return scnprintf(hpp->buf, hpp->size, "%*s",
886 dfmt->header_width, pfmt); 907 dfmt->header_width, pfmt);
887} 908}
888 909
@@ -932,14 +953,15 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
932 else 953 else
933 diff = compute_delta(he, pair); 954 diff = compute_delta(he, pair);
934 955
935 if (fabs(diff) >= 0.01) 956 scnprintf(buf, size, "%+4.2F%%", diff);
936 scnprintf(buf, size, "%+4.2F%%", diff);
937 break; 957 break;
938 958
939 case PERF_HPP_DIFF__RATIO: 959 case PERF_HPP_DIFF__RATIO:
940 /* No point for ratio number if we are dummy.. */ 960 /* No point for ratio number if we are dummy.. */
941 if (he->dummy) 961 if (he->dummy) {
962 scnprintf(buf, size, "N/A");
942 break; 963 break;
964 }
943 965
944 if (pair->diff.computed) 966 if (pair->diff.computed)
945 ratio = pair->diff.period_ratio; 967 ratio = pair->diff.period_ratio;
@@ -952,8 +974,10 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
952 974
953 case PERF_HPP_DIFF__WEIGHTED_DIFF: 975 case PERF_HPP_DIFF__WEIGHTED_DIFF:
954 /* No point for wdiff number if we are dummy.. */ 976 /* No point for wdiff number if we are dummy.. */
955 if (he->dummy) 977 if (he->dummy) {
978 scnprintf(buf, size, "N/A");
956 break; 979 break;
980 }
957 981
958 if (pair->diff.computed) 982 if (pair->diff.computed)
959 wdiff = pair->diff.wdiff; 983 wdiff = pair->diff.wdiff;
@@ -1105,9 +1129,10 @@ static void data__hpp_register(struct data__file *d, int idx)
1105 perf_hpp__register_sort_field(fmt); 1129 perf_hpp__register_sort_field(fmt);
1106} 1130}
1107 1131
1108static void ui_init(void) 1132static int ui_init(void)
1109{ 1133{
1110 struct data__file *d; 1134 struct data__file *d;
1135 struct perf_hpp_fmt *fmt;
1111 int i; 1136 int i;
1112 1137
1113 data__for_each_file(i, d) { 1138 data__for_each_file(i, d) {
@@ -1137,6 +1162,46 @@ static void ui_init(void)
1137 data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD : 1162 data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD :
1138 PERF_HPP_DIFF__PERIOD_BASELINE); 1163 PERF_HPP_DIFF__PERIOD_BASELINE);
1139 } 1164 }
1165
1166 if (!sort_compute)
1167 return 0;
1168
1169 /*
1170 * Prepend an fmt to sort on columns at 'sort_compute' first.
1171 * This fmt is added only to the sort list but not to the
1172 * output fields list.
1173 *
1174 * Note that this column (data) can be compared twice - one
1175 * for this 'sort_compute' fmt and another for the normal
1176 * diff_hpp_fmt. But it shouldn't a problem as most entries
1177 * will be sorted out by first try or baseline and comparing
1178 * is not a costly operation.
1179 */
1180 fmt = zalloc(sizeof(*fmt));
1181 if (fmt == NULL) {
1182 pr_err("Memory allocation failed\n");
1183 return -1;
1184 }
1185
1186 fmt->cmp = hist_entry__cmp_nop;
1187 fmt->collapse = hist_entry__cmp_nop;
1188
1189 switch (compute) {
1190 case COMPUTE_DELTA:
1191 fmt->sort = hist_entry__cmp_delta_idx;
1192 break;
1193 case COMPUTE_RATIO:
1194 fmt->sort = hist_entry__cmp_ratio_idx;
1195 break;
1196 case COMPUTE_WEIGHTED_DIFF:
1197 fmt->sort = hist_entry__cmp_wdiff_idx;
1198 break;
1199 default:
1200 BUG_ON(1);
1201 }
1202
1203 list_add(&fmt->sort_list, &perf_hpp__sort_list);
1204 return 0;
1140} 1205}
1141 1206
1142static int data_init(int argc, const char **argv) 1207static int data_init(int argc, const char **argv)
@@ -1202,7 +1267,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1202 if (data_init(argc, argv) < 0) 1267 if (data_init(argc, argv) < 0)
1203 return -1; 1268 return -1;
1204 1269
1205 ui_init(); 1270 if (ui_init() < 0)
1271 return -1;
1206 1272
1207 sort__mode = SORT_MODE__DIFF; 1273 sort__mode = SORT_MODE__DIFF;
1208 1274
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 84df2deed988..a13641e066f5 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -343,6 +343,7 @@ static int __cmd_inject(struct perf_inject *inject)
343 int ret = -EINVAL; 343 int ret = -EINVAL;
344 struct perf_session *session = inject->session; 344 struct perf_session *session = inject->session;
345 struct perf_data_file *file_out = &inject->output; 345 struct perf_data_file *file_out = &inject->output;
346 int fd = perf_data_file__fd(file_out);
346 347
347 signal(SIGINT, sig_handler); 348 signal(SIGINT, sig_handler);
348 349
@@ -376,7 +377,7 @@ static int __cmd_inject(struct perf_inject *inject)
376 } 377 }
377 378
378 if (!file_out->is_pipe) 379 if (!file_out->is_pipe)
379 lseek(file_out->fd, session->header.data_offset, SEEK_SET); 380 lseek(fd, session->header.data_offset, SEEK_SET);
380 381
381 ret = perf_session__process_events(session, &inject->tool); 382 ret = perf_session__process_events(session, &inject->tool);
382 383
@@ -385,7 +386,7 @@ static int __cmd_inject(struct perf_inject *inject)
385 perf_header__set_feat(&session->header, 386 perf_header__set_feat(&session->header,
386 HEADER_BUILD_ID); 387 HEADER_BUILD_ID);
387 session->header.data_size = inject->bytes_written; 388 session->header.data_size = inject->bytes_written;
388 perf_session__write_header(session, session->evlist, file_out->fd, true); 389 perf_session__write_header(session, session->evlist, fd, true);
389 } 390 }
390 391
391 return ret; 392 return ret;
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 24db6ffe2957..9b5663950a4d 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -7,44 +7,47 @@
7#include "util/session.h" 7#include "util/session.h"
8#include "util/data.h" 8#include "util/data.h"
9 9
10#define MEM_OPERATION_LOAD "load" 10#define MEM_OPERATION_LOAD 0x1
11#define MEM_OPERATION_STORE "store" 11#define MEM_OPERATION_STORE 0x2
12
13static const char *mem_operation = MEM_OPERATION_LOAD;
14 12
15struct perf_mem { 13struct perf_mem {
16 struct perf_tool tool; 14 struct perf_tool tool;
17 char const *input_name; 15 char const *input_name;
18 bool hide_unresolved; 16 bool hide_unresolved;
19 bool dump_raw; 17 bool dump_raw;
18 int operation;
20 const char *cpu_list; 19 const char *cpu_list;
21 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 20 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
22}; 21};
23 22
24static int __cmd_record(int argc, const char **argv) 23static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
25{ 24{
26 int rec_argc, i = 0, j; 25 int rec_argc, i = 0, j;
27 const char **rec_argv; 26 const char **rec_argv;
28 char event[64];
29 int ret; 27 int ret;
30 28
31 rec_argc = argc + 4; 29 rec_argc = argc + 7; /* max number of arguments */
32 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 30 rec_argv = calloc(rec_argc + 1, sizeof(char *));
33 if (!rec_argv) 31 if (!rec_argv)
34 return -1; 32 return -1;
35 33
36 rec_argv[i++] = strdup("record"); 34 rec_argv[i++] = "record";
37 if (!strcmp(mem_operation, MEM_OPERATION_LOAD))
38 rec_argv[i++] = strdup("-W");
39 rec_argv[i++] = strdup("-d");
40 rec_argv[i++] = strdup("-e");
41 35
42 if (strcmp(mem_operation, MEM_OPERATION_LOAD)) 36 if (mem->operation & MEM_OPERATION_LOAD)
43 sprintf(event, "cpu/mem-stores/pp"); 37 rec_argv[i++] = "-W";
44 else 38
45 sprintf(event, "cpu/mem-loads/pp"); 39 rec_argv[i++] = "-d";
40
41 if (mem->operation & MEM_OPERATION_LOAD) {
42 rec_argv[i++] = "-e";
43 rec_argv[i++] = "cpu/mem-loads/pp";
44 }
45
46 if (mem->operation & MEM_OPERATION_STORE) {
47 rec_argv[i++] = "-e";
48 rec_argv[i++] = "cpu/mem-stores/pp";
49 }
46 50
47 rec_argv[i++] = strdup(event);
48 for (j = 1; j < argc; j++, i++) 51 for (j = 1; j < argc; j++, i++)
49 rec_argv[i] = argv[j]; 52 rec_argv[i] = argv[j];
50 53
@@ -162,17 +165,17 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
162 if (!rep_argv) 165 if (!rep_argv)
163 return -1; 166 return -1;
164 167
165 rep_argv[i++] = strdup("report"); 168 rep_argv[i++] = "report";
166 rep_argv[i++] = strdup("--mem-mode"); 169 rep_argv[i++] = "--mem-mode";
167 rep_argv[i++] = strdup("-n"); /* display number of samples */ 170 rep_argv[i++] = "-n"; /* display number of samples */
168 171
169 /* 172 /*
170 * there is no weight (cost) associated with stores, so don't print 173 * there is no weight (cost) associated with stores, so don't print
171 * the column 174 * the column
172 */ 175 */
173 if (strcmp(mem_operation, MEM_OPERATION_LOAD)) 176 if (!(mem->operation & MEM_OPERATION_LOAD))
174 rep_argv[i++] = strdup("--sort=mem,sym,dso,symbol_daddr," 177 rep_argv[i++] = "--sort=mem,sym,dso,symbol_daddr,"
175 "dso_daddr,tlb,locked"); 178 "dso_daddr,tlb,locked";
176 179
177 for (j = 1; j < argc; j++, i++) 180 for (j = 1; j < argc; j++, i++)
178 rep_argv[i] = argv[j]; 181 rep_argv[i] = argv[j];
@@ -182,6 +185,75 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
182 return ret; 185 return ret;
183} 186}
184 187
188struct mem_mode {
189 const char *name;
190 int mode;
191};
192
193#define MEM_OPT(n, m) \
194 { .name = n, .mode = (m) }
195
196#define MEM_END { .name = NULL }
197
198static const struct mem_mode mem_modes[]={
199 MEM_OPT("load", MEM_OPERATION_LOAD),
200 MEM_OPT("store", MEM_OPERATION_STORE),
201 MEM_END
202};
203
204static int
205parse_mem_ops(const struct option *opt, const char *str, int unset)
206{
207 int *mode = (int *)opt->value;
208 const struct mem_mode *m;
209 char *s, *os = NULL, *p;
210 int ret = -1;
211
212 if (unset)
213 return 0;
214
215 /* str may be NULL in case no arg is passed to -t */
216 if (str) {
217 /* because str is read-only */
218 s = os = strdup(str);
219 if (!s)
220 return -1;
221
222 /* reset mode */
223 *mode = 0;
224
225 for (;;) {
226 p = strchr(s, ',');
227 if (p)
228 *p = '\0';
229
230 for (m = mem_modes; m->name; m++) {
231 if (!strcasecmp(s, m->name))
232 break;
233 }
234 if (!m->name) {
235 fprintf(stderr, "unknown sampling op %s,"
236 " check man page\n", s);
237 goto error;
238 }
239
240 *mode |= m->mode;
241
242 if (!p)
243 break;
244
245 s = p + 1;
246 }
247 }
248 ret = 0;
249
250 if (*mode == 0)
251 *mode = MEM_OPERATION_LOAD;
252error:
253 free(os);
254 return ret;
255}
256
185int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) 257int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
186{ 258{
187 struct stat st; 259 struct stat st;
@@ -197,10 +269,15 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
197 .ordered_events = true, 269 .ordered_events = true,
198 }, 270 },
199 .input_name = "perf.data", 271 .input_name = "perf.data",
272 /*
273 * default to both load an store sampling
274 */
275 .operation = MEM_OPERATION_LOAD | MEM_OPERATION_STORE,
200 }; 276 };
201 const struct option mem_options[] = { 277 const struct option mem_options[] = {
202 OPT_STRING('t', "type", &mem_operation, 278 OPT_CALLBACK('t', "type", &mem.operation,
203 "type", "memory operations(load/store)"), 279 "type", "memory operations(load,store) Default load,store",
280 parse_mem_ops),
204 OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw, 281 OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw,
205 "dump raw samples in ASCII"), 282 "dump raw samples in ASCII"),
206 OPT_BOOLEAN('U', "hide-unresolved", &mem.hide_unresolved, 283 OPT_BOOLEAN('U', "hide-unresolved", &mem.hide_unresolved,
@@ -225,7 +302,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
225 argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, 302 argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
226 mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); 303 mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);
227 304
228 if (!argc || !(strncmp(argv[0], "rec", 3) || mem_operation)) 305 if (!argc || !(strncmp(argv[0], "rec", 3) || mem.operation))
229 usage_with_options(mem_usage, mem_options); 306 usage_with_options(mem_usage, mem_options);
230 307
231 if (!mem.input_name || !strlen(mem.input_name)) { 308 if (!mem.input_name || !strlen(mem.input_name)) {
@@ -236,7 +313,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
236 } 313 }
237 314
238 if (!strncmp(argv[0], "rec", 3)) 315 if (!strncmp(argv[0], "rec", 3))
239 return __cmd_record(argc, argv); 316 return __cmd_record(argc, argv, &mem);
240 else if (!strncmp(argv[0], "rep", 3)) 317 else if (!strncmp(argv[0], "rep", 3))
241 return report_events(argc, argv, &mem); 318 return report_events(argc, argv, &mem);
242 else 319 else
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8648c6d3003d..404ab3434052 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -190,16 +190,30 @@ out:
190 return rc; 190 return rc;
191} 191}
192 192
193static int process_sample_event(struct perf_tool *tool,
194 union perf_event *event,
195 struct perf_sample *sample,
196 struct perf_evsel *evsel,
197 struct machine *machine)
198{
199 struct record *rec = container_of(tool, struct record, tool);
200
201 rec->samples++;
202
203 return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
204}
205
193static int process_buildids(struct record *rec) 206static int process_buildids(struct record *rec)
194{ 207{
195 struct perf_data_file *file = &rec->file; 208 struct perf_data_file *file = &rec->file;
196 struct perf_session *session = rec->session; 209 struct perf_session *session = rec->session;
197 u64 start = session->header.data_offset;
198 210
199 u64 size = lseek(file->fd, 0, SEEK_CUR); 211 u64 size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
200 if (size == 0) 212 if (size == 0)
201 return 0; 213 return 0;
202 214
215 file->size = size;
216
203 /* 217 /*
204 * During this process, it'll load kernel map and replace the 218 * During this process, it'll load kernel map and replace the
205 * dso->long_name to a real pathname it found. In this case 219 * dso->long_name to a real pathname it found. In this case
@@ -211,9 +225,7 @@ static int process_buildids(struct record *rec)
211 */ 225 */
212 symbol_conf.ignore_vmlinux_buildid = true; 226 symbol_conf.ignore_vmlinux_buildid = true;
213 227
214 return __perf_session__process_events(session, start, 228 return perf_session__process_events(session, &rec->tool);
215 size - start,
216 size, &build_id__mark_dso_hit_ops);
217} 229}
218 230
219static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 231static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
@@ -322,6 +334,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
322 struct perf_data_file *file = &rec->file; 334 struct perf_data_file *file = &rec->file;
323 struct perf_session *session; 335 struct perf_session *session;
324 bool disabled = false, draining = false; 336 bool disabled = false, draining = false;
337 int fd;
325 338
326 rec->progname = argv[0]; 339 rec->progname = argv[0];
327 340
@@ -336,6 +349,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
336 return -1; 349 return -1;
337 } 350 }
338 351
352 fd = perf_data_file__fd(file);
339 rec->session = session; 353 rec->session = session;
340 354
341 record__init_features(rec); 355 record__init_features(rec);
@@ -360,12 +374,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
360 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 374 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
361 375
362 if (file->is_pipe) { 376 if (file->is_pipe) {
363 err = perf_header__write_pipe(file->fd); 377 err = perf_header__write_pipe(fd);
364 if (err < 0) 378 if (err < 0)
365 goto out_child; 379 goto out_child;
366 } else { 380 } else {
367 err = perf_session__write_header(session, rec->evlist, 381 err = perf_session__write_header(session, rec->evlist, fd, false);
368 file->fd, false);
369 if (err < 0) 382 if (err < 0)
370 goto out_child; 383 goto out_child;
371 } 384 }
@@ -397,7 +410,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
397 * return this more properly and also 410 * return this more properly and also
398 * propagate errors that now are calling die() 411 * propagate errors that now are calling die()
399 */ 412 */
400 err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist, 413 err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist,
401 process_synthesized_event); 414 process_synthesized_event);
402 if (err <= 0) { 415 if (err <= 0) {
403 pr_err("Couldn't record tracing data.\n"); 416 pr_err("Couldn't record tracing data.\n");
@@ -504,19 +517,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
504 goto out_child; 517 goto out_child;
505 } 518 }
506 519
507 if (!quiet) { 520 if (!quiet)
508 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 521 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
509 522
510 /*
511 * Approximate RIP event size: 24 bytes.
512 */
513 fprintf(stderr,
514 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
515 (double)rec->bytes_written / 1024.0 / 1024.0,
516 file->path,
517 rec->bytes_written / 24);
518 }
519
520out_child: 523out_child:
521 if (forks) { 524 if (forks) {
522 int exit_status; 525 int exit_status;
@@ -535,13 +538,29 @@ out_child:
535 } else 538 } else
536 status = err; 539 status = err;
537 540
541 /* this will be recalculated during process_buildids() */
542 rec->samples = 0;
543
538 if (!err && !file->is_pipe) { 544 if (!err && !file->is_pipe) {
539 rec->session->header.data_size += rec->bytes_written; 545 rec->session->header.data_size += rec->bytes_written;
540 546
541 if (!rec->no_buildid) 547 if (!rec->no_buildid)
542 process_buildids(rec); 548 process_buildids(rec);
543 perf_session__write_header(rec->session, rec->evlist, 549 perf_session__write_header(rec->session, rec->evlist, fd, true);
544 file->fd, true); 550 }
551
552 if (!err && !quiet) {
553 char samples[128];
554
555 if (rec->samples)
556 scnprintf(samples, sizeof(samples),
557 " (%" PRIu64 " samples)", rec->samples);
558 else
559 samples[0] = '\0';
560
561 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n",
562 perf_data_file__size(file) / 1024.0 / 1024.0,
563 file->path, samples);
545 } 564 }
546 565
547out_delete_session: 566out_delete_session:
@@ -720,6 +739,13 @@ static struct record record = {
720 .default_per_cpu = true, 739 .default_per_cpu = true,
721 }, 740 },
722 }, 741 },
742 .tool = {
743 .sample = process_sample_event,
744 .fork = perf_event__process_fork,
745 .comm = perf_event__process_comm,
746 .mmap = perf_event__process_mmap,
747 .mmap2 = perf_event__process_mmap2,
748 },
723}; 749};
724 750
725#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 751#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 072ae8ad67fc..2f91094e228b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -86,17 +86,6 @@ static int report__config(const char *var, const char *value, void *cb)
86 return perf_default_config(var, value, cb); 86 return perf_default_config(var, value, cb);
87} 87}
88 88
89static void report__inc_stats(struct report *rep, struct hist_entry *he)
90{
91 /*
92 * The @he is either of a newly created one or an existing one
93 * merging current sample. We only want to count a new one so
94 * checking ->nr_events being 1.
95 */
96 if (he->stat.nr_events == 1)
97 rep->nr_entries++;
98}
99
100static int hist_iter__report_callback(struct hist_entry_iter *iter, 89static int hist_iter__report_callback(struct hist_entry_iter *iter,
101 struct addr_location *al, bool single, 90 struct addr_location *al, bool single,
102 void *arg) 91 void *arg)
@@ -108,8 +97,6 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
108 struct mem_info *mi; 97 struct mem_info *mi;
109 struct branch_info *bi; 98 struct branch_info *bi;
110 99
111 report__inc_stats(rep, he);
112
113 if (!ui__has_annotation()) 100 if (!ui__has_annotation())
114 return 0; 101 return 0;
115 102
@@ -499,6 +486,9 @@ static int __cmd_report(struct report *rep)
499 486
500 report__warn_kptr_restrict(rep); 487 report__warn_kptr_restrict(rep);
501 488
489 evlist__for_each(session->evlist, pos)
490 rep->nr_entries += evsel__hists(pos)->nr_entries;
491
502 if (use_browser == 0) { 492 if (use_browser == 0) {
503 if (verbose > 3) 493 if (verbose > 3)
504 perf_session__fprintf(session, stdout); 494 perf_session__fprintf(session, stdout);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 891086376381..e598e4e98170 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1730,7 +1730,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1730 "detailed run - start a lot of events"), 1730 "detailed run - start a lot of events"),
1731 OPT_BOOLEAN('S', "sync", &sync_run, 1731 OPT_BOOLEAN('S', "sync", &sync_run,
1732 "call sync() before starting a run"), 1732 "call sync() before starting a run"),
1733 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1733 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1734 "print large numbers with thousands\' separators", 1734 "print large numbers with thousands\' separators",
1735 stat__set_big_num), 1735 stat__set_big_num),
1736 OPT_STRING('C', "cpu", &target.cpu_list, "cpu", 1736 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 616f0fcb4701..c4c7eac69de4 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -165,7 +165,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
165 err ? "[unknown]" : uts.release, perf_version_string); 165 err ? "[unknown]" : uts.release, perf_version_string);
166 if (use_browser <= 0) 166 if (use_browser <= 0)
167 sleep(5); 167 sleep(5);
168 168
169 map->erange_warned = true; 169 map->erange_warned = true;
170} 170}
171 171
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index badfabc6a01f..7e935f1083ec 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -929,66 +929,66 @@ static struct syscall_fmt {
929 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 929 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
930 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, 930 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
931 { .name = "close", .errmsg = true, 931 { .name = "close", .errmsg = true,
932 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 932 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
933 { .name = "connect", .errmsg = true, }, 933 { .name = "connect", .errmsg = true, },
934 { .name = "dup", .errmsg = true, 934 { .name = "dup", .errmsg = true,
935 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 935 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
936 { .name = "dup2", .errmsg = true, 936 { .name = "dup2", .errmsg = true,
937 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 937 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
938 { .name = "dup3", .errmsg = true, 938 { .name = "dup3", .errmsg = true,
939 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 939 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
940 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, 940 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
941 { .name = "eventfd2", .errmsg = true, 941 { .name = "eventfd2", .errmsg = true,
942 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, 942 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
943 { .name = "faccessat", .errmsg = true, 943 { .name = "faccessat", .errmsg = true,
944 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 944 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
945 { .name = "fadvise64", .errmsg = true, 945 { .name = "fadvise64", .errmsg = true,
946 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 946 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
947 { .name = "fallocate", .errmsg = true, 947 { .name = "fallocate", .errmsg = true,
948 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 948 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
949 { .name = "fchdir", .errmsg = true, 949 { .name = "fchdir", .errmsg = true,
950 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 950 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
951 { .name = "fchmod", .errmsg = true, 951 { .name = "fchmod", .errmsg = true,
952 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 952 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
953 { .name = "fchmodat", .errmsg = true, 953 { .name = "fchmodat", .errmsg = true,
954 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 954 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
955 { .name = "fchown", .errmsg = true, 955 { .name = "fchown", .errmsg = true,
956 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 956 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
957 { .name = "fchownat", .errmsg = true, 957 { .name = "fchownat", .errmsg = true,
958 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 958 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
959 { .name = "fcntl", .errmsg = true, 959 { .name = "fcntl", .errmsg = true,
960 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 960 .arg_scnprintf = { [0] = SCA_FD, /* fd */
961 [1] = SCA_STRARRAY, /* cmd */ }, 961 [1] = SCA_STRARRAY, /* cmd */ },
962 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, 962 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
963 { .name = "fdatasync", .errmsg = true, 963 { .name = "fdatasync", .errmsg = true,
964 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 964 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
965 { .name = "flock", .errmsg = true, 965 { .name = "flock", .errmsg = true,
966 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 966 .arg_scnprintf = { [0] = SCA_FD, /* fd */
967 [1] = SCA_FLOCK, /* cmd */ }, }, 967 [1] = SCA_FLOCK, /* cmd */ }, },
968 { .name = "fsetxattr", .errmsg = true, 968 { .name = "fsetxattr", .errmsg = true,
969 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 969 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
970 { .name = "fstat", .errmsg = true, .alias = "newfstat", 970 { .name = "fstat", .errmsg = true, .alias = "newfstat",
971 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 971 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
972 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", 972 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
973 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 973 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
974 { .name = "fstatfs", .errmsg = true, 974 { .name = "fstatfs", .errmsg = true,
975 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 975 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
976 { .name = "fsync", .errmsg = true, 976 { .name = "fsync", .errmsg = true,
977 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 977 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
978 { .name = "ftruncate", .errmsg = true, 978 { .name = "ftruncate", .errmsg = true,
979 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 979 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
980 { .name = "futex", .errmsg = true, 980 { .name = "futex", .errmsg = true,
981 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 981 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
982 { .name = "futimesat", .errmsg = true, 982 { .name = "futimesat", .errmsg = true,
983 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 983 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
984 { .name = "getdents", .errmsg = true, 984 { .name = "getdents", .errmsg = true,
985 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 985 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
986 { .name = "getdents64", .errmsg = true, 986 { .name = "getdents64", .errmsg = true,
987 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 987 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
988 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 988 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
989 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 989 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
990 { .name = "ioctl", .errmsg = true, 990 { .name = "ioctl", .errmsg = true,
991 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 991 .arg_scnprintf = { [0] = SCA_FD, /* fd */
992#if defined(__i386__) || defined(__x86_64__) 992#if defined(__i386__) || defined(__x86_64__)
993/* 993/*
994 * FIXME: Make this available to all arches. 994 * FIXME: Make this available to all arches.
@@ -1002,7 +1002,7 @@ static struct syscall_fmt {
1002 { .name = "kill", .errmsg = true, 1002 { .name = "kill", .errmsg = true,
1003 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 1003 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1004 { .name = "linkat", .errmsg = true, 1004 { .name = "linkat", .errmsg = true,
1005 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1005 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1006 { .name = "lseek", .errmsg = true, 1006 { .name = "lseek", .errmsg = true,
1007 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 1007 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1008 [2] = SCA_STRARRAY, /* whence */ }, 1008 [2] = SCA_STRARRAY, /* whence */ },
@@ -1012,9 +1012,9 @@ static struct syscall_fmt {
1012 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 1012 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1013 [2] = SCA_MADV_BHV, /* behavior */ }, }, 1013 [2] = SCA_MADV_BHV, /* behavior */ }, },
1014 { .name = "mkdirat", .errmsg = true, 1014 { .name = "mkdirat", .errmsg = true,
1015 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1015 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1016 { .name = "mknodat", .errmsg = true, 1016 { .name = "mknodat", .errmsg = true,
1017 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 1017 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1018 { .name = "mlock", .errmsg = true, 1018 { .name = "mlock", .errmsg = true,
1019 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1019 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1020 { .name = "mlockall", .errmsg = true, 1020 { .name = "mlockall", .errmsg = true,
@@ -1036,9 +1036,9 @@ static struct syscall_fmt {
1036 { .name = "munmap", .errmsg = true, 1036 { .name = "munmap", .errmsg = true,
1037 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1037 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1038 { .name = "name_to_handle_at", .errmsg = true, 1038 { .name = "name_to_handle_at", .errmsg = true,
1039 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1039 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1040 { .name = "newfstatat", .errmsg = true, 1040 { .name = "newfstatat", .errmsg = true,
1041 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1041 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1042 { .name = "open", .errmsg = true, 1042 { .name = "open", .errmsg = true,
1043 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, 1043 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
1044 { .name = "open_by_handle_at", .errmsg = true, 1044 { .name = "open_by_handle_at", .errmsg = true,
@@ -1052,20 +1052,20 @@ static struct syscall_fmt {
1052 { .name = "poll", .errmsg = true, .timeout = true, }, 1052 { .name = "poll", .errmsg = true, .timeout = true, },
1053 { .name = "ppoll", .errmsg = true, .timeout = true, }, 1053 { .name = "ppoll", .errmsg = true, .timeout = true, },
1054 { .name = "pread", .errmsg = true, .alias = "pread64", 1054 { .name = "pread", .errmsg = true, .alias = "pread64",
1055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1056 { .name = "preadv", .errmsg = true, .alias = "pread", 1056 { .name = "preadv", .errmsg = true, .alias = "pread",
1057 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1057 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1058 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, 1058 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
1059 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", 1059 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
1060 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1060 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1061 { .name = "pwritev", .errmsg = true, 1061 { .name = "pwritev", .errmsg = true,
1062 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1062 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1063 { .name = "read", .errmsg = true, 1063 { .name = "read", .errmsg = true,
1064 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1064 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1065 { .name = "readlinkat", .errmsg = true, 1065 { .name = "readlinkat", .errmsg = true,
1066 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1066 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1067 { .name = "readv", .errmsg = true, 1067 { .name = "readv", .errmsg = true,
1068 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1068 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1069 { .name = "recvfrom", .errmsg = true, 1069 { .name = "recvfrom", .errmsg = true,
1070 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, }, 1070 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1071 { .name = "recvmmsg", .errmsg = true, 1071 { .name = "recvmmsg", .errmsg = true,
@@ -1073,7 +1073,7 @@ static struct syscall_fmt {
1073 { .name = "recvmsg", .errmsg = true, 1073 { .name = "recvmsg", .errmsg = true,
1074 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, }, 1074 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1075 { .name = "renameat", .errmsg = true, 1075 { .name = "renameat", .errmsg = true,
1076 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1076 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1077 { .name = "rt_sigaction", .errmsg = true, 1077 { .name = "rt_sigaction", .errmsg = true,
1078 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, 1078 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
1079 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, 1079 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
@@ -1091,7 +1091,7 @@ static struct syscall_fmt {
1091 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 1091 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1092 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 1092 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1093 { .name = "shutdown", .errmsg = true, 1093 { .name = "shutdown", .errmsg = true,
1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1095 { .name = "socket", .errmsg = true, 1095 { .name = "socket", .errmsg = true,
1096 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 1096 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1097 [1] = SCA_SK_TYPE, /* type */ }, 1097 [1] = SCA_SK_TYPE, /* type */ },
@@ -1102,7 +1102,7 @@ static struct syscall_fmt {
1102 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 1102 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1103 { .name = "stat", .errmsg = true, .alias = "newstat", }, 1103 { .name = "stat", .errmsg = true, .alias = "newstat", },
1104 { .name = "symlinkat", .errmsg = true, 1104 { .name = "symlinkat", .errmsg = true,
1105 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 1105 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1106 { .name = "tgkill", .errmsg = true, 1106 { .name = "tgkill", .errmsg = true,
1107 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 1107 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1108 { .name = "tkill", .errmsg = true, 1108 { .name = "tkill", .errmsg = true,
@@ -1113,9 +1113,9 @@ static struct syscall_fmt {
1113 { .name = "utimensat", .errmsg = true, 1113 { .name = "utimensat", .errmsg = true,
1114 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, }, 1114 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1115 { .name = "write", .errmsg = true, 1115 { .name = "write", .errmsg = true,
1116 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1116 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1117 { .name = "writev", .errmsg = true, 1117 { .name = "writev", .errmsg = true,
1118 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 1118 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1119}; 1119};
1120 1120
1121static int syscall_fmt__cmp(const void *name, const void *fmtp) 1121static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -1191,7 +1191,7 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
1191 1191
1192 if (thread__priv(thread) == NULL) 1192 if (thread__priv(thread) == NULL)
1193 thread__set_priv(thread, thread_trace__new()); 1193 thread__set_priv(thread, thread_trace__new());
1194 1194
1195 if (thread__priv(thread) == NULL) 1195 if (thread__priv(thread) == NULL)
1196 goto fail; 1196 goto fail;
1197 1197
@@ -2056,23 +2056,24 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2056 if (trace->trace_syscalls && 2056 if (trace->trace_syscalls &&
2057 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, 2057 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
2058 trace__sys_exit)) 2058 trace__sys_exit))
2059 goto out_error_tp; 2059 goto out_error_raw_syscalls;
2060 2060
2061 if (trace->trace_syscalls) 2061 if (trace->trace_syscalls)
2062 perf_evlist__add_vfs_getname(evlist); 2062 perf_evlist__add_vfs_getname(evlist);
2063 2063
2064 if ((trace->trace_pgfaults & TRACE_PFMAJ) && 2064 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&
2065 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) 2065 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {
2066 goto out_error_tp; 2066 goto out_error_mem;
2067 }
2067 2068
2068 if ((trace->trace_pgfaults & TRACE_PFMIN) && 2069 if ((trace->trace_pgfaults & TRACE_PFMIN) &&
2069 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN)) 2070 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))
2070 goto out_error_tp; 2071 goto out_error_mem;
2071 2072
2072 if (trace->sched && 2073 if (trace->sched &&
2073 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 2074 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
2074 trace__sched_stat_runtime)) 2075 trace__sched_stat_runtime))
2075 goto out_error_tp; 2076 goto out_error_sched_stat_runtime;
2076 2077
2077 err = perf_evlist__create_maps(evlist, &trace->opts.target); 2078 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2078 if (err < 0) { 2079 if (err < 0) {
@@ -2202,8 +2203,12 @@ out:
2202{ 2203{
2203 char errbuf[BUFSIZ]; 2204 char errbuf[BUFSIZ];
2204 2205
2205out_error_tp: 2206out_error_sched_stat_runtime:
2206 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf)); 2207 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime");
2208 goto out_error;
2209
2210out_error_raw_syscalls:
2211 debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)");
2207 goto out_error; 2212 goto out_error;
2208 2213
2209out_error_mmap: 2214out_error_mmap:
@@ -2217,6 +2222,9 @@ out_error:
2217 fprintf(trace->output, "%s\n", errbuf); 2222 fprintf(trace->output, "%s\n", errbuf);
2218 goto out_delete_evlist; 2223 goto out_delete_evlist;
2219} 2224}
2225out_error_mem:
2226 fprintf(trace->output, "Not enough memory to run!\n");
2227 goto out_delete_evlist;
2220} 2228}
2221 2229
2222static int trace__replay(struct trace *trace) 2230static int trace__replay(struct trace *trace)
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 648e31ff4021..cc224080b525 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -198,6 +198,7 @@ CORE_FEATURE_TESTS = \
198 libpython-version \ 198 libpython-version \
199 libslang \ 199 libslang \
200 libunwind \ 200 libunwind \
201 pthread-attr-setaffinity-np \
201 stackprotector-all \ 202 stackprotector-all \
202 timerfd \ 203 timerfd \
203 libdw-dwarf-unwind \ 204 libdw-dwarf-unwind \
@@ -226,6 +227,7 @@ VF_FEATURE_TESTS = \
226 libelf-getphdrnum \ 227 libelf-getphdrnum \
227 libelf-mmap \ 228 libelf-mmap \
228 libpython-version \ 229 libpython-version \
230 pthread-attr-setaffinity-np \
229 stackprotector-all \ 231 stackprotector-all \
230 timerfd \ 232 timerfd \
231 libunwind-debug-frame \ 233 libunwind-debug-frame \
@@ -301,6 +303,10 @@ ifeq ($(feature-sync-compare-and-swap), 1)
301 CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT 303 CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT
302endif 304endif
303 305
306ifeq ($(feature-pthread-attr-setaffinity-np), 1)
307 CFLAGS += -DHAVE_PTHREAD_ATTR_SETAFFINITY_NP
308endif
309
304ifndef NO_BIONIC 310ifndef NO_BIONIC
305 $(call feature_check,bionic) 311 $(call feature_check,bionic)
306 ifeq ($(feature-bionic), 1) 312 ifeq ($(feature-bionic), 1)
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 53f19b5dbc37..42ac05aaf8ac 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -25,6 +25,7 @@ FILES= \
25 test-libslang.bin \ 25 test-libslang.bin \
26 test-libunwind.bin \ 26 test-libunwind.bin \
27 test-libunwind-debug-frame.bin \ 27 test-libunwind-debug-frame.bin \
28 test-pthread-attr-setaffinity-np.bin \
28 test-stackprotector-all.bin \ 29 test-stackprotector-all.bin \
29 test-timerfd.bin \ 30 test-timerfd.bin \
30 test-libdw-dwarf-unwind.bin \ 31 test-libdw-dwarf-unwind.bin \
@@ -47,6 +48,9 @@ test-all.bin:
47test-hello.bin: 48test-hello.bin:
48 $(BUILD) 49 $(BUILD)
49 50
51test-pthread-attr-setaffinity-np.bin:
52 $(BUILD) -Werror -lpthread
53
50test-stackprotector-all.bin: 54test-stackprotector-all.bin:
51 $(BUILD) -Werror -fstack-protector-all 55 $(BUILD) -Werror -fstack-protector-all
52 56
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index 652e0098eba6..6d4d09323922 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -97,6 +97,10 @@
97# include "test-zlib.c" 97# include "test-zlib.c"
98#undef main 98#undef main
99 99
100#define main main_test_pthread_attr_setaffinity_np
101# include "test-pthread_attr_setaffinity_np.c"
102#undef main
103
100int main(int argc, char *argv[]) 104int main(int argc, char *argv[])
101{ 105{
102 main_test_libpython(); 106 main_test_libpython();
@@ -121,6 +125,7 @@ int main(int argc, char *argv[])
121 main_test_libdw_dwarf_unwind(); 125 main_test_libdw_dwarf_unwind();
122 main_test_sync_compare_and_swap(argc, argv); 126 main_test_sync_compare_and_swap(argc, argv);
123 main_test_zlib(); 127 main_test_zlib();
128 main_test_pthread_attr_setaffinity_np();
124 129
125 return 0; 130 return 0;
126} 131}
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
new file mode 100644
index 000000000000..0a0d3ecb4e8a
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
@@ -0,0 +1,14 @@
1#include <stdint.h>
2#include <pthread.h>
3
4int main(void)
5{
6 int ret = 0;
7 pthread_attr_t thread_attr;
8
9 pthread_attr_init(&thread_attr);
10 /* don't care abt exact args, just the API itself in libpthread */
11 ret = pthread_attr_setaffinity_np(&thread_attr, 0, NULL);
12
13 return ret;
14}
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
index c9b4b6269b51..1091bd47adfd 100644
--- a/tools/perf/tests/attr.py
+++ b/tools/perf/tests/attr.py
@@ -104,7 +104,6 @@ class Event(dict):
104 continue 104 continue
105 if not self.compare_data(self[t], other[t]): 105 if not self.compare_data(self[t], other[t]):
106 log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) 106 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
107
108 107
109# Test file description needs to have following sections: 108# Test file description needs to have following sections:
110# [config] 109# [config]
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 8d110dec393e..18619966454c 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -140,7 +140,7 @@ static void del_hist_entries(struct hists *hists)
140 he = rb_entry(node, struct hist_entry, rb_node); 140 he = rb_entry(node, struct hist_entry, rb_node);
141 rb_erase(node, root_out); 141 rb_erase(node, root_out);
142 rb_erase(&he->rb_node_in, root_in); 142 rb_erase(&he->rb_node_in, root_in);
143 hist_entry__free(he); 143 hist_entry__delete(he);
144 } 144 }
145} 145}
146 146
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index f5547610da02..b52c9faea224 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -106,7 +106,7 @@ static void del_hist_entries(struct hists *hists)
106 he = rb_entry(node, struct hist_entry, rb_node); 106 he = rb_entry(node, struct hist_entry, rb_node);
107 rb_erase(node, root_out); 107 rb_erase(node, root_out);
108 rb_erase(&he->rb_node_in, root_in); 108 rb_erase(&he->rb_node_in, root_in);
109 hist_entry__free(he); 109 hist_entry__delete(he);
110 } 110 }
111} 111}
112 112
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 69a71ff84e01..75709d2b17b4 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -222,7 +222,6 @@ tarpkg:
222 @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \ 222 @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \
223 echo "- $@: $$cmd" && echo $$cmd > $@ && \ 223 echo "- $@: $$cmd" && echo $$cmd > $@ && \
224 ( eval $$cmd ) >> $@ 2>&1 224 ( eval $$cmd ) >> $@ 2>&1
225
226 225
227all: $(run) $(run_O) tarpkg 226all: $(run) $(run_O) tarpkg
228 @echo OK 227 @echo OK
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 7f2f51f93619..1cdab0ce00e2 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1145,6 +1145,49 @@ static int test__pinned_group(struct perf_evlist *evlist)
1145 return 0; 1145 return 0;
1146} 1146}
1147 1147
1148static int test__checkevent_breakpoint_len(struct perf_evlist *evlist)
1149{
1150 struct perf_evsel *evsel = perf_evlist__first(evlist);
1151
1152 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
1153 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
1154 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
1155 TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
1156 evsel->attr.bp_type);
1157 TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_1 ==
1158 evsel->attr.bp_len);
1159
1160 return 0;
1161}
1162
1163static int test__checkevent_breakpoint_len_w(struct perf_evlist *evlist)
1164{
1165 struct perf_evsel *evsel = perf_evlist__first(evlist);
1166
1167 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
1168 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
1169 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
1170 TEST_ASSERT_VAL("wrong bp_type", HW_BREAKPOINT_W ==
1171 evsel->attr.bp_type);
1172 TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_2 ==
1173 evsel->attr.bp_len);
1174
1175 return 0;
1176}
1177
1178static int
1179test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist)
1180{
1181 struct perf_evsel *evsel = perf_evlist__first(evlist);
1182
1183 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
1184 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
1185 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
1186 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
1187
1188 return test__checkevent_breakpoint_rw(evlist);
1189}
1190
1148static int count_tracepoints(void) 1191static int count_tracepoints(void)
1149{ 1192{
1150 char events_path[PATH_MAX]; 1193 char events_path[PATH_MAX];
@@ -1420,6 +1463,21 @@ static struct evlist_test test__events[] = {
1420 .check = test__pinned_group, 1463 .check = test__pinned_group,
1421 .id = 41, 1464 .id = 41,
1422 }, 1465 },
1466 {
1467 .name = "mem:0/1",
1468 .check = test__checkevent_breakpoint_len,
1469 .id = 42,
1470 },
1471 {
1472 .name = "mem:0/2:w",
1473 .check = test__checkevent_breakpoint_len_w,
1474 .id = 43,
1475 },
1476 {
1477 .name = "mem:0/4:rw:u",
1478 .check = test__checkevent_breakpoint_len_rw_modifier,
1479 .id = 44
1480 },
1423#if defined(__s390x__) 1481#if defined(__s390x__)
1424 { 1482 {
1425 .name = "kvm-s390:kvm_s390_create_vm", 1483 .name = "kvm-s390:kvm_s390_create_vm",
@@ -1471,7 +1529,7 @@ static int test_event(struct evlist_test *e)
1471 } else { 1529 } else {
1472 ret = e->check(evlist); 1530 ret = e->check(evlist);
1473 } 1531 }
1474 1532
1475 perf_evlist__delete(evlist); 1533 perf_evlist__delete(evlist);
1476 1534
1477 return ret; 1535 return ret;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 4908c648a597..30c02181e78b 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -110,7 +110,7 @@ static bool samples_same(const struct perf_sample *s1,
110 110
111 if (type & PERF_SAMPLE_STACK_USER) { 111 if (type & PERF_SAMPLE_STACK_USER) {
112 COMP(user_stack.size); 112 COMP(user_stack.size);
113 if (memcmp(s1->user_stack.data, s1->user_stack.data, 113 if (memcmp(s1->user_stack.data, s2->user_stack.data,
114 s1->user_stack.size)) { 114 s1->user_stack.size)) {
115 pr_debug("Samples differ at 'user_stack'\n"); 115 pr_debug("Samples differ at 'user_stack'\n");
116 return false; 116 return false;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 1e0a2fd80115..9d32e3c0cfee 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -517,7 +517,7 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
517 } 517 }
518 518
519 annotate_browser__set_top(browser, dl, idx); 519 annotate_browser__set_top(browser, dl, idx);
520 520
521 return true; 521 return true;
522} 522}
523 523
@@ -867,7 +867,6 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser
867 867
868 ++browser->nr_jumps; 868 ++browser->nr_jumps;
869 } 869 }
870
871} 870}
872 871
873static inline int width_jumps(int n) 872static inline int width_jumps(int n)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 482adae3cc44..25d608394d74 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -285,7 +285,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
285} 285}
286 286
287#define __HPP_SORT_FN(_type, _field) \ 287#define __HPP_SORT_FN(_type, _field) \
288static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ 288static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
289 struct hist_entry *a, struct hist_entry *b) \
289{ \ 290{ \
290 return __hpp__sort(a, b, he_get_##_field); \ 291 return __hpp__sort(a, b, he_get_##_field); \
291} 292}
@@ -312,7 +313,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
312} 313}
313 314
314#define __HPP_SORT_ACC_FN(_type, _field) \ 315#define __HPP_SORT_ACC_FN(_type, _field) \
315static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ 316static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
317 struct hist_entry *a, struct hist_entry *b) \
316{ \ 318{ \
317 return __hpp__sort_acc(a, b, he_get_acc_##_field); \ 319 return __hpp__sort_acc(a, b, he_get_acc_##_field); \
318} 320}
@@ -331,7 +333,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
331} 333}
332 334
333#define __HPP_SORT_RAW_FN(_type, _field) \ 335#define __HPP_SORT_RAW_FN(_type, _field) \
334static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ 336static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
337 struct hist_entry *a, struct hist_entry *b) \
335{ \ 338{ \
336 return __hpp__sort(a, b, he_get_raw_##_field); \ 339 return __hpp__sort(a, b, he_get_raw_##_field); \
337} 340}
@@ -361,7 +364,8 @@ HPP_PERCENT_ACC_FNS(overhead_acc, period)
361HPP_RAW_FNS(samples, nr_events) 364HPP_RAW_FNS(samples, nr_events)
362HPP_RAW_FNS(period, period) 365HPP_RAW_FNS(period, period)
363 366
364static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused, 367static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
368 struct hist_entry *a __maybe_unused,
365 struct hist_entry *b __maybe_unused) 369 struct hist_entry *b __maybe_unused)
366{ 370{
367 return 0; 371 return 0;
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index f34f89eb607c..717d39d3052b 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -4,12 +4,12 @@
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6void ui_progress__finish(void); 6void ui_progress__finish(void);
7 7
8struct ui_progress { 8struct ui_progress {
9 const char *title; 9 const char *title;
10 u64 curr, next, step, total; 10 u64 curr, next, step, total;
11}; 11};
12 12
13void ui_progress__init(struct ui_progress *p, u64 total, const char *title); 13void ui_progress__init(struct ui_progress *p, u64 total, const char *title);
14void ui_progress__update(struct ui_progress *p, u64 adv); 14void ui_progress__update(struct ui_progress *p, u64 adv);
15 15
diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c
index 1c8b9afd5d6e..88f5143a5981 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -9,6 +9,7 @@
9#include "../libslang.h" 9#include "../libslang.h"
10 10
11char ui_helpline__last_msg[1024]; 11char ui_helpline__last_msg[1024];
12bool tui_helpline__set;
12 13
13static void tui_helpline__pop(void) 14static void tui_helpline__pop(void)
14{ 15{
@@ -35,6 +36,8 @@ static int tui_helpline__show(const char *format, va_list ap)
35 sizeof(ui_helpline__last_msg) - backlog, format, ap); 36 sizeof(ui_helpline__last_msg) - backlog, format, ap);
36 backlog += ret; 37 backlog += ret;
37 38
39 tui_helpline__set = true;
40
38 if (ui_helpline__last_msg[backlog - 1] == '\n') { 41 if (ui_helpline__last_msg[backlog - 1] == '\n') {
39 ui_helpline__puts(ui_helpline__last_msg); 42 ui_helpline__puts(ui_helpline__last_msg);
40 SLsmg_refresh(); 43 SLsmg_refresh();
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 3c38f25b1695..b77e1d771363 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -17,6 +17,7 @@
17static volatile int ui__need_resize; 17static volatile int ui__need_resize;
18 18
19extern struct perf_error_ops perf_tui_eops; 19extern struct perf_error_ops perf_tui_eops;
20extern bool tui_helpline__set;
20 21
21extern void hist_browser__init_hpp(void); 22extern void hist_browser__init_hpp(void);
22 23
@@ -159,7 +160,7 @@ out:
159 160
160void ui__exit(bool wait_for_ok) 161void ui__exit(bool wait_for_ok)
161{ 162{
162 if (wait_for_ok) 163 if (wait_for_ok && tui_helpline__set)
163 ui__question_window("Fatal Error", 164 ui__question_window("Fatal Error",
164 ui_helpline__last_msg, 165 ui_helpline__last_msg,
165 "Press any key...", 0); 166 "Press any key...", 0);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 01bc4e23a2cf..61bf9128e1f2 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -239,7 +239,7 @@ static int mov__parse(struct ins_operands *ops)
239 *s = '\0'; 239 *s = '\0';
240 ops->source.raw = strdup(ops->raw); 240 ops->source.raw = strdup(ops->raw);
241 *s = ','; 241 *s = ',';
242 242
243 if (ops->source.raw == NULL) 243 if (ops->source.raw == NULL)
244 return -1; 244 return -1;
245 245
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index f4654183d391..55355b3d4f85 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -5,132 +5,6 @@
5 5
6int perf_use_color_default = -1; 6int perf_use_color_default = -1;
7 7
8static int parse_color(const char *name, int len)
9{
10 static const char * const color_names[] = {
11 "normal", "black", "red", "green", "yellow",
12 "blue", "magenta", "cyan", "white"
13 };
14 char *end;
15 int i;
16
17 for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) {
18 const char *str = color_names[i];
19 if (!strncasecmp(name, str, len) && !str[len])
20 return i - 1;
21 }
22 i = strtol(name, &end, 10);
23 if (end - name == len && i >= -1 && i <= 255)
24 return i;
25 return -2;
26}
27
28static int parse_attr(const char *name, int len)
29{
30 static const int attr_values[] = { 1, 2, 4, 5, 7 };
31 static const char * const attr_names[] = {
32 "bold", "dim", "ul", "blink", "reverse"
33 };
34 unsigned int i;
35
36 for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
37 const char *str = attr_names[i];
38 if (!strncasecmp(name, str, len) && !str[len])
39 return attr_values[i];
40 }
41 return -1;
42}
43
44void color_parse(const char *value, const char *var, char *dst)
45{
46 color_parse_mem(value, strlen(value), var, dst);
47}
48
49void color_parse_mem(const char *value, int value_len, const char *var,
50 char *dst)
51{
52 const char *ptr = value;
53 int len = value_len;
54 int attr = -1;
55 int fg = -2;
56 int bg = -2;
57
58 if (!strncasecmp(value, "reset", len)) {
59 strcpy(dst, PERF_COLOR_RESET);
60 return;
61 }
62
63 /* [fg [bg]] [attr] */
64 while (len > 0) {
65 const char *word = ptr;
66 int val, wordlen = 0;
67
68 while (len > 0 && !isspace(word[wordlen])) {
69 wordlen++;
70 len--;
71 }
72
73 ptr = word + wordlen;
74 while (len > 0 && isspace(*ptr)) {
75 ptr++;
76 len--;
77 }
78
79 val = parse_color(word, wordlen);
80 if (val >= -1) {
81 if (fg == -2) {
82 fg = val;
83 continue;
84 }
85 if (bg == -2) {
86 bg = val;
87 continue;
88 }
89 goto bad;
90 }
91 val = parse_attr(word, wordlen);
92 if (val < 0 || attr != -1)
93 goto bad;
94 attr = val;
95 }
96
97 if (attr >= 0 || fg >= 0 || bg >= 0) {
98 int sep = 0;
99
100 *dst++ = '\033';
101 *dst++ = '[';
102 if (attr >= 0) {
103 *dst++ = '0' + attr;
104 sep++;
105 }
106 if (fg >= 0) {
107 if (sep++)
108 *dst++ = ';';
109 if (fg < 8) {
110 *dst++ = '3';
111 *dst++ = '0' + fg;
112 } else {
113 dst += sprintf(dst, "38;5;%d", fg);
114 }
115 }
116 if (bg >= 0) {
117 if (sep++)
118 *dst++ = ';';
119 if (bg < 8) {
120 *dst++ = '4';
121 *dst++ = '0' + bg;
122 } else {
123 dst += sprintf(dst, "48;5;%d", bg);
124 }
125 }
126 *dst++ = 'm';
127 }
128 *dst = 0;
129 return;
130bad:
131 die("bad color value '%.*s' for variable '%s'", value_len, value, var);
132}
133
134int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty) 8int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
135{ 9{
136 if (value) { 10 if (value) {
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 0a594b8a0c26..38146f922c54 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -30,8 +30,6 @@ extern int perf_use_color_default;
30int perf_color_default_config(const char *var, const char *value, void *cb); 30int perf_color_default_config(const char *var, const char *value, void *cb);
31 31
32int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty); 32int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty);
33void color_parse(const char *value, const char *var, char *dst);
34void color_parse_mem(const char *value, int len, const char *var, char *dst);
35int color_vsnprintf(char *bf, size_t size, const char *color, 33int color_vsnprintf(char *bf, size_t size, const char *color,
36 const char *fmt, va_list args); 34 const char *fmt, va_list args);
37int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); 35int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args);
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 45be944d450a..c2f7d3b90966 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -532,12 +532,8 @@ dso_cache__read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
532 break; 532 break;
533 533
534 cache_offset = offset & DSO__DATA_CACHE_MASK; 534 cache_offset = offset & DSO__DATA_CACHE_MASK;
535 ret = -EINVAL;
536 535
537 if (-1 == lseek(dso->data.fd, cache_offset, SEEK_SET)) 536 ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, cache_offset);
538 break;
539
540 ret = read(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE);
541 if (ret <= 0) 537 if (ret <= 0)
542 break; 538 break;
543 539
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 3782c82c6e44..ced92841ff97 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -139,6 +139,7 @@ struct dso {
139 u32 status_seen; 139 u32 status_seen;
140 size_t file_size; 140 size_t file_size;
141 struct list_head open_entry; 141 struct list_head open_entry;
142 u64 frame_offset;
142 } data; 143 } data;
143 144
144 union { /* Tool specific area */ 145 union { /* Tool specific area */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 2e507b5025a3..28b8ce86bf12 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1436,33 +1436,6 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1436 return printed + fprintf(fp, "\n"); 1436 return printed + fprintf(fp, "\n");
1437} 1437}
1438 1438
1439int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused,
1440 int err, char *buf, size_t size)
1441{
1442 char sbuf[128];
1443
1444 switch (err) {
1445 case ENOENT:
1446 scnprintf(buf, size, "%s",
1447 "Error:\tUnable to find debugfs\n"
1448 "Hint:\tWas your kernel compiled with debugfs support?\n"
1449 "Hint:\tIs the debugfs filesystem mounted?\n"
1450 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
1451 break;
1452 case EACCES:
1453 scnprintf(buf, size,
1454 "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
1455 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
1456 debugfs_mountpoint, debugfs_mountpoint);
1457 break;
1458 default:
1459 scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
1460 break;
1461 }
1462
1463 return 0;
1464}
1465
1466int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused, 1439int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1467 int err, char *buf, size_t size) 1440 int err, char *buf, size_t size)
1468{ 1441{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 0ba93f67ab94..c94a9e03ecf1 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -183,7 +183,6 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
183 183
184size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); 184size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
185 185
186int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
187int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 186int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
188int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); 187int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
189 188
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1e90c8557ede..ea51a90e20a0 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -709,6 +709,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
709 if (opts->sample_weight) 709 if (opts->sample_weight)
710 perf_evsel__set_sample_bit(evsel, WEIGHT); 710 perf_evsel__set_sample_bit(evsel, WEIGHT);
711 711
712 attr->task = track;
712 attr->mmap = track; 713 attr->mmap = track;
713 attr->mmap2 = track && !perf_missing_features.mmap2; 714 attr->mmap2 = track && !perf_missing_features.mmap2;
714 attr->comm = track; 715 attr->comm = track;
@@ -797,6 +798,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
797 798
798int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 799int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
799{ 800{
801 if (ncpus == 0 || nthreads == 0)
802 return 0;
803
800 if (evsel->system_wide) 804 if (evsel->system_wide)
801 nthreads = 1; 805 nthreads = 1;
802 806
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index b20e40c74468..1f407f7352a7 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2237,6 +2237,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2237 * - unique number to identify actual perf.data files 2237 * - unique number to identify actual perf.data files
2238 * - encode endianness of file 2238 * - encode endianness of file
2239 */ 2239 */
2240 ph->version = PERF_HEADER_VERSION_2;
2240 2241
2241 /* check magic number with one endianness */ 2242 /* check magic number with one endianness */
2242 if (magic == __perf_magic2) 2243 if (magic == __perf_magic2)
@@ -2247,7 +2248,6 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2247 return -1; 2248 return -1;
2248 2249
2249 ph->needs_swap = true; 2250 ph->needs_swap = true;
2250 ph->version = PERF_HEADER_VERSION_2;
2251 2251
2252 return 0; 2252 return 0;
2253} 2253}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 182395546ddc..70b48a65064c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -241,6 +241,20 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
241 return he->stat.period == 0; 241 return he->stat.period == 0;
242} 242}
243 243
244static void hists__delete_entry(struct hists *hists, struct hist_entry *he)
245{
246 rb_erase(&he->rb_node, &hists->entries);
247
248 if (sort__need_collapse)
249 rb_erase(&he->rb_node_in, &hists->entries_collapsed);
250
251 --hists->nr_entries;
252 if (!he->filtered)
253 --hists->nr_non_filtered_entries;
254
255 hist_entry__delete(he);
256}
257
244void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel) 258void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
245{ 259{
246 struct rb_node *next = rb_first(&hists->entries); 260 struct rb_node *next = rb_first(&hists->entries);
@@ -258,16 +272,7 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
258 (zap_kernel && n->level != '.') || 272 (zap_kernel && n->level != '.') ||
259 hists__decay_entry(hists, n)) && 273 hists__decay_entry(hists, n)) &&
260 !n->used) { 274 !n->used) {
261 rb_erase(&n->rb_node, &hists->entries); 275 hists__delete_entry(hists, n);
262
263 if (sort__need_collapse)
264 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
265
266 --hists->nr_entries;
267 if (!n->filtered)
268 --hists->nr_non_filtered_entries;
269
270 hist_entry__free(n);
271 } 276 }
272 } 277 }
273} 278}
@@ -281,16 +286,7 @@ void hists__delete_entries(struct hists *hists)
281 n = rb_entry(next, struct hist_entry, rb_node); 286 n = rb_entry(next, struct hist_entry, rb_node);
282 next = rb_next(&n->rb_node); 287 next = rb_next(&n->rb_node);
283 288
284 rb_erase(&n->rb_node, &hists->entries); 289 hists__delete_entry(hists, n);
285
286 if (sort__need_collapse)
287 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
288
289 --hists->nr_entries;
290 if (!n->filtered)
291 --hists->nr_non_filtered_entries;
292
293 hist_entry__free(n);
294 } 290 }
295} 291}
296 292
@@ -433,6 +429,8 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
433 if (!he) 429 if (!he)
434 return NULL; 430 return NULL;
435 431
432 hists->nr_entries++;
433
436 rb_link_node(&he->rb_node_in, parent, p); 434 rb_link_node(&he->rb_node_in, parent, p);
437 rb_insert_color(&he->rb_node_in, hists->entries_in); 435 rb_insert_color(&he->rb_node_in, hists->entries_in);
438out: 436out:
@@ -915,7 +913,7 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
915 if (perf_hpp__should_skip(fmt)) 913 if (perf_hpp__should_skip(fmt))
916 continue; 914 continue;
917 915
918 cmp = fmt->cmp(left, right); 916 cmp = fmt->cmp(fmt, left, right);
919 if (cmp) 917 if (cmp)
920 break; 918 break;
921 } 919 }
@@ -933,7 +931,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
933 if (perf_hpp__should_skip(fmt)) 931 if (perf_hpp__should_skip(fmt))
934 continue; 932 continue;
935 933
936 cmp = fmt->collapse(left, right); 934 cmp = fmt->collapse(fmt, left, right);
937 if (cmp) 935 if (cmp)
938 break; 936 break;
939 } 937 }
@@ -941,7 +939,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
941 return cmp; 939 return cmp;
942} 940}
943 941
944void hist_entry__free(struct hist_entry *he) 942void hist_entry__delete(struct hist_entry *he)
945{ 943{
946 zfree(&he->branch_info); 944 zfree(&he->branch_info);
947 zfree(&he->mem_info); 945 zfree(&he->mem_info);
@@ -981,7 +979,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
981 iter->callchain, 979 iter->callchain,
982 he->callchain); 980 he->callchain);
983 } 981 }
984 hist_entry__free(he); 982 hist_entry__delete(he);
985 return false; 983 return false;
986 } 984 }
987 985
@@ -1063,7 +1061,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
1063 if (perf_hpp__should_skip(fmt)) 1061 if (perf_hpp__should_skip(fmt))
1064 continue; 1062 continue;
1065 1063
1066 cmp = fmt->sort(a, b); 1064 cmp = fmt->sort(fmt, a, b);
1067 if (cmp) 1065 if (cmp)
1068 break; 1066 break;
1069 } 1067 }
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 46bd50344f85..2b690d028907 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -119,7 +119,7 @@ int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
119int hist_entry__transaction_len(void); 119int hist_entry__transaction_len(void);
120int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, 120int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
121 struct hists *hists); 121 struct hists *hists);
122void hist_entry__free(struct hist_entry *); 122void hist_entry__delete(struct hist_entry *he);
123 123
124void hists__output_resort(struct hists *hists, struct ui_progress *prog); 124void hists__output_resort(struct hists *hists, struct ui_progress *prog);
125void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 125void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
@@ -195,9 +195,12 @@ struct perf_hpp_fmt {
195 struct hist_entry *he); 195 struct hist_entry *he);
196 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 196 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
197 struct hist_entry *he); 197 struct hist_entry *he);
198 int64_t (*cmp)(struct hist_entry *a, struct hist_entry *b); 198 int64_t (*cmp)(struct perf_hpp_fmt *fmt,
199 int64_t (*collapse)(struct hist_entry *a, struct hist_entry *b); 199 struct hist_entry *a, struct hist_entry *b);
200 int64_t (*sort)(struct hist_entry *a, struct hist_entry *b); 200 int64_t (*collapse)(struct perf_hpp_fmt *fmt,
201 struct hist_entry *a, struct hist_entry *b);
202 int64_t (*sort)(struct perf_hpp_fmt *fmt,
203 struct hist_entry *a, struct hist_entry *b);
201 204
202 struct list_head list; 205 struct list_head list;
203 struct list_head sort_list; 206 struct list_head sort_list;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 77b43fe43d55..7f8ec6ce2823 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -526,7 +526,7 @@ do { \
526} 526}
527 527
528int parse_events_add_breakpoint(struct list_head *list, int *idx, 528int parse_events_add_breakpoint(struct list_head *list, int *idx,
529 void *ptr, char *type) 529 void *ptr, char *type, u64 len)
530{ 530{
531 struct perf_event_attr attr; 531 struct perf_event_attr attr;
532 532
@@ -536,14 +536,15 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
536 if (parse_breakpoint_type(type, &attr)) 536 if (parse_breakpoint_type(type, &attr))
537 return -EINVAL; 537 return -EINVAL;
538 538
539 /* 539 /* Provide some defaults if len is not specified */
540 * We should find a nice way to override the access length 540 if (!len) {
541 * Provide some defaults for now 541 if (attr.bp_type == HW_BREAKPOINT_X)
542 */ 542 len = sizeof(long);
543 if (attr.bp_type == HW_BREAKPOINT_X) 543 else
544 attr.bp_len = sizeof(long); 544 len = HW_BREAKPOINT_LEN_4;
545 else 545 }
546 attr.bp_len = HW_BREAKPOINT_LEN_4; 546
547 attr.bp_len = len;
547 548
548 attr.type = PERF_TYPE_BREAKPOINT; 549 attr.type = PERF_TYPE_BREAKPOINT;
549 attr.sample_period = 1; 550 attr.sample_period = 1;
@@ -1121,7 +1122,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1121 return; 1122 return;
1122 1123
1123 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1124 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1124 if (subsys_glob != NULL && 1125 if (subsys_glob != NULL &&
1125 !strglobmatch(sys_dirent.d_name, subsys_glob)) 1126 !strglobmatch(sys_dirent.d_name, subsys_glob))
1126 continue; 1127 continue;
1127 1128
@@ -1132,7 +1133,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1132 continue; 1133 continue;
1133 1134
1134 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 1135 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
1135 if (event_glob != NULL && 1136 if (event_glob != NULL &&
1136 !strglobmatch(evt_dirent.d_name, event_glob)) 1137 !strglobmatch(evt_dirent.d_name, event_glob))
1137 continue; 1138 continue;
1138 1139
@@ -1305,7 +1306,7 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1305 1306
1306 for (i = 0; i < max; i++, syms++) { 1307 for (i = 0; i < max; i++, syms++) {
1307 1308
1308 if (event_glob != NULL && 1309 if (event_glob != NULL &&
1309 !(strglobmatch(syms->symbol, event_glob) || 1310 !(strglobmatch(syms->symbol, event_glob) ||
1310 (syms->alias && strglobmatch(syms->alias, event_glob)))) 1311 (syms->alias && strglobmatch(syms->alias, event_glob))))
1311 continue; 1312 continue;
@@ -1366,7 +1367,7 @@ void print_events(const char *event_glob, bool name_only)
1366 printf("\n"); 1367 printf("\n");
1367 1368
1368 printf(" %-50s [%s]\n", 1369 printf(" %-50s [%s]\n",
1369 "mem:<addr>[:access]", 1370 "mem:<addr>[/len][:access]",
1370 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1371 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
1371 printf("\n"); 1372 printf("\n");
1372 } 1373 }
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index db2cf78ff0f3..ff6e1fa4111e 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ struct parse_events_term {
71 int type_val; 71 int type_val;
72 int type_term; 72 int type_term;
73 struct list_head list; 73 struct list_head list;
74 bool used;
74}; 75};
75 76
76struct parse_events_evlist { 77struct parse_events_evlist {
@@ -104,7 +105,7 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
104int parse_events_add_cache(struct list_head *list, int *idx, 105int parse_events_add_cache(struct list_head *list, int *idx,
105 char *type, char *op_result1, char *op_result2); 106 char *type, char *op_result1, char *op_result2);
106int parse_events_add_breakpoint(struct list_head *list, int *idx, 107int parse_events_add_breakpoint(struct list_head *list, int *idx,
107 void *ptr, char *type); 108 void *ptr, char *type, u64 len);
108int parse_events_add_pmu(struct list_head *list, int *idx, 109int parse_events_add_pmu(struct list_head *list, int *idx,
109 char *pmu , struct list_head *head_config); 110 char *pmu , struct list_head *head_config);
110enum perf_pmu_event_symbol_type 111enum perf_pmu_event_symbol_type
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 906630bbf8eb..94eacb6c1ef7 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -159,6 +159,7 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
159<mem>{ 159<mem>{
160{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } 160{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
161: { return ':'; } 161: { return ':'; }
162"/" { return '/'; }
162{num_dec} { return value(yyscanner, 10); } 163{num_dec} { return value(yyscanner, 10); }
163{num_hex} { return value(yyscanner, 16); } 164{num_hex} { return value(yyscanner, 16); }
164 /* 165 /*
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 93c4c9fbc922..72def077dbbf 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -326,6 +326,28 @@ PE_NAME_CACHE_TYPE
326} 326}
327 327
328event_legacy_mem: 328event_legacy_mem:
329PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
330{
331 struct parse_events_evlist *data = _data;
332 struct list_head *list;
333
334 ALLOC_LIST(list);
335 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
336 (void *) $2, $6, $4));
337 $$ = list;
338}
339|
340PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
341{
342 struct parse_events_evlist *data = _data;
343 struct list_head *list;
344
345 ALLOC_LIST(list);
346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
347 (void *) $2, NULL, $4));
348 $$ = list;
349}
350|
329PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 351PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
330{ 352{
331 struct parse_events_evlist *data = _data; 353 struct parse_events_evlist *data = _data;
@@ -333,7 +355,7 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
333 355
334 ALLOC_LIST(list); 356 ALLOC_LIST(list);
335 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 357 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
336 (void *) $2, $4)); 358 (void *) $2, $4, 0));
337 $$ = list; 359 $$ = list;
338} 360}
339| 361|
@@ -344,7 +366,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc
344 366
345 ALLOC_LIST(list); 367 ALLOC_LIST(list);
346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 368 ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
347 (void *) $2, NULL)); 369 (void *) $2, NULL, 0));
348 $$ = list; 370 $$ = list;
349} 371}
350 372
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index f62dee7bd924..4a015f77e2b5 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -46,7 +46,7 @@ static int get_value(struct parse_opt_ctx_t *p,
46 return opterror(opt, "is not usable", flags); 46 return opterror(opt, "is not usable", flags);
47 47
48 if (opt->flags & PARSE_OPT_EXCLUSIVE) { 48 if (opt->flags & PARSE_OPT_EXCLUSIVE) {
49 if (p->excl_opt) { 49 if (p->excl_opt && p->excl_opt != opt) {
50 char msg[128]; 50 char msg[128];
51 51
52 if (((flags & OPT_SHORT) && p->excl_opt->short_name) || 52 if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 5c9c4947cfb4..48411674da0f 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -551,31 +551,68 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
551} 551}
552 552
553/* 553/*
554 * Term is a string term, and might be a param-term. Try to look up it's value
555 * in the remaining terms.
556 * - We have a term like "base-or-format-term=param-term",
557 * - We need to find the value supplied for "param-term" (with param-term named
558 * in a config string) later on in the term list.
559 */
560static int pmu_resolve_param_term(struct parse_events_term *term,
561 struct list_head *head_terms,
562 __u64 *value)
563{
564 struct parse_events_term *t;
565
566 list_for_each_entry(t, head_terms, list) {
567 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
568 if (!strcmp(t->config, term->config)) {
569 t->used = true;
570 *value = t->val.num;
571 return 0;
572 }
573 }
574 }
575
576 if (verbose)
577 printf("Required parameter '%s' not specified\n", term->config);
578
579 return -1;
580}
581
582/*
554 * Setup one of config[12] attr members based on the 583 * Setup one of config[12] attr members based on the
555 * user input data - term parameter. 584 * user input data - term parameter.
556 */ 585 */
557static int pmu_config_term(struct list_head *formats, 586static int pmu_config_term(struct list_head *formats,
558 struct perf_event_attr *attr, 587 struct perf_event_attr *attr,
559 struct parse_events_term *term, 588 struct parse_events_term *term,
589 struct list_head *head_terms,
560 bool zero) 590 bool zero)
561{ 591{
562 struct perf_pmu_format *format; 592 struct perf_pmu_format *format;
563 __u64 *vp; 593 __u64 *vp;
594 __u64 val;
595
596 /*
597 * If this is a parameter we've already used for parameterized-eval,
598 * skip it in normal eval.
599 */
600 if (term->used)
601 return 0;
564 602
565 /* 603 /*
566 * Support only for hardcoded and numnerial terms.
567 * Hardcoded terms should be already in, so nothing 604 * Hardcoded terms should be already in, so nothing
568 * to be done for them. 605 * to be done for them.
569 */ 606 */
570 if (parse_events__is_hardcoded_term(term)) 607 if (parse_events__is_hardcoded_term(term))
571 return 0; 608 return 0;
572 609
573 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
574 return -EINVAL;
575
576 format = pmu_find_format(formats, term->config); 610 format = pmu_find_format(formats, term->config);
577 if (!format) 611 if (!format) {
612 if (verbose)
613 printf("Invalid event/parameter '%s'\n", term->config);
578 return -EINVAL; 614 return -EINVAL;
615 }
579 616
580 switch (format->value) { 617 switch (format->value) {
581 case PERF_PMU_FORMAT_VALUE_CONFIG: 618 case PERF_PMU_FORMAT_VALUE_CONFIG:
@@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats,
592 } 629 }
593 630
594 /* 631 /*
595 * XXX If we ever decide to go with string values for 632 * Either directly use a numeric term, or try to translate string terms
596 * non-hardcoded terms, here's the place to translate 633 * using event parameters.
597 * them into value.
598 */ 634 */
599 pmu_format_value(format->bits, term->val.num, vp, zero); 635 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
636 val = term->val.num;
637 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
638 if (strcmp(term->val.str, "?")) {
639 if (verbose)
640 pr_info("Invalid sysfs entry %s=%s\n",
641 term->config, term->val.str);
642 return -EINVAL;
643 }
644
645 if (pmu_resolve_param_term(term, head_terms, &val))
646 return -EINVAL;
647 } else
648 return -EINVAL;
649
650 pmu_format_value(format->bits, val, vp, zero);
600 return 0; 651 return 0;
601} 652}
602 653
@@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats,
607{ 658{
608 struct parse_events_term *term; 659 struct parse_events_term *term;
609 660
610 list_for_each_entry(term, head_terms, list) 661 list_for_each_entry(term, head_terms, list) {
611 if (pmu_config_term(formats, attr, term, zero)) 662 if (pmu_config_term(formats, attr, term, head_terms, zero))
612 return -EINVAL; 663 return -EINVAL;
664 }
613 665
614 return 0; 666 return 0;
615} 667}
@@ -767,10 +819,36 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
767 set_bit(b, bits); 819 set_bit(b, bits);
768} 820}
769 821
822static int sub_non_neg(int a, int b)
823{
824 if (b > a)
825 return 0;
826 return a - b;
827}
828
770static char *format_alias(char *buf, int len, struct perf_pmu *pmu, 829static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
771 struct perf_pmu_alias *alias) 830 struct perf_pmu_alias *alias)
772{ 831{
773 snprintf(buf, len, "%s/%s/", pmu->name, alias->name); 832 struct parse_events_term *term;
833 int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
834
835 list_for_each_entry(term, &alias->terms, list) {
836 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
837 used += snprintf(buf + used, sub_non_neg(len, used),
838 ",%s=%s", term->config,
839 term->val.str);
840 }
841
842 if (sub_non_neg(len, used) > 0) {
843 buf[used] = '/';
844 used++;
845 }
846 if (sub_non_neg(len, used) > 0) {
847 buf[used] = '\0';
848 used++;
849 } else
850 buf[len - 1] = '\0';
851
774 return buf; 852 return buf;
775} 853}
776 854
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 3dda85ca50c1..d906d0ad5d40 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -768,7 +768,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
768 Py_DECREF(file); 768 Py_DECREF(file);
769 goto free_list; 769 goto free_list;
770 } 770 }
771 771
772 Py_DECREF(file); 772 Py_DECREF(file);
773 } 773 }
774 774
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index d808a328f4dc..0c815a40a6e8 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -89,7 +89,7 @@ static void handler_call_die(const char *handler_name)
89 89
90/* 90/*
91 * Insert val into into the dictionary and decrement the reference counter. 91 * Insert val into into the dictionary and decrement the reference counter.
92 * This is necessary for dictionaries since PyDict_SetItemString() does not 92 * This is necessary for dictionaries since PyDict_SetItemString() does not
93 * steal a reference, as opposed to PyTuple_SetItem(). 93 * steal a reference, as opposed to PyTuple_SetItem().
94 */ 94 */
95static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val) 95static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5f0e05a76c05..0baf75f12b7c 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -274,7 +274,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
274 if (tool->id_index == NULL) 274 if (tool->id_index == NULL)
275 tool->id_index = process_id_index_stub; 275 tool->id_index = process_id_index_stub;
276} 276}
277 277
278static void swap_sample_id_all(union perf_event *event, void *data) 278static void swap_sample_id_all(union perf_event *event, void *data)
279{ 279{
280 void *end = (void *) event + event->header.size; 280 void *end = (void *) event + event->header.size;
@@ -1251,9 +1251,9 @@ fetch_mmaped_event(struct perf_session *session,
1251#define NUM_MMAPS 128 1251#define NUM_MMAPS 128
1252#endif 1252#endif
1253 1253
1254int __perf_session__process_events(struct perf_session *session, 1254static int __perf_session__process_events(struct perf_session *session,
1255 u64 data_offset, u64 data_size, 1255 u64 data_offset, u64 data_size,
1256 u64 file_size, struct perf_tool *tool) 1256 u64 file_size, struct perf_tool *tool)
1257{ 1257{
1258 int fd = perf_data_file__fd(session->file); 1258 int fd = perf_data_file__fd(session->file);
1259 u64 head, page_offset, file_offset, file_pos, size; 1259 u64 head, page_offset, file_offset, file_pos, size;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index dc26ebf60fe4..6d663dc76404 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -49,9 +49,6 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 union perf_event **event_ptr, 49 union perf_event **event_ptr,
50 struct perf_sample *sample); 50 struct perf_sample *sample);
51 51
52int __perf_session__process_events(struct perf_session *session,
53 u64 data_offset, u64 data_size, u64 size,
54 struct perf_tool *tool);
55int perf_session__process_events(struct perf_session *session, 52int perf_session__process_events(struct perf_session *session,
56 struct perf_tool *tool); 53 struct perf_tool *tool);
57 54
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9139dda9f9a3..7a39c1ed8d37 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1304,6 +1304,37 @@ static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1304 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 1304 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1305} 1305}
1306 1306
1307static int64_t __sort__hpp_cmp(struct perf_hpp_fmt *fmt,
1308 struct hist_entry *a, struct hist_entry *b)
1309{
1310 struct hpp_sort_entry *hse;
1311
1312 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1313 return hse->se->se_cmp(a, b);
1314}
1315
1316static int64_t __sort__hpp_collapse(struct perf_hpp_fmt *fmt,
1317 struct hist_entry *a, struct hist_entry *b)
1318{
1319 struct hpp_sort_entry *hse;
1320 int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
1321
1322 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1323 collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp;
1324 return collapse_fn(a, b);
1325}
1326
1327static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt,
1328 struct hist_entry *a, struct hist_entry *b)
1329{
1330 struct hpp_sort_entry *hse;
1331 int64_t (*sort_fn)(struct hist_entry *, struct hist_entry *);
1332
1333 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1334 sort_fn = hse->se->se_sort ?: hse->se->se_cmp;
1335 return sort_fn(a, b);
1336}
1337
1307static struct hpp_sort_entry * 1338static struct hpp_sort_entry *
1308__sort_dimension__alloc_hpp(struct sort_dimension *sd) 1339__sort_dimension__alloc_hpp(struct sort_dimension *sd)
1309{ 1340{
@@ -1322,9 +1353,9 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1322 hse->hpp.entry = __sort__hpp_entry; 1353 hse->hpp.entry = __sort__hpp_entry;
1323 hse->hpp.color = NULL; 1354 hse->hpp.color = NULL;
1324 1355
1325 hse->hpp.cmp = sd->entry->se_cmp; 1356 hse->hpp.cmp = __sort__hpp_cmp;
1326 hse->hpp.collapse = sd->entry->se_collapse ? : sd->entry->se_cmp; 1357 hse->hpp.collapse = __sort__hpp_collapse;
1327 hse->hpp.sort = sd->entry->se_sort ? : hse->hpp.collapse; 1358 hse->hpp.sort = __sort__hpp_sort;
1328 1359
1329 INIT_LIST_HEAD(&hse->hpp.list); 1360 INIT_LIST_HEAD(&hse->hpp.list);
1330 INIT_LIST_HEAD(&hse->hpp.sort_list); 1361 INIT_LIST_HEAD(&hse->hpp.sort_list);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 06fcd1bf98b6..b24f9d8727a8 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -574,13 +574,16 @@ static int decompress_kmodule(struct dso *dso, const char *name,
574 const char *ext = strrchr(name, '.'); 574 const char *ext = strrchr(name, '.');
575 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; 575 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
576 576
577 if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && 577 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
578 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) || 578 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
579 type != dso->symtab_type) 579 type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
580 return -1; 580 return -1;
581 581
582 if (!ext || !is_supported_compression(ext + 1)) 582 if (!ext || !is_supported_compression(ext + 1)) {
583 return -1; 583 ext = strrchr(dso->name, '.');
584 if (!ext || !is_supported_compression(ext + 1))
585 return -1;
586 }
584 587
585 fd = mkstemp(tmpbuf); 588 fd = mkstemp(tmpbuf);
586 if (fd < 0) 589 if (fd < 0)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a194702a0a2f..a69066865a55 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -685,7 +685,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
685 struct machine *machine = kmaps->machine; 685 struct machine *machine = kmaps->machine;
686 struct map *curr_map = map; 686 struct map *curr_map = map;
687 struct symbol *pos; 687 struct symbol *pos;
688 int count = 0, moved = 0; 688 int count = 0, moved = 0;
689 struct rb_root *root = &dso->symbols[map->type]; 689 struct rb_root *root = &dso->symbols[map->type];
690 struct rb_node *next = rb_first(root); 690 struct rb_node *next = rb_first(root);
691 int kernel_range = 0; 691 int kernel_range = 0;
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 6edf535f65c2..e3c40a520a25 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -266,14 +266,17 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
266 u64 *fde_count) 266 u64 *fde_count)
267{ 267{
268 int ret = -EINVAL, fd; 268 int ret = -EINVAL, fd;
269 u64 offset; 269 u64 offset = dso->data.frame_offset;
270 270
271 fd = dso__data_fd(dso, machine); 271 if (offset == 0) {
272 if (fd < 0) 272 fd = dso__data_fd(dso, machine);
273 return -EINVAL; 273 if (fd < 0)
274 return -EINVAL;
274 275
275 /* Check the .eh_frame section for unwinding info */ 276 /* Check the .eh_frame section for unwinding info */
276 offset = elf_section_offset(fd, ".eh_frame_hdr"); 277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.frame_offset = offset;
279 }
277 280
278 if (offset) 281 if (offset)
279 ret = unwind_spec_ehframe(dso, machine, offset, 282 ret = unwind_spec_ehframe(dso, machine, offset,
@@ -287,14 +290,20 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
287static int read_unwind_spec_debug_frame(struct dso *dso, 290static int read_unwind_spec_debug_frame(struct dso *dso,
288 struct machine *machine, u64 *offset) 291 struct machine *machine, u64 *offset)
289{ 292{
290 int fd = dso__data_fd(dso, machine); 293 int fd;
294 u64 ofs = dso->data.frame_offset;
291 295
292 if (fd < 0) 296 if (ofs == 0) {
293 return -EINVAL; 297 fd = dso__data_fd(dso, machine);
298 if (fd < 0)
299 return -EINVAL;
294 300
295 /* Check the .debug_frame section for unwinding info */ 301 /* Check the .debug_frame section for unwinding info */
296 *offset = elf_section_offset(fd, ".debug_frame"); 302 ofs = elf_section_offset(fd, ".debug_frame");
303 dso->data.frame_offset = ofs;
304 }
297 305
306 *offset = ofs;
298 if (*offset) 307 if (*offset)
299 return 0; 308 return 0;
300 309
diff --git a/tools/testing/selftests/rcutorture/bin/cpus2use.sh b/tools/testing/selftests/rcutorture/bin/cpus2use.sh
index abe14b7f36e9..bb99cde3f5f9 100755
--- a/tools/testing/selftests/rcutorture/bin/cpus2use.sh
+++ b/tools/testing/selftests/rcutorture/bin/cpus2use.sh
@@ -24,7 +24,7 @@
24 24
25ncpus=`grep '^processor' /proc/cpuinfo | wc -l` 25ncpus=`grep '^processor' /proc/cpuinfo | wc -l`
26idlecpus=`mpstat | tail -1 | \ 26idlecpus=`mpstat | tail -1 | \
27 awk -v ncpus=$ncpus '{ print ncpus * ($7 + $12) / 100 }'` 27 awk -v ncpus=$ncpus '{ print ncpus * ($7 + $NF) / 100 }'`
28awk -v ncpus=$ncpus -v idlecpus=$idlecpus < /dev/null ' 28awk -v ncpus=$ncpus -v idlecpus=$idlecpus < /dev/null '
29BEGIN { 29BEGIN {
30 cpus2use = idlecpus; 30 cpus2use = idlecpus;
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
index d6cc07fc137f..559e01ac86be 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
@@ -30,6 +30,7 @@ else
30 echo Unreadable results directory: $i 30 echo Unreadable results directory: $i
31 exit 1 31 exit 1
32fi 32fi
33. tools/testing/selftests/rcutorture/bin/functions.sh
33 34
34configfile=`echo $i | sed -e 's/^.*\///'` 35configfile=`echo $i | sed -e 's/^.*\///'`
35ngps=`grep ver: $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* ver: //' -e 's/ .*$//'` 36ngps=`grep ver: $i/console.log 2> /dev/null | tail -1 | sed -e 's/^.* ver: //' -e 's/ .*$//'`
@@ -48,4 +49,21 @@ else
48 title="$title ($ngpsps per second)" 49 title="$title ($ngpsps per second)"
49 fi 50 fi
50 echo $title 51 echo $title
52 nclosecalls=`grep --binary-files=text 'torture: Reader Batch' $i/console.log | tail -1 | awk '{for (i=NF-8;i<=NF;i++) sum+=$i; } END {print sum}'`
53 if test -z "$nclosecalls"
54 then
55 exit 0
56 fi
57 if test "$nclosecalls" -eq 0
58 then
59 exit 0
60 fi
61 # Compute number of close calls per tenth of an hour
62 nclosecalls10=`awk -v nclosecalls=$nclosecalls -v dur=$dur 'BEGIN { print int(nclosecalls * 36000 / dur) }' < /dev/null`
63 if test $nclosecalls10 -gt 5 -a $nclosecalls -gt 1
64 then
65 print_bug $nclosecalls "Reader Batch close calls in" $(($dur/60)) minute run: $i
66 else
67 print_warning $nclosecalls "Reader Batch close calls in" $(($dur/60)) minute run: $i
68 fi
51fi 69fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 8ca9f21f2efc..5236e073919d 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -8,9 +8,9 @@
8# 8#
9# Usage: kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args 9# Usage: kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args
10# 10#
11# qemu-args defaults to "-nographic", along with arguments specifying the 11# qemu-args defaults to "-enable-kvm -soundhw pcspk -nographic", along with
12# number of CPUs and other options generated from 12# arguments specifying the number of CPUs and other
13# the underlying CPU architecture. 13# options generated from the underlying CPU architecture.
14# boot_args defaults to value returned by the per_version_boot_params 14# boot_args defaults to value returned by the per_version_boot_params
15# shell function. 15# shell function.
16# 16#
@@ -138,7 +138,7 @@ then
138fi 138fi
139 139
140# Generate -smp qemu argument. 140# Generate -smp qemu argument.
141qemu_args="-nographic $qemu_args" 141qemu_args="-enable-kvm -soundhw pcspk -nographic $qemu_args"
142cpu_count=`configNR_CPUS.sh $config_template` 142cpu_count=`configNR_CPUS.sh $config_template`
143cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"` 143cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"`
144vcpus=`identify_qemu_vcpus` 144vcpus=`identify_qemu_vcpus`
@@ -168,6 +168,7 @@ then
168 touch $resdir/buildonly 168 touch $resdir/buildonly
169 exit 0 169 exit 0
170fi 170fi
171echo "NOTE: $QEMU either did not run or was interactive" > $builddir/console.log
171echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd 172echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
172( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) & 173( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) &
173qemu_pid=$! 174qemu_pid=$!
diff --git a/tools/testing/selftests/rcutorture/bin/parse-build.sh b/tools/testing/selftests/rcutorture/bin/parse-build.sh
index 499d1e598e42..a6b57622c2e5 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-build.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-build.sh
@@ -26,12 +26,15 @@
26# 26#
27# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 27# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
28 28
29T=$1 29F=$1
30title=$2 30title=$2
31T=/tmp/parse-build.sh.$$
32trap 'rm -rf $T' 0
33mkdir $T
31 34
32. functions.sh 35. functions.sh
33 36
34if grep -q CC < $T 37if grep -q CC < $F
35then 38then
36 : 39 :
37else 40else
@@ -39,18 +42,21 @@ else
39 exit 1 42 exit 1
40fi 43fi
41 44
42if grep -q "error:" < $T 45if grep -q "error:" < $F
43then 46then
44 print_bug $title build errors: 47 print_bug $title build errors:
45 grep "error:" < $T 48 grep "error:" < $F
46 exit 2 49 exit 2
47fi 50fi
48exit 0
49 51
50if egrep -q "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T 52grep warning: < $F > $T/warnings
53grep "include/linux/*rcu*\.h:" $T/warnings > $T/hwarnings
54grep "kernel/rcu/[^/]*:" $T/warnings > $T/cwarnings
55cat $T/hwarnings $T/cwarnings > $T/rcuwarnings
56if test -s $T/rcuwarnings
51then 57then
52 print_warning $title build errors: 58 print_warning $title build errors:
53 egrep "rcu[^/]*\.c.*warning:|rcu.*\.h.*warning:" < $T 59 cat $T/rcuwarnings
54 exit 2 60 exit 2
55fi 61fi
56exit 0 62exit 0
diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh
index f962ba4cf68b..d8f35cf116be 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-console.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh
@@ -36,7 +36,7 @@ if grep -Pq '\x00' < $file
36then 36then
37 print_warning Console output contains nul bytes, old qemu still running? 37 print_warning Console output contains nul bytes, old qemu still running?
38fi 38fi
39egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T 39egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|Stall ended before state dump start' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T
40if test -s $T 40if test -s $T
41then 41then
42 print_warning Assertion failure in $file $title 42 print_warning Assertion failure in $file $title