aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-20 14:29:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-20 14:29:32 -0400
commit12e24f34cb0d55efd08c18b2112507d4bf498008 (patch)
tree83b07be17b8ef45f42360a3b9159b3aaae3fbad4 /tools/perf
parent1eb51c33b21ffa3fceb634d1d6bcd6488c79bc26 (diff)
parenteadc84cc01e04f9f74ec2de0c9355be035c7b396 (diff)
Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (49 commits) perfcounter: Handle some IO return values perf_counter: Push perf_sample_data through the swcounter code perf_counter tools: Define and use our own u64, s64 etc. definitions perf_counter: Close race in perf_lock_task_context() perf_counter, x86: Improve interactions with fast-gup perf_counter: Simplify and fix task migration counting perf_counter tools: Add a data file header perf_counter: Update userspace callchain sampling uses perf_counter: Make callchain samples extensible perf report: Filter to parent set by default perf_counter tools: Handle lost events perf_counter: Add event overlow handling fs: Provide empty .set_page_dirty() aop for anon inodes perf_counter: tools: Makefile tweaks for 64-bit powerpc perf_counter: powerpc: Add processor back-end for MPC7450 family perf_counter: powerpc: Make powerpc perf_counter code safe for 32-bit kernels perf_counter: powerpc: Change how processor-specific back-ends get selected perf_counter: powerpc: Use unsigned long for register and constraint values perf_counter: powerpc: Enable use of software counters on 32-bit powerpc perf_counter tools: Add and use isprint() ...
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile10
-rw-r--r--tools/perf/builtin-annotate.c262
-rw-r--r--tools/perf/builtin-record.c163
-rw-r--r--tools/perf/builtin-report.c439
-rw-r--r--tools/perf/builtin-stat.c308
-rw-r--r--tools/perf/builtin-top.c24
-rw-r--r--tools/perf/perf.h7
-rw-r--r--tools/perf/types.h17
-rw-r--r--tools/perf/util/ctype.c17
-rw-r--r--tools/perf/util/parse-events.c14
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/string.h4
-rw-r--r--tools/perf/util/symbol.c20
-rw-r--r--tools/perf/util/symbol.h16
-rw-r--r--tools/perf/util/util.h18
15 files changed, 992 insertions, 329 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 0cbd5d6874ec..36d7eef49913 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -157,10 +157,15 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
157uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') 157uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') 158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
159 159
160# If we're on a 64-bit kernel, use -m64
161ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
162 M64 := -m64
163endif
164
160# CFLAGS and LDFLAGS are for the users to override from the command line. 165# CFLAGS and LDFLAGS are for the users to override from the command line.
161 166
162CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6 167CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6
163LDFLAGS = -lpthread -lrt -lelf 168LDFLAGS = -lpthread -lrt -lelf -lm
164ALL_CFLAGS = $(CFLAGS) 169ALL_CFLAGS = $(CFLAGS)
165ALL_LDFLAGS = $(LDFLAGS) 170ALL_LDFLAGS = $(LDFLAGS)
166STRIP ?= strip 171STRIP ?= strip
@@ -285,6 +290,7 @@ LIB_FILE=libperf.a
285 290
286LIB_H += ../../include/linux/perf_counter.h 291LIB_H += ../../include/linux/perf_counter.h
287LIB_H += perf.h 292LIB_H += perf.h
293LIB_H += types.h
288LIB_H += util/list.h 294LIB_H += util/list.h
289LIB_H += util/rbtree.h 295LIB_H += util/rbtree.h
290LIB_H += util/levenshtein.h 296LIB_H += util/levenshtein.h
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index b1ed5f766cb3..7e58e3ad1508 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -25,6 +25,10 @@
25#define SHOW_USER 2 25#define SHOW_USER 2
26#define SHOW_HV 4 26#define SHOW_HV 4
27 27
28#define MIN_GREEN 0.5
29#define MIN_RED 5.0
30
31
28static char const *input_name = "perf.data"; 32static char const *input_name = "perf.data";
29static char *vmlinux = "vmlinux"; 33static char *vmlinux = "vmlinux";
30 34
@@ -39,40 +43,42 @@ static int dump_trace = 0;
39 43
40static int verbose; 44static int verbose;
41 45
46static int print_line;
47
42static unsigned long page_size; 48static unsigned long page_size;
43static unsigned long mmap_window = 32; 49static unsigned long mmap_window = 32;
44 50
45struct ip_event { 51struct ip_event {
46 struct perf_event_header header; 52 struct perf_event_header header;
47 __u64 ip; 53 u64 ip;
48 __u32 pid, tid; 54 u32 pid, tid;
49}; 55};
50 56
51struct mmap_event { 57struct mmap_event {
52 struct perf_event_header header; 58 struct perf_event_header header;
53 __u32 pid, tid; 59 u32 pid, tid;
54 __u64 start; 60 u64 start;
55 __u64 len; 61 u64 len;
56 __u64 pgoff; 62 u64 pgoff;
57 char filename[PATH_MAX]; 63 char filename[PATH_MAX];
58}; 64};
59 65
60struct comm_event { 66struct comm_event {
61 struct perf_event_header header; 67 struct perf_event_header header;
62 __u32 pid, tid; 68 u32 pid, tid;
63 char comm[16]; 69 char comm[16];
64}; 70};
65 71
66struct fork_event { 72struct fork_event {
67 struct perf_event_header header; 73 struct perf_event_header header;
68 __u32 pid, ppid; 74 u32 pid, ppid;
69}; 75};
70 76
71struct period_event { 77struct period_event {
72 struct perf_event_header header; 78 struct perf_event_header header;
73 __u64 time; 79 u64 time;
74 __u64 id; 80 u64 id;
75 __u64 sample_period; 81 u64 sample_period;
76}; 82};
77 83
78typedef union event_union { 84typedef union event_union {
@@ -84,6 +90,13 @@ typedef union event_union {
84 struct period_event period; 90 struct period_event period;
85} event_t; 91} event_t;
86 92
93
94struct sym_ext {
95 struct rb_node node;
96 double percent;
97 char *path;
98};
99
87static LIST_HEAD(dsos); 100static LIST_HEAD(dsos);
88static struct dso *kernel_dso; 101static struct dso *kernel_dso;
89static struct dso *vdso; 102static struct dso *vdso;
@@ -145,7 +158,7 @@ static void dsos__fprintf(FILE *fp)
145 dso__fprintf(pos, fp); 158 dso__fprintf(pos, fp);
146} 159}
147 160
148static struct symbol *vdso__find_symbol(struct dso *dso, __u64 ip) 161static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
149{ 162{
150 return dso__find_symbol(kernel_dso, ip); 163 return dso__find_symbol(kernel_dso, ip);
151} 164}
@@ -178,19 +191,19 @@ static int load_kernel(void)
178 191
179struct map { 192struct map {
180 struct list_head node; 193 struct list_head node;
181 __u64 start; 194 u64 start;
182 __u64 end; 195 u64 end;
183 __u64 pgoff; 196 u64 pgoff;
184 __u64 (*map_ip)(struct map *, __u64); 197 u64 (*map_ip)(struct map *, u64);
185 struct dso *dso; 198 struct dso *dso;
186}; 199};
187 200
188static __u64 map__map_ip(struct map *map, __u64 ip) 201static u64 map__map_ip(struct map *map, u64 ip)
189{ 202{
190 return ip - map->start + map->pgoff; 203 return ip - map->start + map->pgoff;
191} 204}
192 205
193static __u64 vdso__map_ip(struct map *map, __u64 ip) 206static u64 vdso__map_ip(struct map *map, u64 ip)
194{ 207{
195 return ip; 208 return ip;
196} 209}
@@ -373,7 +386,7 @@ static int thread__fork(struct thread *self, struct thread *parent)
373 return 0; 386 return 0;
374} 387}
375 388
376static struct map *thread__find_map(struct thread *self, __u64 ip) 389static struct map *thread__find_map(struct thread *self, u64 ip)
377{ 390{
378 struct map *pos; 391 struct map *pos;
379 392
@@ -414,7 +427,7 @@ struct hist_entry {
414 struct map *map; 427 struct map *map;
415 struct dso *dso; 428 struct dso *dso;
416 struct symbol *sym; 429 struct symbol *sym;
417 __u64 ip; 430 u64 ip;
418 char level; 431 char level;
419 432
420 uint32_t count; 433 uint32_t count;
@@ -519,7 +532,7 @@ sort__dso_print(FILE *fp, struct hist_entry *self)
519 if (self->dso) 532 if (self->dso)
520 return fprintf(fp, "%-25s", self->dso->name); 533 return fprintf(fp, "%-25s", self->dso->name);
521 534
522 return fprintf(fp, "%016llx ", (__u64)self->ip); 535 return fprintf(fp, "%016llx ", (u64)self->ip);
523} 536}
524 537
525static struct sort_entry sort_dso = { 538static struct sort_entry sort_dso = {
@@ -533,7 +546,7 @@ static struct sort_entry sort_dso = {
533static int64_t 546static int64_t
534sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 547sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
535{ 548{
536 __u64 ip_l, ip_r; 549 u64 ip_l, ip_r;
537 550
538 if (left->sym == right->sym) 551 if (left->sym == right->sym)
539 return 0; 552 return 0;
@@ -550,13 +563,13 @@ sort__sym_print(FILE *fp, struct hist_entry *self)
550 size_t ret = 0; 563 size_t ret = 0;
551 564
552 if (verbose) 565 if (verbose)
553 ret += fprintf(fp, "%#018llx ", (__u64)self->ip); 566 ret += fprintf(fp, "%#018llx ", (u64)self->ip);
554 567
555 if (self->sym) { 568 if (self->sym) {
556 ret += fprintf(fp, "[%c] %s", 569 ret += fprintf(fp, "[%c] %s",
557 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 570 self->dso == kernel_dso ? 'k' : '.', self->sym->name);
558 } else { 571 } else {
559 ret += fprintf(fp, "%#016llx", (__u64)self->ip); 572 ret += fprintf(fp, "%#016llx", (u64)self->ip);
560 } 573 }
561 574
562 return ret; 575 return ret;
@@ -647,7 +660,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
647/* 660/*
648 * collect histogram counts 661 * collect histogram counts
649 */ 662 */
650static void hist_hit(struct hist_entry *he, __u64 ip) 663static void hist_hit(struct hist_entry *he, u64 ip)
651{ 664{
652 unsigned int sym_size, offset; 665 unsigned int sym_size, offset;
653 struct symbol *sym = he->sym; 666 struct symbol *sym = he->sym;
@@ -676,7 +689,7 @@ static void hist_hit(struct hist_entry *he, __u64 ip)
676 689
677static int 690static int
678hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 691hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
679 struct symbol *sym, __u64 ip, char level) 692 struct symbol *sym, u64 ip, char level)
680{ 693{
681 struct rb_node **p = &hist.rb_node; 694 struct rb_node **p = &hist.rb_node;
682 struct rb_node *parent = NULL; 695 struct rb_node *parent = NULL;
@@ -848,7 +861,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
848 int show = 0; 861 int show = 0;
849 struct dso *dso = NULL; 862 struct dso *dso = NULL;
850 struct thread *thread = threads__findnew(event->ip.pid); 863 struct thread *thread = threads__findnew(event->ip.pid);
851 __u64 ip = event->ip.ip; 864 u64 ip = event->ip.ip;
852 struct map *map = NULL; 865 struct map *map = NULL;
853 866
854 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 867 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
@@ -1030,13 +1043,33 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1030 return 0; 1043 return 0;
1031} 1044}
1032 1045
1046static char *get_color(double percent)
1047{
1048 char *color = PERF_COLOR_NORMAL;
1049
1050 /*
1051 * We color high-overhead entries in red, mid-overhead
1052 * entries in green - and keep the low overhead places
1053 * normal:
1054 */
1055 if (percent >= MIN_RED)
1056 color = PERF_COLOR_RED;
1057 else {
1058 if (percent > MIN_GREEN)
1059 color = PERF_COLOR_GREEN;
1060 }
1061 return color;
1062}
1063
1033static int 1064static int
1034parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len) 1065parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1035{ 1066{
1036 char *line = NULL, *tmp, *tmp2; 1067 char *line = NULL, *tmp, *tmp2;
1068 static const char *prev_line;
1069 static const char *prev_color;
1037 unsigned int offset; 1070 unsigned int offset;
1038 size_t line_len; 1071 size_t line_len;
1039 __u64 line_ip; 1072 u64 line_ip;
1040 int ret; 1073 int ret;
1041 char *c; 1074 char *c;
1042 1075
@@ -1073,27 +1106,36 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)
1073 } 1106 }
1074 1107
1075 if (line_ip != -1) { 1108 if (line_ip != -1) {
1109 const char *path = NULL;
1076 unsigned int hits = 0; 1110 unsigned int hits = 0;
1077 double percent = 0.0; 1111 double percent = 0.0;
1078 char *color = PERF_COLOR_NORMAL; 1112 char *color;
1113 struct sym_ext *sym_ext = sym->priv;
1079 1114
1080 offset = line_ip - start; 1115 offset = line_ip - start;
1081 if (offset < len) 1116 if (offset < len)
1082 hits = sym->hist[offset]; 1117 hits = sym->hist[offset];
1083 1118
1084 if (sym->hist_sum) 1119 if (offset < len && sym_ext) {
1120 path = sym_ext[offset].path;
1121 percent = sym_ext[offset].percent;
1122 } else if (sym->hist_sum)
1085 percent = 100.0 * hits / sym->hist_sum; 1123 percent = 100.0 * hits / sym->hist_sum;
1086 1124
1125 color = get_color(percent);
1126
1087 /* 1127 /*
1088 * We color high-overhead entries in red, mid-overhead 1128 * Also color the filename and line if needed, with
1089 * entries in green - and keep the low overhead places 1129 * the same color than the percentage. Don't print it
1090 * normal: 1130 * twice for close colored ip with the same filename:line
1091 */ 1131 */
1092 if (percent >= 5.0) 1132 if (path) {
1093 color = PERF_COLOR_RED; 1133 if (!prev_line || strcmp(prev_line, path)
1094 else { 1134 || color != prev_color) {
1095 if (percent > 0.5) 1135 color_fprintf(stdout, color, " %s", path);
1096 color = PERF_COLOR_GREEN; 1136 prev_line = path;
1137 prev_color = color;
1138 }
1097 } 1139 }
1098 1140
1099 color_fprintf(stdout, color, " %7.2f", percent); 1141 color_fprintf(stdout, color, " %7.2f", percent);
@@ -1109,10 +1151,125 @@ parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len)
1109 return 0; 1151 return 0;
1110} 1152}
1111 1153
1154static struct rb_root root_sym_ext;
1155
1156static void insert_source_line(struct sym_ext *sym_ext)
1157{
1158 struct sym_ext *iter;
1159 struct rb_node **p = &root_sym_ext.rb_node;
1160 struct rb_node *parent = NULL;
1161
1162 while (*p != NULL) {
1163 parent = *p;
1164 iter = rb_entry(parent, struct sym_ext, node);
1165
1166 if (sym_ext->percent > iter->percent)
1167 p = &(*p)->rb_left;
1168 else
1169 p = &(*p)->rb_right;
1170 }
1171
1172 rb_link_node(&sym_ext->node, parent, p);
1173 rb_insert_color(&sym_ext->node, &root_sym_ext);
1174}
1175
1176static void free_source_line(struct symbol *sym, int len)
1177{
1178 struct sym_ext *sym_ext = sym->priv;
1179 int i;
1180
1181 if (!sym_ext)
1182 return;
1183
1184 for (i = 0; i < len; i++)
1185 free(sym_ext[i].path);
1186 free(sym_ext);
1187
1188 sym->priv = NULL;
1189 root_sym_ext = RB_ROOT;
1190}
1191
1192/* Get the filename:line for the colored entries */
1193static void
1194get_source_line(struct symbol *sym, u64 start, int len, char *filename)
1195{
1196 int i;
1197 char cmd[PATH_MAX * 2];
1198 struct sym_ext *sym_ext;
1199
1200 if (!sym->hist_sum)
1201 return;
1202
1203 sym->priv = calloc(len, sizeof(struct sym_ext));
1204 if (!sym->priv)
1205 return;
1206
1207 sym_ext = sym->priv;
1208
1209 for (i = 0; i < len; i++) {
1210 char *path = NULL;
1211 size_t line_len;
1212 u64 offset;
1213 FILE *fp;
1214
1215 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum;
1216 if (sym_ext[i].percent <= 0.5)
1217 continue;
1218
1219 offset = start + i;
1220 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
1221 fp = popen(cmd, "r");
1222 if (!fp)
1223 continue;
1224
1225 if (getline(&path, &line_len, fp) < 0 || !line_len)
1226 goto next;
1227
1228 sym_ext[i].path = malloc(sizeof(char) * line_len + 1);
1229 if (!sym_ext[i].path)
1230 goto next;
1231
1232 strcpy(sym_ext[i].path, path);
1233 insert_source_line(&sym_ext[i]);
1234
1235 next:
1236 pclose(fp);
1237 }
1238}
1239
1240static void print_summary(char *filename)
1241{
1242 struct sym_ext *sym_ext;
1243 struct rb_node *node;
1244
1245 printf("\nSorted summary for file %s\n", filename);
1246 printf("----------------------------------------------\n\n");
1247
1248 if (RB_EMPTY_ROOT(&root_sym_ext)) {
1249 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
1250 return;
1251 }
1252
1253 node = rb_first(&root_sym_ext);
1254 while (node) {
1255 double percent;
1256 char *color;
1257 char *path;
1258
1259 sym_ext = rb_entry(node, struct sym_ext, node);
1260 percent = sym_ext->percent;
1261 color = get_color(percent);
1262 path = sym_ext->path;
1263
1264 color_fprintf(stdout, color, " %7.2f %s", percent, path);
1265 node = rb_next(node);
1266 }
1267}
1268
1112static void annotate_sym(struct dso *dso, struct symbol *sym) 1269static void annotate_sym(struct dso *dso, struct symbol *sym)
1113{ 1270{
1114 char *filename = dso->name; 1271 char *filename = dso->name;
1115 __u64 start, end, len; 1272 u64 start, end, len;
1116 char command[PATH_MAX*2]; 1273 char command[PATH_MAX*2];
1117 FILE *file; 1274 FILE *file;
1118 1275
@@ -1121,13 +1278,6 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1121 if (dso == kernel_dso) 1278 if (dso == kernel_dso)
1122 filename = vmlinux; 1279 filename = vmlinux;
1123 1280
1124 printf("\n------------------------------------------------\n");
1125 printf(" Percent | Source code & Disassembly of %s\n", filename);
1126 printf("------------------------------------------------\n");
1127
1128 if (verbose >= 2)
1129 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1130
1131 start = sym->obj_start; 1281 start = sym->obj_start;
1132 if (!start) 1282 if (!start)
1133 start = sym->start; 1283 start = sym->start;
@@ -1135,7 +1285,19 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1135 end = start + sym->end - sym->start + 1; 1285 end = start + sym->end - sym->start + 1;
1136 len = sym->end - sym->start; 1286 len = sym->end - sym->start;
1137 1287
1138 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (__u64)start, (__u64)end, filename); 1288 if (print_line) {
1289 get_source_line(sym, start, len, filename);
1290 print_summary(filename);
1291 }
1292
1293 printf("\n\n------------------------------------------------\n");
1294 printf(" Percent | Source code & Disassembly of %s\n", filename);
1295 printf("------------------------------------------------\n");
1296
1297 if (verbose >= 2)
1298 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1299
1300 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename);
1139 1301
1140 if (verbose >= 3) 1302 if (verbose >= 3)
1141 printf("doing: %s\n", command); 1303 printf("doing: %s\n", command);
@@ -1150,6 +1312,8 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1150 } 1312 }
1151 1313
1152 pclose(file); 1314 pclose(file);
1315 if (print_line)
1316 free_source_line(sym, len);
1153} 1317}
1154 1318
1155static void find_annotations(void) 1319static void find_annotations(void)
@@ -1308,6 +1472,8 @@ static const struct option options[] = {
1308 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1472 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1309 "dump raw trace in ASCII"), 1473 "dump raw trace in ASCII"),
1310 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1474 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1475 OPT_BOOLEAN('l', "print-line", &print_line,
1476 "print matching source lines (may be slow)"),
1311 OPT_END() 1477 OPT_END()
1312}; 1478};
1313 1479
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0f5771f615da..d7ebbd757543 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -37,33 +37,37 @@ static pid_t target_pid = -1;
37static int inherit = 1; 37static int inherit = 1;
38static int force = 0; 38static int force = 0;
39static int append_file = 0; 39static int append_file = 0;
40static int call_graph = 0;
40static int verbose = 0; 41static int verbose = 0;
41 42
42static long samples; 43static long samples;
43static struct timeval last_read; 44static struct timeval last_read;
44static struct timeval this_read; 45static struct timeval this_read;
45 46
46static __u64 bytes_written; 47static u64 bytes_written;
47 48
48static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; 49static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
49 50
50static int nr_poll; 51static int nr_poll;
51static int nr_cpu; 52static int nr_cpu;
52 53
54static int file_new = 1;
55static struct perf_file_header file_header;
56
53struct mmap_event { 57struct mmap_event {
54 struct perf_event_header header; 58 struct perf_event_header header;
55 __u32 pid; 59 u32 pid;
56 __u32 tid; 60 u32 tid;
57 __u64 start; 61 u64 start;
58 __u64 len; 62 u64 len;
59 __u64 pgoff; 63 u64 pgoff;
60 char filename[PATH_MAX]; 64 char filename[PATH_MAX];
61}; 65};
62 66
63struct comm_event { 67struct comm_event {
64 struct perf_event_header header; 68 struct perf_event_header header;
65 __u32 pid; 69 u32 pid;
66 __u32 tid; 70 u32 tid;
67 char comm[16]; 71 char comm[16];
68}; 72};
69 73
@@ -77,10 +81,10 @@ struct mmap_data {
77 81
78static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; 82static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
79 83
80static unsigned int mmap_read_head(struct mmap_data *md) 84static unsigned long mmap_read_head(struct mmap_data *md)
81{ 85{
82 struct perf_counter_mmap_page *pc = md->base; 86 struct perf_counter_mmap_page *pc = md->base;
83 int head; 87 long head;
84 88
85 head = pc->data_head; 89 head = pc->data_head;
86 rmb(); 90 rmb();
@@ -88,6 +92,32 @@ static unsigned int mmap_read_head(struct mmap_data *md)
88 return head; 92 return head;
89} 93}
90 94
95static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
96{
97 struct perf_counter_mmap_page *pc = md->base;
98
99 /*
100 * ensure all reads are done before we write the tail out.
101 */
102 /* mb(); */
103 pc->data_tail = tail;
104}
105
106static void write_output(void *buf, size_t size)
107{
108 while (size) {
109 int ret = write(output, buf, size);
110
111 if (ret < 0)
112 die("failed to write");
113
114 size -= ret;
115 buf += ret;
116
117 bytes_written += ret;
118 }
119}
120
91static void mmap_read(struct mmap_data *md) 121static void mmap_read(struct mmap_data *md)
92{ 122{
93 unsigned int head = mmap_read_head(md); 123 unsigned int head = mmap_read_head(md);
@@ -108,7 +138,7 @@ static void mmap_read(struct mmap_data *md)
108 * In either case, truncate and restart at head. 138 * In either case, truncate and restart at head.
109 */ 139 */
110 diff = head - old; 140 diff = head - old;
111 if (diff > md->mask / 2 || diff < 0) { 141 if (diff < 0) {
112 struct timeval iv; 142 struct timeval iv;
113 unsigned long msecs; 143 unsigned long msecs;
114 144
@@ -136,36 +166,17 @@ static void mmap_read(struct mmap_data *md)
136 size = md->mask + 1 - (old & md->mask); 166 size = md->mask + 1 - (old & md->mask);
137 old += size; 167 old += size;
138 168
139 while (size) { 169 write_output(buf, size);
140 int ret = write(output, buf, size);
141
142 if (ret < 0)
143 die("failed to write");
144
145 size -= ret;
146 buf += ret;
147
148 bytes_written += ret;
149 }
150 } 170 }
151 171
152 buf = &data[old & md->mask]; 172 buf = &data[old & md->mask];
153 size = head - old; 173 size = head - old;
154 old += size; 174 old += size;
155 175
156 while (size) { 176 write_output(buf, size);
157 int ret = write(output, buf, size);
158
159 if (ret < 0)
160 die("failed to write");
161
162 size -= ret;
163 buf += ret;
164
165 bytes_written += ret;
166 }
167 177
168 md->prev = old; 178 md->prev = old;
179 mmap_write_tail(md, old);
169} 180}
170 181
171static volatile int done = 0; 182static volatile int done = 0;
@@ -191,7 +202,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
191 struct comm_event comm_ev; 202 struct comm_event comm_ev;
192 char filename[PATH_MAX]; 203 char filename[PATH_MAX];
193 char bf[BUFSIZ]; 204 char bf[BUFSIZ];
194 int fd, ret; 205 int fd;
195 size_t size; 206 size_t size;
196 char *field, *sep; 207 char *field, *sep;
197 DIR *tasks; 208 DIR *tasks;
@@ -201,8 +212,12 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
201 212
202 fd = open(filename, O_RDONLY); 213 fd = open(filename, O_RDONLY);
203 if (fd < 0) { 214 if (fd < 0) {
204 fprintf(stderr, "couldn't open %s\n", filename); 215 /*
205 exit(EXIT_FAILURE); 216 * We raced with a task exiting - just return:
217 */
218 if (verbose)
219 fprintf(stderr, "couldn't open %s\n", filename);
220 return;
206 } 221 }
207 if (read(fd, bf, sizeof(bf)) < 0) { 222 if (read(fd, bf, sizeof(bf)) < 0) {
208 fprintf(stderr, "couldn't read %s\n", filename); 223 fprintf(stderr, "couldn't read %s\n", filename);
@@ -223,17 +238,13 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
223 238
224 comm_ev.pid = pid; 239 comm_ev.pid = pid;
225 comm_ev.header.type = PERF_EVENT_COMM; 240 comm_ev.header.type = PERF_EVENT_COMM;
226 size = ALIGN(size, sizeof(__u64)); 241 size = ALIGN(size, sizeof(u64));
227 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); 242 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
228 243
229 if (!full) { 244 if (!full) {
230 comm_ev.tid = pid; 245 comm_ev.tid = pid;
231 246
232 ret = write(output, &comm_ev, comm_ev.header.size); 247 write_output(&comm_ev, comm_ev.header.size);
233 if (ret < 0) {
234 perror("failed to write");
235 exit(-1);
236 }
237 return; 248 return;
238 } 249 }
239 250
@@ -248,11 +259,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
248 259
249 comm_ev.tid = pid; 260 comm_ev.tid = pid;
250 261
251 ret = write(output, &comm_ev, comm_ev.header.size); 262 write_output(&comm_ev, comm_ev.header.size);
252 if (ret < 0) {
253 perror("failed to write");
254 exit(-1);
255 }
256 } 263 }
257 closedir(tasks); 264 closedir(tasks);
258 return; 265 return;
@@ -272,8 +279,12 @@ static void pid_synthesize_mmap_samples(pid_t pid)
272 279
273 fp = fopen(filename, "r"); 280 fp = fopen(filename, "r");
274 if (fp == NULL) { 281 if (fp == NULL) {
275 fprintf(stderr, "couldn't open %s\n", filename); 282 /*
276 exit(EXIT_FAILURE); 283 * We raced with a task exiting - just return:
284 */
285 if (verbose)
286 fprintf(stderr, "couldn't open %s\n", filename);
287 return;
277 } 288 }
278 while (1) { 289 while (1) {
279 char bf[BUFSIZ], *pbf = bf; 290 char bf[BUFSIZ], *pbf = bf;
@@ -304,17 +315,14 @@ static void pid_synthesize_mmap_samples(pid_t pid)
304 size = strlen(execname); 315 size = strlen(execname);
305 execname[size - 1] = '\0'; /* Remove \n */ 316 execname[size - 1] = '\0'; /* Remove \n */
306 memcpy(mmap_ev.filename, execname, size); 317 memcpy(mmap_ev.filename, execname, size);
307 size = ALIGN(size, sizeof(__u64)); 318 size = ALIGN(size, sizeof(u64));
308 mmap_ev.len -= mmap_ev.start; 319 mmap_ev.len -= mmap_ev.start;
309 mmap_ev.header.size = (sizeof(mmap_ev) - 320 mmap_ev.header.size = (sizeof(mmap_ev) -
310 (sizeof(mmap_ev.filename) - size)); 321 (sizeof(mmap_ev.filename) - size));
311 mmap_ev.pid = pid; 322 mmap_ev.pid = pid;
312 mmap_ev.tid = pid; 323 mmap_ev.tid = pid;
313 324
314 if (write(output, &mmap_ev, mmap_ev.header.size) < 0) { 325 write_output(&mmap_ev, mmap_ev.header.size);
315 perror("failed to write");
316 exit(-1);
317 }
318 } 326 }
319 } 327 }
320 328
@@ -351,11 +359,25 @@ static void create_counter(int counter, int cpu, pid_t pid)
351 int track = 1; 359 int track = 1;
352 360
353 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 361 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
362
354 if (freq) { 363 if (freq) {
355 attr->sample_type |= PERF_SAMPLE_PERIOD; 364 attr->sample_type |= PERF_SAMPLE_PERIOD;
356 attr->freq = 1; 365 attr->freq = 1;
357 attr->sample_freq = freq; 366 attr->sample_freq = freq;
358 } 367 }
368
369 if (call_graph)
370 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
371
372 if (file_new) {
373 file_header.sample_type = attr->sample_type;
374 } else {
375 if (file_header.sample_type != attr->sample_type) {
376 fprintf(stderr, "incompatible append\n");
377 exit(-1);
378 }
379 }
380
359 attr->mmap = track; 381 attr->mmap = track;
360 attr->comm = track; 382 attr->comm = track;
361 attr->inherit = (cpu < 0) && inherit; 383 attr->inherit = (cpu < 0) && inherit;
@@ -410,7 +432,7 @@ try_again:
410 mmap_array[nr_cpu][counter].prev = 0; 432 mmap_array[nr_cpu][counter].prev = 0;
411 mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1; 433 mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1;
412 mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size, 434 mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
413 PROT_READ, MAP_SHARED, fd[nr_cpu][counter], 0); 435 PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter], 0);
414 if (mmap_array[nr_cpu][counter].base == MAP_FAILED) { 436 if (mmap_array[nr_cpu][counter].base == MAP_FAILED) {
415 error("failed to mmap with %d (%s)\n", errno, strerror(errno)); 437 error("failed to mmap with %d (%s)\n", errno, strerror(errno));
416 exit(-1); 438 exit(-1);
@@ -435,6 +457,14 @@ static void open_counters(int cpu, pid_t pid)
435 nr_cpu++; 457 nr_cpu++;
436} 458}
437 459
460static void atexit_header(void)
461{
462 file_header.data_size += bytes_written;
463
464 if (pwrite(output, &file_header, sizeof(file_header), 0) == -1)
465 perror("failed to write on file headers");
466}
467
438static int __cmd_record(int argc, const char **argv) 468static int __cmd_record(int argc, const char **argv)
439{ 469{
440 int i, counter; 470 int i, counter;
@@ -448,6 +478,10 @@ static int __cmd_record(int argc, const char **argv)
448 assert(nr_cpus <= MAX_NR_CPUS); 478 assert(nr_cpus <= MAX_NR_CPUS);
449 assert(nr_cpus >= 0); 479 assert(nr_cpus >= 0);
450 480
481 atexit(sig_atexit);
482 signal(SIGCHLD, sig_handler);
483 signal(SIGINT, sig_handler);
484
451 if (!stat(output_name, &st) && !force && !append_file) { 485 if (!stat(output_name, &st) && !force && !append_file) {
452 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", 486 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
453 output_name); 487 output_name);
@@ -456,7 +490,7 @@ static int __cmd_record(int argc, const char **argv)
456 490
457 flags = O_CREAT|O_RDWR; 491 flags = O_CREAT|O_RDWR;
458 if (append_file) 492 if (append_file)
459 flags |= O_APPEND; 493 file_new = 0;
460 else 494 else
461 flags |= O_TRUNC; 495 flags |= O_TRUNC;
462 496
@@ -466,15 +500,22 @@ static int __cmd_record(int argc, const char **argv)
466 exit(-1); 500 exit(-1);
467 } 501 }
468 502
503 if (!file_new) {
504 if (read(output, &file_header, sizeof(file_header)) == -1) {
505 perror("failed to read file headers");
506 exit(-1);
507 }
508
509 lseek(output, file_header.data_size, SEEK_CUR);
510 }
511
512 atexit(atexit_header);
513
469 if (!system_wide) { 514 if (!system_wide) {
470 open_counters(-1, target_pid != -1 ? target_pid : getpid()); 515 open_counters(-1, target_pid != -1 ? target_pid : getpid());
471 } else for (i = 0; i < nr_cpus; i++) 516 } else for (i = 0; i < nr_cpus; i++)
472 open_counters(i, target_pid); 517 open_counters(i, target_pid);
473 518
474 atexit(sig_atexit);
475 signal(SIGCHLD, sig_handler);
476 signal(SIGINT, sig_handler);
477
478 if (target_pid == -1 && argc) { 519 if (target_pid == -1 && argc) {
479 pid = fork(); 520 pid = fork();
480 if (pid < 0) 521 if (pid < 0)
@@ -555,6 +596,8 @@ static const struct option options[] = {
555 "profile at this frequency"), 596 "profile at this frequency"),
556 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 597 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
557 "number of mmap data pages"), 598 "number of mmap data pages"),
599 OPT_BOOLEAN('g', "call-graph", &call_graph,
600 "do call-graph (stack chain/backtrace) recording"),
558 OPT_BOOLEAN('v', "verbose", &verbose, 601 OPT_BOOLEAN('v', "verbose", &verbose,
559 "be more verbose (show counter open errors, etc)"), 602 "be more verbose (show counter open errors, etc)"),
560 OPT_END() 603 OPT_END()
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 82fa93b4db99..5eb5566f0c95 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -36,45 +36,65 @@ static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
36 36
37static int dump_trace = 0; 37static int dump_trace = 0;
38#define dprintf(x...) do { if (dump_trace) printf(x); } while (0) 38#define dprintf(x...) do { if (dump_trace) printf(x); } while (0)
39#define cdprintf(x...) do { if (dump_trace) color_fprintf(stdout, color, x); } while (0)
39 40
40static int verbose; 41static int verbose;
42#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0)
43
41static int full_paths; 44static int full_paths;
42 45
43static unsigned long page_size; 46static unsigned long page_size;
44static unsigned long mmap_window = 32; 47static unsigned long mmap_window = 32;
45 48
49static char default_parent_pattern[] = "^sys_|^do_page_fault";
50static char *parent_pattern = default_parent_pattern;
51static regex_t parent_regex;
52
53static int exclude_other = 1;
54
46struct ip_event { 55struct ip_event {
47 struct perf_event_header header; 56 struct perf_event_header header;
48 __u64 ip; 57 u64 ip;
49 __u32 pid, tid; 58 u32 pid, tid;
50 __u64 period; 59 unsigned char __more_data[];
60};
61
62struct ip_callchain {
63 u64 nr;
64 u64 ips[0];
51}; 65};
52 66
53struct mmap_event { 67struct mmap_event {
54 struct perf_event_header header; 68 struct perf_event_header header;
55 __u32 pid, tid; 69 u32 pid, tid;
56 __u64 start; 70 u64 start;
57 __u64 len; 71 u64 len;
58 __u64 pgoff; 72 u64 pgoff;
59 char filename[PATH_MAX]; 73 char filename[PATH_MAX];
60}; 74};
61 75
62struct comm_event { 76struct comm_event {
63 struct perf_event_header header; 77 struct perf_event_header header;
64 __u32 pid, tid; 78 u32 pid, tid;
65 char comm[16]; 79 char comm[16];
66}; 80};
67 81
68struct fork_event { 82struct fork_event {
69 struct perf_event_header header; 83 struct perf_event_header header;
70 __u32 pid, ppid; 84 u32 pid, ppid;
71}; 85};
72 86
73struct period_event { 87struct period_event {
74 struct perf_event_header header; 88 struct perf_event_header header;
75 __u64 time; 89 u64 time;
76 __u64 id; 90 u64 id;
77 __u64 sample_period; 91 u64 sample_period;
92};
93
94struct lost_event {
95 struct perf_event_header header;
96 u64 id;
97 u64 lost;
78}; 98};
79 99
80typedef union event_union { 100typedef union event_union {
@@ -84,6 +104,7 @@ typedef union event_union {
84 struct comm_event comm; 104 struct comm_event comm;
85 struct fork_event fork; 105 struct fork_event fork;
86 struct period_event period; 106 struct period_event period;
107 struct lost_event lost;
87} event_t; 108} event_t;
88 109
89static LIST_HEAD(dsos); 110static LIST_HEAD(dsos);
@@ -119,15 +140,11 @@ static struct dso *dsos__findnew(const char *name)
119 140
120 nr = dso__load(dso, NULL, verbose); 141 nr = dso__load(dso, NULL, verbose);
121 if (nr < 0) { 142 if (nr < 0) {
122 if (verbose) 143 eprintf("Failed to open: %s\n", name);
123 fprintf(stderr, "Failed to open: %s\n", name);
124 goto out_delete_dso; 144 goto out_delete_dso;
125 } 145 }
126 if (!nr && verbose) { 146 if (!nr)
127 fprintf(stderr, 147 eprintf("No symbols found in: %s, maybe install a debug package?\n", name);
128 "No symbols found in: %s, maybe install a debug package?\n",
129 name);
130 }
131 148
132 dsos__add(dso); 149 dsos__add(dso);
133 150
@@ -146,7 +163,7 @@ static void dsos__fprintf(FILE *fp)
146 dso__fprintf(pos, fp); 163 dso__fprintf(pos, fp);
147} 164}
148 165
149static struct symbol *vdso__find_symbol(struct dso *dso, __u64 ip) 166static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
150{ 167{
151 return dso__find_symbol(kernel_dso, ip); 168 return dso__find_symbol(kernel_dso, ip);
152} 169}
@@ -193,19 +210,19 @@ static int strcommon(const char *pathname)
193 210
194struct map { 211struct map {
195 struct list_head node; 212 struct list_head node;
196 __u64 start; 213 u64 start;
197 __u64 end; 214 u64 end;
198 __u64 pgoff; 215 u64 pgoff;
199 __u64 (*map_ip)(struct map *, __u64); 216 u64 (*map_ip)(struct map *, u64);
200 struct dso *dso; 217 struct dso *dso;
201}; 218};
202 219
203static __u64 map__map_ip(struct map *map, __u64 ip) 220static u64 map__map_ip(struct map *map, u64 ip)
204{ 221{
205 return ip - map->start + map->pgoff; 222 return ip - map->start + map->pgoff;
206} 223}
207 224
208static __u64 vdso__map_ip(struct map *map, __u64 ip) 225static u64 vdso__map_ip(struct map *map, u64 ip)
209{ 226{
210 return ip; 227 return ip;
211} 228}
@@ -412,7 +429,7 @@ static int thread__fork(struct thread *self, struct thread *parent)
412 return 0; 429 return 0;
413} 430}
414 431
415static struct map *thread__find_map(struct thread *self, __u64 ip) 432static struct map *thread__find_map(struct thread *self, u64 ip)
416{ 433{
417 struct map *pos; 434 struct map *pos;
418 435
@@ -453,10 +470,11 @@ struct hist_entry {
453 struct map *map; 470 struct map *map;
454 struct dso *dso; 471 struct dso *dso;
455 struct symbol *sym; 472 struct symbol *sym;
456 __u64 ip; 473 struct symbol *parent;
474 u64 ip;
457 char level; 475 char level;
458 476
459 __u64 count; 477 u64 count;
460}; 478};
461 479
462/* 480/*
@@ -473,6 +491,16 @@ struct sort_entry {
473 size_t (*print)(FILE *fp, struct hist_entry *); 491 size_t (*print)(FILE *fp, struct hist_entry *);
474}; 492};
475 493
494static int64_t cmp_null(void *l, void *r)
495{
496 if (!l && !r)
497 return 0;
498 else if (!l)
499 return -1;
500 else
501 return 1;
502}
503
476/* --sort pid */ 504/* --sort pid */
477 505
478static int64_t 506static int64_t
@@ -507,14 +535,8 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
507 char *comm_l = left->thread->comm; 535 char *comm_l = left->thread->comm;
508 char *comm_r = right->thread->comm; 536 char *comm_r = right->thread->comm;
509 537
510 if (!comm_l || !comm_r) { 538 if (!comm_l || !comm_r)
511 if (!comm_l && !comm_r) 539 return cmp_null(comm_l, comm_r);
512 return 0;
513 else if (!comm_l)
514 return -1;
515 else
516 return 1;
517 }
518 540
519 return strcmp(comm_l, comm_r); 541 return strcmp(comm_l, comm_r);
520} 542}
@@ -540,14 +562,8 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
540 struct dso *dso_l = left->dso; 562 struct dso *dso_l = left->dso;
541 struct dso *dso_r = right->dso; 563 struct dso *dso_r = right->dso;
542 564
543 if (!dso_l || !dso_r) { 565 if (!dso_l || !dso_r)
544 if (!dso_l && !dso_r) 566 return cmp_null(dso_l, dso_r);
545 return 0;
546 else if (!dso_l)
547 return -1;
548 else
549 return 1;
550 }
551 567
552 return strcmp(dso_l->name, dso_r->name); 568 return strcmp(dso_l->name, dso_r->name);
553} 569}
@@ -558,7 +574,7 @@ sort__dso_print(FILE *fp, struct hist_entry *self)
558 if (self->dso) 574 if (self->dso)
559 return fprintf(fp, "%-25s", self->dso->name); 575 return fprintf(fp, "%-25s", self->dso->name);
560 576
561 return fprintf(fp, "%016llx ", (__u64)self->ip); 577 return fprintf(fp, "%016llx ", (u64)self->ip);
562} 578}
563 579
564static struct sort_entry sort_dso = { 580static struct sort_entry sort_dso = {
@@ -572,7 +588,7 @@ static struct sort_entry sort_dso = {
572static int64_t 588static int64_t
573sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 589sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
574{ 590{
575 __u64 ip_l, ip_r; 591 u64 ip_l, ip_r;
576 592
577 if (left->sym == right->sym) 593 if (left->sym == right->sym)
578 return 0; 594 return 0;
@@ -589,13 +605,13 @@ sort__sym_print(FILE *fp, struct hist_entry *self)
589 size_t ret = 0; 605 size_t ret = 0;
590 606
591 if (verbose) 607 if (verbose)
592 ret += fprintf(fp, "%#018llx ", (__u64)self->ip); 608 ret += fprintf(fp, "%#018llx ", (u64)self->ip);
593 609
594 if (self->sym) { 610 if (self->sym) {
595 ret += fprintf(fp, "[%c] %s", 611 ret += fprintf(fp, "[%c] %s",
596 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 612 self->dso == kernel_dso ? 'k' : '.', self->sym->name);
597 } else { 613 } else {
598 ret += fprintf(fp, "%#016llx", (__u64)self->ip); 614 ret += fprintf(fp, "%#016llx", (u64)self->ip);
599 } 615 }
600 616
601 return ret; 617 return ret;
@@ -607,7 +623,38 @@ static struct sort_entry sort_sym = {
607 .print = sort__sym_print, 623 .print = sort__sym_print,
608}; 624};
609 625
626/* --sort parent */
627
628static int64_t
629sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
630{
631 struct symbol *sym_l = left->parent;
632 struct symbol *sym_r = right->parent;
633
634 if (!sym_l || !sym_r)
635 return cmp_null(sym_l, sym_r);
636
637 return strcmp(sym_l->name, sym_r->name);
638}
639
640static size_t
641sort__parent_print(FILE *fp, struct hist_entry *self)
642{
643 size_t ret = 0;
644
645 ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
646
647 return ret;
648}
649
650static struct sort_entry sort_parent = {
651 .header = "Parent symbol ",
652 .cmp = sort__parent_cmp,
653 .print = sort__parent_print,
654};
655
610static int sort__need_collapse = 0; 656static int sort__need_collapse = 0;
657static int sort__has_parent = 0;
611 658
612struct sort_dimension { 659struct sort_dimension {
613 char *name; 660 char *name;
@@ -620,6 +667,7 @@ static struct sort_dimension sort_dimensions[] = {
620 { .name = "comm", .entry = &sort_comm, }, 667 { .name = "comm", .entry = &sort_comm, },
621 { .name = "dso", .entry = &sort_dso, }, 668 { .name = "dso", .entry = &sort_dso, },
622 { .name = "symbol", .entry = &sort_sym, }, 669 { .name = "symbol", .entry = &sort_sym, },
670 { .name = "parent", .entry = &sort_parent, },
623}; 671};
624 672
625static LIST_HEAD(hist_entry__sort_list); 673static LIST_HEAD(hist_entry__sort_list);
@@ -640,6 +688,19 @@ static int sort_dimension__add(char *tok)
640 if (sd->entry->collapse) 688 if (sd->entry->collapse)
641 sort__need_collapse = 1; 689 sort__need_collapse = 1;
642 690
691 if (sd->entry == &sort_parent) {
692 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
693 if (ret) {
694 char err[BUFSIZ];
695
696 regerror(ret, &parent_regex, err, sizeof(err));
697 fprintf(stderr, "Invalid regex: %s\n%s",
698 parent_pattern, err);
699 exit(-1);
700 }
701 sort__has_parent = 1;
702 }
703
643 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 704 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
644 sd->taken = 1; 705 sd->taken = 1;
645 706
@@ -684,11 +745,14 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
684} 745}
685 746
686static size_t 747static size_t
687hist_entry__fprintf(FILE *fp, struct hist_entry *self, __u64 total_samples) 748hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
688{ 749{
689 struct sort_entry *se; 750 struct sort_entry *se;
690 size_t ret; 751 size_t ret;
691 752
753 if (exclude_other && !self->parent)
754 return 0;
755
692 if (total_samples) { 756 if (total_samples) {
693 double percent = self->count * 100.0 / total_samples; 757 double percent = self->count * 100.0 / total_samples;
694 char *color = PERF_COLOR_NORMAL; 758 char *color = PERF_COLOR_NORMAL;
@@ -711,6 +775,9 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, __u64 total_samples)
711 ret = fprintf(fp, "%12Ld ", self->count); 775 ret = fprintf(fp, "%12Ld ", self->count);
712 776
713 list_for_each_entry(se, &hist_entry__sort_list, list) { 777 list_for_each_entry(se, &hist_entry__sort_list, list) {
778 if (exclude_other && (se == &sort_parent))
779 continue;
780
714 fprintf(fp, " "); 781 fprintf(fp, " ");
715 ret += se->print(fp, self); 782 ret += se->print(fp, self);
716 } 783 }
@@ -721,12 +788,72 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, __u64 total_samples)
721} 788}
722 789
723/* 790/*
791 *
792 */
793
794static struct symbol *
795resolve_symbol(struct thread *thread, struct map **mapp,
796 struct dso **dsop, u64 *ipp)
797{
798 struct dso *dso = dsop ? *dsop : NULL;
799 struct map *map = mapp ? *mapp : NULL;
800 uint64_t ip = *ipp;
801
802 if (!thread)
803 return NULL;
804
805 if (dso)
806 goto got_dso;
807
808 if (map)
809 goto got_map;
810
811 map = thread__find_map(thread, ip);
812 if (map != NULL) {
813 if (mapp)
814 *mapp = map;
815got_map:
816 ip = map->map_ip(map, ip);
817 *ipp = ip;
818
819 dso = map->dso;
820 } else {
821 /*
822 * If this is outside of all known maps,
823 * and is a negative address, try to look it
824 * up in the kernel dso, as it might be a
825 * vsyscall (which executes in user-mode):
826 */
827 if ((long long)ip < 0)
828 dso = kernel_dso;
829 }
830 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
831
832 if (dsop)
833 *dsop = dso;
834
835 if (!dso)
836 return NULL;
837got_dso:
838 return dso->find_symbol(dso, ip);
839}
840
841static int call__match(struct symbol *sym)
842{
843 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
844 return 1;
845
846 return 0;
847}
848
849/*
724 * collect histogram counts 850 * collect histogram counts
725 */ 851 */
726 852
727static int 853static int
728hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 854hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
729 struct symbol *sym, __u64 ip, char level, __u64 count) 855 struct symbol *sym, u64 ip, struct ip_callchain *chain,
856 char level, u64 count)
730{ 857{
731 struct rb_node **p = &hist.rb_node; 858 struct rb_node **p = &hist.rb_node;
732 struct rb_node *parent = NULL; 859 struct rb_node *parent = NULL;
@@ -739,9 +866,41 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
739 .ip = ip, 866 .ip = ip,
740 .level = level, 867 .level = level,
741 .count = count, 868 .count = count,
869 .parent = NULL,
742 }; 870 };
743 int cmp; 871 int cmp;
744 872
873 if (sort__has_parent && chain) {
874 u64 context = PERF_CONTEXT_MAX;
875 int i;
876
877 for (i = 0; i < chain->nr; i++) {
878 u64 ip = chain->ips[i];
879 struct dso *dso = NULL;
880 struct symbol *sym;
881
882 if (ip >= PERF_CONTEXT_MAX) {
883 context = ip;
884 continue;
885 }
886
887 switch (context) {
888 case PERF_CONTEXT_KERNEL:
889 dso = kernel_dso;
890 break;
891 default:
892 break;
893 }
894
895 sym = resolve_symbol(thread, NULL, &dso, &ip);
896
897 if (sym && call__match(sym)) {
898 entry.parent = sym;
899 break;
900 }
901 }
902 }
903
745 while (*p != NULL) { 904 while (*p != NULL) {
746 parent = *p; 905 parent = *p;
747 he = rb_entry(parent, struct hist_entry, rb_node); 906 he = rb_entry(parent, struct hist_entry, rb_node);
@@ -873,7 +1032,7 @@ static void output__resort(void)
873 } 1032 }
874} 1033}
875 1034
876static size_t output__fprintf(FILE *fp, __u64 total_samples) 1035static size_t output__fprintf(FILE *fp, u64 total_samples)
877{ 1036{
878 struct hist_entry *pos; 1037 struct hist_entry *pos;
879 struct sort_entry *se; 1038 struct sort_entry *se;
@@ -882,18 +1041,24 @@ static size_t output__fprintf(FILE *fp, __u64 total_samples)
882 1041
883 fprintf(fp, "\n"); 1042 fprintf(fp, "\n");
884 fprintf(fp, "#\n"); 1043 fprintf(fp, "#\n");
885 fprintf(fp, "# (%Ld samples)\n", (__u64)total_samples); 1044 fprintf(fp, "# (%Ld samples)\n", (u64)total_samples);
886 fprintf(fp, "#\n"); 1045 fprintf(fp, "#\n");
887 1046
888 fprintf(fp, "# Overhead"); 1047 fprintf(fp, "# Overhead");
889 list_for_each_entry(se, &hist_entry__sort_list, list) 1048 list_for_each_entry(se, &hist_entry__sort_list, list) {
1049 if (exclude_other && (se == &sort_parent))
1050 continue;
890 fprintf(fp, " %s", se->header); 1051 fprintf(fp, " %s", se->header);
1052 }
891 fprintf(fp, "\n"); 1053 fprintf(fp, "\n");
892 1054
893 fprintf(fp, "# ........"); 1055 fprintf(fp, "# ........");
894 list_for_each_entry(se, &hist_entry__sort_list, list) { 1056 list_for_each_entry(se, &hist_entry__sort_list, list) {
895 int i; 1057 int i;
896 1058
1059 if (exclude_other && (se == &sort_parent))
1060 continue;
1061
897 fprintf(fp, " "); 1062 fprintf(fp, " ");
898 for (i = 0; i < strlen(se->header); i++) 1063 for (i = 0; i < strlen(se->header); i++)
899 fprintf(fp, "."); 1064 fprintf(fp, ".");
@@ -907,7 +1072,8 @@ static size_t output__fprintf(FILE *fp, __u64 total_samples)
907 ret += hist_entry__fprintf(fp, pos, total_samples); 1072 ret += hist_entry__fprintf(fp, pos, total_samples);
908 } 1073 }
909 1074
910 if (!strcmp(sort_order, default_sort_order)) { 1075 if (sort_order == default_sort_order &&
1076 parent_pattern == default_parent_pattern) {
911 fprintf(fp, "#\n"); 1077 fprintf(fp, "#\n");
912 fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n"); 1078 fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n");
913 fprintf(fp, "#\n"); 1079 fprintf(fp, "#\n");
@@ -932,7 +1098,21 @@ static unsigned long total = 0,
932 total_mmap = 0, 1098 total_mmap = 0,
933 total_comm = 0, 1099 total_comm = 0,
934 total_fork = 0, 1100 total_fork = 0,
935 total_unknown = 0; 1101 total_unknown = 0,
1102 total_lost = 0;
1103
1104static int validate_chain(struct ip_callchain *chain, event_t *event)
1105{
1106 unsigned int chain_size;
1107
1108 chain_size = event->header.size;
1109 chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
1110
1111 if (chain->nr*sizeof(u64) > chain_size)
1112 return -1;
1113
1114 return 0;
1115}
936 1116
937static int 1117static int
938process_overflow_event(event_t *event, unsigned long offset, unsigned long head) 1118process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
@@ -941,12 +1121,16 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
941 int show = 0; 1121 int show = 0;
942 struct dso *dso = NULL; 1122 struct dso *dso = NULL;
943 struct thread *thread = threads__findnew(event->ip.pid); 1123 struct thread *thread = threads__findnew(event->ip.pid);
944 __u64 ip = event->ip.ip; 1124 u64 ip = event->ip.ip;
945 __u64 period = 1; 1125 u64 period = 1;
946 struct map *map = NULL; 1126 struct map *map = NULL;
1127 void *more_data = event->ip.__more_data;
1128 struct ip_callchain *chain = NULL;
947 1129
948 if (event->header.type & PERF_SAMPLE_PERIOD) 1130 if (event->header.type & PERF_SAMPLE_PERIOD) {
949 period = event->ip.period; 1131 period = *(u64 *)more_data;
1132 more_data += sizeof(u64);
1133 }
950 1134
951 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n", 1135 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n",
952 (void *)(offset + head), 1136 (void *)(offset + head),
@@ -956,10 +1140,28 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
956 (void *)(long)ip, 1140 (void *)(long)ip,
957 (long long)period); 1141 (long long)period);
958 1142
1143 if (event->header.type & PERF_SAMPLE_CALLCHAIN) {
1144 int i;
1145
1146 chain = (void *)more_data;
1147
1148 dprintf("... chain: nr:%Lu\n", chain->nr);
1149
1150 if (validate_chain(chain, event) < 0) {
1151 eprintf("call-chain problem with event, skipping it.\n");
1152 return 0;
1153 }
1154
1155 if (dump_trace) {
1156 for (i = 0; i < chain->nr; i++)
1157 dprintf("..... %2d: %016Lx\n", i, chain->ips[i]);
1158 }
1159 }
1160
959 dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1161 dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid);
960 1162
961 if (thread == NULL) { 1163 if (thread == NULL) {
962 fprintf(stderr, "problem processing %d event, skipping it.\n", 1164 eprintf("problem processing %d event, skipping it.\n",
963 event->header.type); 1165 event->header.type);
964 return -1; 1166 return -1;
965 } 1167 }
@@ -977,22 +1179,6 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
977 show = SHOW_USER; 1179 show = SHOW_USER;
978 level = '.'; 1180 level = '.';
979 1181
980 map = thread__find_map(thread, ip);
981 if (map != NULL) {
982 ip = map->map_ip(map, ip);
983 dso = map->dso;
984 } else {
985 /*
986 * If this is outside of all known maps,
987 * and is a negative address, try to look it
988 * up in the kernel dso, as it might be a
989 * vsyscall (which executes in user-mode):
990 */
991 if ((long long)ip < 0)
992 dso = kernel_dso;
993 }
994 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
995
996 } else { 1182 } else {
997 show = SHOW_HV; 1183 show = SHOW_HV;
998 level = 'H'; 1184 level = 'H';
@@ -1000,14 +1186,10 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1000 } 1186 }
1001 1187
1002 if (show & show_mask) { 1188 if (show & show_mask) {
1003 struct symbol *sym = NULL; 1189 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
1004
1005 if (dso)
1006 sym = dso->find_symbol(dso, ip);
1007 1190
1008 if (hist_entry__add(thread, map, dso, sym, ip, level, period)) { 1191 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
1009 fprintf(stderr, 1192 eprintf("problem incrementing symbol count, skipping event\n");
1010 "problem incrementing symbol count, skipping event\n");
1011 return -1; 1193 return -1;
1012 } 1194 }
1013 } 1195 }
@@ -1096,8 +1278,60 @@ process_period_event(event_t *event, unsigned long offset, unsigned long head)
1096} 1278}
1097 1279
1098static int 1280static int
1281process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1282{
1283 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
1284 (void *)(offset + head),
1285 (void *)(long)(event->header.size),
1286 event->lost.id,
1287 event->lost.lost);
1288
1289 total_lost += event->lost.lost;
1290
1291 return 0;
1292}
1293
1294static void trace_event(event_t *event)
1295{
1296 unsigned char *raw_event = (void *)event;
1297 char *color = PERF_COLOR_BLUE;
1298 int i, j;
1299
1300 if (!dump_trace)
1301 return;
1302
1303 dprintf(".");
1304 cdprintf("\n. ... raw event: size %d bytes\n", event->header.size);
1305
1306 for (i = 0; i < event->header.size; i++) {
1307 if ((i & 15) == 0) {
1308 dprintf(".");
1309 cdprintf(" %04x: ", i);
1310 }
1311
1312 cdprintf(" %02x", raw_event[i]);
1313
1314 if (((i & 15) == 15) || i == event->header.size-1) {
1315 cdprintf(" ");
1316 for (j = 0; j < 15-(i & 15); j++)
1317 cdprintf(" ");
1318 for (j = 0; j < (i & 15); j++) {
1319 if (isprint(raw_event[i-15+j]))
1320 cdprintf("%c", raw_event[i-15+j]);
1321 else
1322 cdprintf(".");
1323 }
1324 cdprintf("\n");
1325 }
1326 }
1327 dprintf(".\n");
1328}
1329
1330static int
1099process_event(event_t *event, unsigned long offset, unsigned long head) 1331process_event(event_t *event, unsigned long offset, unsigned long head)
1100{ 1332{
1333 trace_event(event);
1334
1101 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) 1335 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
1102 return process_overflow_event(event, offset, head); 1336 return process_overflow_event(event, offset, head);
1103 1337
@@ -1113,6 +1347,10 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1113 1347
1114 case PERF_EVENT_PERIOD: 1348 case PERF_EVENT_PERIOD:
1115 return process_period_event(event, offset, head); 1349 return process_period_event(event, offset, head);
1350
1351 case PERF_EVENT_LOST:
1352 return process_lost_event(event, offset, head);
1353
1116 /* 1354 /*
1117 * We dont process them right now but they are fine: 1355 * We dont process them right now but they are fine:
1118 */ 1356 */
@@ -1128,11 +1366,13 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1128 return 0; 1366 return 0;
1129} 1367}
1130 1368
1369static struct perf_file_header file_header;
1370
1131static int __cmd_report(void) 1371static int __cmd_report(void)
1132{ 1372{
1133 int ret, rc = EXIT_FAILURE; 1373 int ret, rc = EXIT_FAILURE;
1134 unsigned long offset = 0; 1374 unsigned long offset = 0;
1135 unsigned long head = 0; 1375 unsigned long head = sizeof(file_header);
1136 struct stat stat; 1376 struct stat stat;
1137 event_t *event; 1377 event_t *event;
1138 uint32_t size; 1378 uint32_t size;
@@ -1160,6 +1400,17 @@ static int __cmd_report(void)
1160 exit(0); 1400 exit(0);
1161 } 1401 }
1162 1402
1403 if (read(input, &file_header, sizeof(file_header)) == -1) {
1404 perror("failed to read file headers");
1405 exit(-1);
1406 }
1407
1408 if (sort__has_parent &&
1409 !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) {
1410 fprintf(stderr, "selected --sort parent, but no callchain data\n");
1411 exit(-1);
1412 }
1413
1163 if (load_kernel() < 0) { 1414 if (load_kernel() < 0) {
1164 perror("failed to load kernel symbols"); 1415 perror("failed to load kernel symbols");
1165 return EXIT_FAILURE; 1416 return EXIT_FAILURE;
@@ -1204,7 +1455,7 @@ more:
1204 1455
1205 size = event->header.size; 1456 size = event->header.size;
1206 1457
1207 dprintf("%p [%p]: event: %d\n", 1458 dprintf("\n%p [%p]: event: %d\n",
1208 (void *)(offset + head), 1459 (void *)(offset + head),
1209 (void *)(long)event->header.size, 1460 (void *)(long)event->header.size,
1210 event->header.type); 1461 event->header.type);
@@ -1231,9 +1482,13 @@ more:
1231 1482
1232 head += size; 1483 head += size;
1233 1484
1485 if (offset + head >= sizeof(file_header) + file_header.data_size)
1486 goto done;
1487
1234 if (offset + head < stat.st_size) 1488 if (offset + head < stat.st_size)
1235 goto more; 1489 goto more;
1236 1490
1491done:
1237 rc = EXIT_SUCCESS; 1492 rc = EXIT_SUCCESS;
1238 close(input); 1493 close(input);
1239 1494
@@ -1241,6 +1496,7 @@ more:
1241 dprintf(" mmap events: %10ld\n", total_mmap); 1496 dprintf(" mmap events: %10ld\n", total_mmap);
1242 dprintf(" comm events: %10ld\n", total_comm); 1497 dprintf(" comm events: %10ld\n", total_comm);
1243 dprintf(" fork events: %10ld\n", total_fork); 1498 dprintf(" fork events: %10ld\n", total_fork);
1499 dprintf(" lost events: %10ld\n", total_lost);
1244 dprintf(" unknown events: %10ld\n", total_unknown); 1500 dprintf(" unknown events: %10ld\n", total_unknown);
1245 1501
1246 if (dump_trace) 1502 if (dump_trace)
@@ -1273,9 +1529,13 @@ static const struct option options[] = {
1273 "dump raw trace in ASCII"), 1529 "dump raw trace in ASCII"),
1274 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1530 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1275 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1531 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1276 "sort by key(s): pid, comm, dso, symbol. Default: pid,symbol"), 1532 "sort by key(s): pid, comm, dso, symbol, parent"),
1277 OPT_BOOLEAN('P', "full-paths", &full_paths, 1533 OPT_BOOLEAN('P', "full-paths", &full_paths,
1278 "Don't shorten the pathnames taking into account the cwd"), 1534 "Don't shorten the pathnames taking into account the cwd"),
1535 OPT_STRING('p', "parent", &parent_pattern, "regex",
1536 "regex filter to identify parent, see: '--sort parent'"),
1537 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1538 "Only display entries with parent-match"),
1279 OPT_END() 1539 OPT_END()
1280}; 1540};
1281 1541
@@ -1304,6 +1564,11 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1304 1564
1305 setup_sorting(); 1565 setup_sorting();
1306 1566
1567 if (parent_pattern != default_parent_pattern)
1568 sort_dimension__add("parent");
1569 else
1570 exclude_other = 0;
1571
1307 /* 1572 /*
1308 * Any (unrecognized) arguments left? 1573 * Any (unrecognized) arguments left?
1309 */ 1574 */
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c43e4a97dc42..6d3eeac1ea25 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,6 +43,7 @@
43#include "util/parse-events.h" 43#include "util/parse-events.h"
44 44
45#include <sys/prctl.h> 45#include <sys/prctl.h>
46#include <math.h>
46 47
47static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { 48static struct perf_counter_attr default_attrs[MAX_COUNTERS] = {
48 49
@@ -79,12 +80,34 @@ static const unsigned int default_count[] = {
79 10000, 80 10000,
80}; 81};
81 82
82static __u64 event_res[MAX_COUNTERS][3]; 83#define MAX_RUN 100
83static __u64 event_scaled[MAX_COUNTERS];
84 84
85static __u64 runtime_nsecs; 85static int run_count = 1;
86static __u64 walltime_nsecs; 86static int run_idx = 0;
87static __u64 runtime_cycles; 87
88static u64 event_res[MAX_RUN][MAX_COUNTERS][3];
89static u64 event_scaled[MAX_RUN][MAX_COUNTERS];
90
91//static u64 event_hist[MAX_RUN][MAX_COUNTERS][3];
92
93
94static u64 runtime_nsecs[MAX_RUN];
95static u64 walltime_nsecs[MAX_RUN];
96static u64 runtime_cycles[MAX_RUN];
97
98static u64 event_res_avg[MAX_COUNTERS][3];
99static u64 event_res_noise[MAX_COUNTERS][3];
100
101static u64 event_scaled_avg[MAX_COUNTERS];
102
103static u64 runtime_nsecs_avg;
104static u64 runtime_nsecs_noise;
105
106static u64 walltime_nsecs_avg;
107static u64 walltime_nsecs_noise;
108
109static u64 runtime_cycles_avg;
110static u64 runtime_cycles_noise;
88 111
89static void create_perf_stat_counter(int counter) 112static void create_perf_stat_counter(int counter)
90{ 113{
@@ -135,12 +158,12 @@ static inline int nsec_counter(int counter)
135 */ 158 */
136static void read_counter(int counter) 159static void read_counter(int counter)
137{ 160{
138 __u64 *count, single_count[3]; 161 u64 *count, single_count[3];
139 ssize_t res; 162 ssize_t res;
140 int cpu, nv; 163 int cpu, nv;
141 int scaled; 164 int scaled;
142 165
143 count = event_res[counter]; 166 count = event_res[run_idx][counter];
144 167
145 count[0] = count[1] = count[2] = 0; 168 count[0] = count[1] = count[2] = 0;
146 169
@@ -149,8 +172,10 @@ static void read_counter(int counter)
149 if (fd[cpu][counter] < 0) 172 if (fd[cpu][counter] < 0)
150 continue; 173 continue;
151 174
152 res = read(fd[cpu][counter], single_count, nv * sizeof(__u64)); 175 res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
153 assert(res == nv * sizeof(__u64)); 176 assert(res == nv * sizeof(u64));
177 close(fd[cpu][counter]);
178 fd[cpu][counter] = -1;
154 179
155 count[0] += single_count[0]; 180 count[0] += single_count[0];
156 if (scale) { 181 if (scale) {
@@ -162,13 +187,13 @@ static void read_counter(int counter)
162 scaled = 0; 187 scaled = 0;
163 if (scale) { 188 if (scale) {
164 if (count[2] == 0) { 189 if (count[2] == 0) {
165 event_scaled[counter] = -1; 190 event_scaled[run_idx][counter] = -1;
166 count[0] = 0; 191 count[0] = 0;
167 return; 192 return;
168 } 193 }
169 194
170 if (count[2] < count[1]) { 195 if (count[2] < count[1]) {
171 event_scaled[counter] = 1; 196 event_scaled[run_idx][counter] = 1;
172 count[0] = (unsigned long long) 197 count[0] = (unsigned long long)
173 ((double)count[0] * count[1] / count[2] + 0.5); 198 ((double)count[0] * count[1] / count[2] + 0.5);
174 } 199 }
@@ -178,10 +203,94 @@ static void read_counter(int counter)
178 */ 203 */
179 if (attrs[counter].type == PERF_TYPE_SOFTWARE && 204 if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
180 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) 205 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
181 runtime_nsecs = count[0]; 206 runtime_nsecs[run_idx] = count[0];
182 if (attrs[counter].type == PERF_TYPE_HARDWARE && 207 if (attrs[counter].type == PERF_TYPE_HARDWARE &&
183 attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES) 208 attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
184 runtime_cycles = count[0]; 209 runtime_cycles[run_idx] = count[0];
210}
211
212static int run_perf_stat(int argc, const char **argv)
213{
214 unsigned long long t0, t1;
215 int status = 0;
216 int counter;
217 int pid;
218
219 if (!system_wide)
220 nr_cpus = 1;
221
222 for (counter = 0; counter < nr_counters; counter++)
223 create_perf_stat_counter(counter);
224
225 /*
226 * Enable counters and exec the command:
227 */
228 t0 = rdclock();
229 prctl(PR_TASK_PERF_COUNTERS_ENABLE);
230
231 if ((pid = fork()) < 0)
232 perror("failed to fork");
233
234 if (!pid) {
235 if (execvp(argv[0], (char **)argv)) {
236 perror(argv[0]);
237 exit(-1);
238 }
239 }
240
241 wait(&status);
242
243 prctl(PR_TASK_PERF_COUNTERS_DISABLE);
244 t1 = rdclock();
245
246 walltime_nsecs[run_idx] = t1 - t0;
247
248 for (counter = 0; counter < nr_counters; counter++)
249 read_counter(counter);
250
251 return WEXITSTATUS(status);
252}
253
254static void print_noise(u64 *count, u64 *noise)
255{
256 if (run_count > 1)
257 fprintf(stderr, " ( +- %7.3f%% )",
258 (double)noise[0]/(count[0]+1)*100.0);
259}
260
261static void nsec_printout(int counter, u64 *count, u64 *noise)
262{
263 double msecs = (double)count[0] / 1000000;
264
265 fprintf(stderr, " %14.6f %-20s", msecs, event_name(counter));
266
267 if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
268 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
269
270 if (walltime_nsecs_avg)
271 fprintf(stderr, " # %10.3f CPUs ",
272 (double)count[0] / (double)walltime_nsecs_avg);
273 }
274 print_noise(count, noise);
275}
276
277static void abs_printout(int counter, u64 *count, u64 *noise)
278{
279 fprintf(stderr, " %14Ld %-20s", count[0], event_name(counter));
280
281 if (runtime_cycles_avg &&
282 attrs[counter].type == PERF_TYPE_HARDWARE &&
283 attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
284
285 fprintf(stderr, " # %10.3f IPC ",
286 (double)count[0] / (double)runtime_cycles_avg);
287 } else {
288 if (runtime_nsecs_avg) {
289 fprintf(stderr, " # %10.3f M/sec",
290 (double)count[0]/runtime_nsecs_avg*1000.0);
291 }
292 }
293 print_noise(count, noise);
185} 294}
186 295
187/* 296/*
@@ -189,11 +298,12 @@ static void read_counter(int counter)
189 */ 298 */
190static void print_counter(int counter) 299static void print_counter(int counter)
191{ 300{
192 __u64 *count; 301 u64 *count, *noise;
193 int scaled; 302 int scaled;
194 303
195 count = event_res[counter]; 304 count = event_res_avg[counter];
196 scaled = event_scaled[counter]; 305 noise = event_res_noise[counter];
306 scaled = event_scaled_avg[counter];
197 307
198 if (scaled == -1) { 308 if (scaled == -1) {
199 fprintf(stderr, " %14s %-20s\n", 309 fprintf(stderr, " %14s %-20s\n",
@@ -201,75 +311,107 @@ static void print_counter(int counter)
201 return; 311 return;
202 } 312 }
203 313
204 if (nsec_counter(counter)) { 314 if (nsec_counter(counter))
205 double msecs = (double)count[0] / 1000000; 315 nsec_printout(counter, count, noise);
206 316 else
207 fprintf(stderr, " %14.6f %-20s", 317 abs_printout(counter, count, noise);
208 msecs, event_name(counter));
209 if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
210 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
211 318
212 if (walltime_nsecs)
213 fprintf(stderr, " # %11.3f CPU utilization factor",
214 (double)count[0] / (double)walltime_nsecs);
215 }
216 } else {
217 fprintf(stderr, " %14Ld %-20s",
218 count[0], event_name(counter));
219 if (runtime_nsecs)
220 fprintf(stderr, " # %11.3f M/sec",
221 (double)count[0]/runtime_nsecs*1000.0);
222 if (runtime_cycles &&
223 attrs[counter].type == PERF_TYPE_HARDWARE &&
224 attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
225
226 fprintf(stderr, " # %1.3f per cycle",
227 (double)count[0] / (double)runtime_cycles);
228 }
229 }
230 if (scaled) 319 if (scaled)
231 fprintf(stderr, " (scaled from %.2f%%)", 320 fprintf(stderr, " (scaled from %.2f%%)",
232 (double) count[2] / count[1] * 100); 321 (double) count[2] / count[1] * 100);
322
233 fprintf(stderr, "\n"); 323 fprintf(stderr, "\n");
234} 324}
235 325
236static int do_perf_stat(int argc, const char **argv) 326/*
327 * normalize_noise noise values down to stddev:
328 */
329static void normalize_noise(u64 *val)
237{ 330{
238 unsigned long long t0, t1; 331 double res;
239 int counter;
240 int status;
241 int pid;
242 int i;
243 332
244 if (!system_wide) 333 res = (double)*val / (run_count * sqrt((double)run_count));
245 nr_cpus = 1;
246 334
247 for (counter = 0; counter < nr_counters; counter++) 335 *val = (u64)res;
248 create_perf_stat_counter(counter); 336}
249 337
250 /* 338static void update_avg(const char *name, int idx, u64 *avg, u64 *val)
251 * Enable counters and exec the command: 339{
252 */ 340 *avg += *val;
253 t0 = rdclock();
254 prctl(PR_TASK_PERF_COUNTERS_ENABLE);
255 341
256 if ((pid = fork()) < 0) 342 if (verbose > 1)
257 perror("failed to fork"); 343 fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val);
344}
345/*
346 * Calculate the averages and noises:
347 */
348static void calc_avg(void)
349{
350 int i, j;
351
352 if (verbose > 1)
353 fprintf(stderr, "\n");
354
355 for (i = 0; i < run_count; i++) {
356 update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i);
357 update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i);
358 update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i);
359
360 for (j = 0; j < nr_counters; j++) {
361 update_avg("counter/0", j,
362 event_res_avg[j]+0, event_res[i][j]+0);
363 update_avg("counter/1", j,
364 event_res_avg[j]+1, event_res[i][j]+1);
365 update_avg("counter/2", j,
366 event_res_avg[j]+2, event_res[i][j]+2);
367 update_avg("scaled", j,
368 event_scaled_avg + j, event_scaled[i]+j);
369 }
370 }
371 runtime_nsecs_avg /= run_count;
372 walltime_nsecs_avg /= run_count;
373 runtime_cycles_avg /= run_count;
374
375 for (j = 0; j < nr_counters; j++) {
376 event_res_avg[j][0] /= run_count;
377 event_res_avg[j][1] /= run_count;
378 event_res_avg[j][2] /= run_count;
379 }
258 380
259 if (!pid) { 381 for (i = 0; i < run_count; i++) {
260 if (execvp(argv[0], (char **)argv)) { 382 runtime_nsecs_noise +=
261 perror(argv[0]); 383 abs((s64)(runtime_nsecs[i] - runtime_nsecs_avg));
262 exit(-1); 384 walltime_nsecs_noise +=
385 abs((s64)(walltime_nsecs[i] - walltime_nsecs_avg));
386 runtime_cycles_noise +=
387 abs((s64)(runtime_cycles[i] - runtime_cycles_avg));
388
389 for (j = 0; j < nr_counters; j++) {
390 event_res_noise[j][0] +=
391 abs((s64)(event_res[i][j][0] - event_res_avg[j][0]));
392 event_res_noise[j][1] +=
393 abs((s64)(event_res[i][j][1] - event_res_avg[j][1]));
394 event_res_noise[j][2] +=
395 abs((s64)(event_res[i][j][2] - event_res_avg[j][2]));
263 } 396 }
264 } 397 }
265 398
266 while (wait(&status) >= 0) 399 normalize_noise(&runtime_nsecs_noise);
267 ; 400 normalize_noise(&walltime_nsecs_noise);
401 normalize_noise(&runtime_cycles_noise);
268 402
269 prctl(PR_TASK_PERF_COUNTERS_DISABLE); 403 for (j = 0; j < nr_counters; j++) {
270 t1 = rdclock(); 404 normalize_noise(&event_res_noise[j][0]);
405 normalize_noise(&event_res_noise[j][1]);
406 normalize_noise(&event_res_noise[j][2]);
407 }
408}
271 409
272 walltime_nsecs = t1 - t0; 410static void print_stat(int argc, const char **argv)
411{
412 int i, counter;
413
414 calc_avg();
273 415
274 fflush(stdout); 416 fflush(stdout);
275 417
@@ -279,22 +421,19 @@ static int do_perf_stat(int argc, const char **argv)
279 for (i = 1; i < argc; i++) 421 for (i = 1; i < argc; i++)
280 fprintf(stderr, " %s", argv[i]); 422 fprintf(stderr, " %s", argv[i]);
281 423
282 fprintf(stderr, "\':\n"); 424 fprintf(stderr, "\'");
283 fprintf(stderr, "\n"); 425 if (run_count > 1)
284 426 fprintf(stderr, " (%d runs)", run_count);
285 for (counter = 0; counter < nr_counters; counter++) 427 fprintf(stderr, ":\n\n");
286 read_counter(counter);
287 428
288 for (counter = 0; counter < nr_counters; counter++) 429 for (counter = 0; counter < nr_counters; counter++)
289 print_counter(counter); 430 print_counter(counter);
290 431
291 432
292 fprintf(stderr, "\n"); 433 fprintf(stderr, "\n");
293 fprintf(stderr, " Wall-clock time elapsed: %12.6f msecs\n", 434 fprintf(stderr, " %14.9f seconds time elapsed.\n",
294 (double)(t1-t0)/1e6); 435 (double)walltime_nsecs_avg/1e9);
295 fprintf(stderr, "\n"); 436 fprintf(stderr, "\n");
296
297 return 0;
298} 437}
299 438
300static volatile int signr = -1; 439static volatile int signr = -1;
@@ -332,11 +471,15 @@ static const struct option options[] = {
332 "scale/normalize counters"), 471 "scale/normalize counters"),
333 OPT_BOOLEAN('v', "verbose", &verbose, 472 OPT_BOOLEAN('v', "verbose", &verbose,
334 "be more verbose (show counter open errors, etc)"), 473 "be more verbose (show counter open errors, etc)"),
474 OPT_INTEGER('r', "repeat", &run_count,
475 "repeat command and print average + stddev (max: 100)"),
335 OPT_END() 476 OPT_END()
336}; 477};
337 478
338int cmd_stat(int argc, const char **argv, const char *prefix) 479int cmd_stat(int argc, const char **argv, const char *prefix)
339{ 480{
481 int status;
482
340 page_size = sysconf(_SC_PAGE_SIZE); 483 page_size = sysconf(_SC_PAGE_SIZE);
341 484
342 memcpy(attrs, default_attrs, sizeof(attrs)); 485 memcpy(attrs, default_attrs, sizeof(attrs));
@@ -344,6 +487,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix)
344 argc = parse_options(argc, argv, options, stat_usage, 0); 487 argc = parse_options(argc, argv, options, stat_usage, 0);
345 if (!argc) 488 if (!argc)
346 usage_with_options(stat_usage, options); 489 usage_with_options(stat_usage, options);
490 if (run_count <= 0 || run_count > MAX_RUN)
491 usage_with_options(stat_usage, options);
347 492
348 if (!nr_counters) 493 if (!nr_counters)
349 nr_counters = 8; 494 nr_counters = 8;
@@ -363,5 +508,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix)
363 signal(SIGALRM, skip_signal); 508 signal(SIGALRM, skip_signal);
364 signal(SIGABRT, skip_signal); 509 signal(SIGABRT, skip_signal);
365 510
366 return do_perf_stat(argc, argv); 511 status = 0;
512 for (run_idx = 0; run_idx < run_count; run_idx++) {
513 if (run_count != 1 && verbose)
514 fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1);
515 status = run_perf_stat(argc, argv);
516 }
517
518 print_stat(argc, argv);
519
520 return status;
367} 521}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fe338d3c5d7e..5352b5e352ed 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -54,7 +54,7 @@ static int system_wide = 0;
54 54
55static int default_interval = 100000; 55static int default_interval = 100000;
56 56
57static __u64 count_filter = 5; 57static u64 count_filter = 5;
58static int print_entries = 15; 58static int print_entries = 15;
59 59
60static int target_pid = -1; 60static int target_pid = -1;
@@ -79,8 +79,8 @@ static int dump_symtab;
79 * Symbols 79 * Symbols
80 */ 80 */
81 81
82static __u64 min_ip; 82static u64 min_ip;
83static __u64 max_ip = -1ll; 83static u64 max_ip = -1ll;
84 84
85struct sym_entry { 85struct sym_entry {
86 struct rb_node rb_node; 86 struct rb_node rb_node;
@@ -194,7 +194,7 @@ static void print_sym_table(void)
194 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 194 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
195 195
196 if (nr_counters == 1) { 196 if (nr_counters == 1) {
197 printf("%Ld", attrs[0].sample_period); 197 printf("%Ld", (u64)attrs[0].sample_period);
198 if (freq) 198 if (freq)
199 printf("Hz "); 199 printf("Hz ");
200 else 200 else
@@ -372,7 +372,7 @@ out_delete_dso:
372/* 372/*
373 * Binary search in the histogram table and record the hit: 373 * Binary search in the histogram table and record the hit:
374 */ 374 */
375static void record_ip(__u64 ip, int counter) 375static void record_ip(u64 ip, int counter)
376{ 376{
377 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 377 struct symbol *sym = dso__find_symbol(kernel_dso, ip);
378 378
@@ -392,7 +392,7 @@ static void record_ip(__u64 ip, int counter)
392 samples--; 392 samples--;
393} 393}
394 394
395static void process_event(__u64 ip, int counter) 395static void process_event(u64 ip, int counter)
396{ 396{
397 samples++; 397 samples++;
398 398
@@ -463,15 +463,15 @@ static void mmap_read_counter(struct mmap_data *md)
463 for (; old != head;) { 463 for (; old != head;) {
464 struct ip_event { 464 struct ip_event {
465 struct perf_event_header header; 465 struct perf_event_header header;
466 __u64 ip; 466 u64 ip;
467 __u32 pid, target_pid; 467 u32 pid, target_pid;
468 }; 468 };
469 struct mmap_event { 469 struct mmap_event {
470 struct perf_event_header header; 470 struct perf_event_header header;
471 __u32 pid, target_pid; 471 u32 pid, target_pid;
472 __u64 start; 472 u64 start;
473 __u64 len; 473 u64 len;
474 __u64 pgoff; 474 u64 pgoff;
475 char filename[PATH_MAX]; 475 char filename[PATH_MAX];
476 }; 476 };
477 477
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 87a1aca4a424..bccb529dac08 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -19,6 +19,7 @@
19#include <sys/syscall.h> 19#include <sys/syscall.h>
20 20
21#include "../../include/linux/perf_counter.h" 21#include "../../include/linux/perf_counter.h"
22#include "types.h"
22 23
23/* 24/*
24 * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all 25 * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all
@@ -65,4 +66,10 @@ sys_perf_counter_open(struct perf_counter_attr *attr,
65#define MAX_COUNTERS 256 66#define MAX_COUNTERS 256
66#define MAX_NR_CPUS 256 67#define MAX_NR_CPUS 256
67 68
69struct perf_file_header {
70 u64 version;
71 u64 sample_type;
72 u64 data_size;
73};
74
68#endif 75#endif
diff --git a/tools/perf/types.h b/tools/perf/types.h
new file mode 100644
index 000000000000..5e75f9005940
--- /dev/null
+++ b/tools/perf/types.h
@@ -0,0 +1,17 @@
1#ifndef _PERF_TYPES_H
2#define _PERF_TYPES_H
3
4/*
5 * We define u64 as unsigned long long for every architecture
6 * so that we can print it with %Lx without getting warnings.
7 */
8typedef unsigned long long u64;
9typedef signed long long s64;
10typedef unsigned int u32;
11typedef signed int s32;
12typedef unsigned short u16;
13typedef signed short s16;
14typedef unsigned char u8;
15typedef signed char s8;
16
17#endif /* _PERF_TYPES_H */
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index b90ec004f29c..0b791bd346bc 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -11,16 +11,21 @@ enum {
11 D = GIT_DIGIT, 11 D = GIT_DIGIT,
12 G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */ 12 G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */
13 R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */ 13 R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */
14 P = GIT_PRINT_EXTRA, /* printable - alpha - digit - glob - regex */
15
16 PS = GIT_SPACE | GIT_PRINT_EXTRA,
14}; 17};
15 18
16unsigned char sane_ctype[256] = { 19unsigned char sane_ctype[256] = {
20/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
21
17 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */ 22 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */
18 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */ 23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */
19 S, 0, 0, 0, R, 0, 0, 0, R, R, G, R, 0, 0, R, 0, /* 32.. 47 */ 24 PS,P, P, P, R, P, P, P, R, R, G, R, P, P, R, P, /* 32.. 47 */
20 D, D, D, D, D, D, D, D, D, D, 0, 0, 0, 0, 0, G, /* 48.. 63 */ 25 D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G, /* 48.. 63 */
21 0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */ 26 P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */
22 A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, 0, /* 80.. 95 */ 27 A, A, A, A, A, A, A, A, A, A, A, G, G, P, R, P, /* 80.. 95 */
23 0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */ 28 P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */
24 A, A, A, A, A, A, A, A, A, A, A, R, R, 0, 0, 0, /* 112..127 */ 29 A, A, A, A, A, A, A, A, A, A, A, R, R, P, P, 0, /* 112..127 */
25 /* Nothing in the 128.. range */ 30 /* Nothing in the 128.. range */
26}; 31};
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5a72586e1df0..35d04da38d6a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -13,8 +13,8 @@ int nr_counters;
13struct perf_counter_attr attrs[MAX_COUNTERS]; 13struct perf_counter_attr attrs[MAX_COUNTERS];
14 14
15struct event_symbol { 15struct event_symbol {
16 __u8 type; 16 u8 type;
17 __u64 config; 17 u64 config;
18 char *symbol; 18 char *symbol;
19}; 19};
20 20
@@ -63,8 +63,8 @@ static char *hw_event_names[] = {
63}; 63};
64 64
65static char *sw_event_names[] = { 65static char *sw_event_names[] = {
66 "cpu-clock-ticks", 66 "cpu-clock-msecs",
67 "task-clock-ticks", 67 "task-clock-msecs",
68 "page-faults", 68 "page-faults",
69 "context-switches", 69 "context-switches",
70 "CPU-migrations", 70 "CPU-migrations",
@@ -96,7 +96,7 @@ static char *hw_cache_result [][MAX_ALIASES] = {
96 96
97char *event_name(int counter) 97char *event_name(int counter)
98{ 98{
99 __u64 config = attrs[counter].config; 99 u64 config = attrs[counter].config;
100 int type = attrs[counter].type; 100 int type = attrs[counter].type;
101 static char buf[32]; 101 static char buf[32];
102 102
@@ -112,7 +112,7 @@ char *event_name(int counter)
112 return "unknown-hardware"; 112 return "unknown-hardware";
113 113
114 case PERF_TYPE_HW_CACHE: { 114 case PERF_TYPE_HW_CACHE: {
115 __u8 cache_type, cache_op, cache_result; 115 u8 cache_type, cache_op, cache_result;
116 static char name[100]; 116 static char name[100];
117 117
118 cache_type = (config >> 0) & 0xff; 118 cache_type = (config >> 0) & 0xff;
@@ -202,7 +202,7 @@ static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *a
202 */ 202 */
203static int parse_event_symbols(const char *str, struct perf_counter_attr *attr) 203static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
204{ 204{
205 __u64 config, id; 205 u64 config, id;
206 int type; 206 int type;
207 unsigned int i; 207 unsigned int i;
208 const char *sep, *pstr; 208 const char *sep, *pstr;
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index ec33c0c7f4e2..c93eca9a7be3 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -15,7 +15,7 @@ static int hex(char ch)
15 * While we find nice hex chars, build a long_val. 15 * While we find nice hex chars, build a long_val.
16 * Return number of chars processed. 16 * Return number of chars processed.
17 */ 17 */
18int hex2u64(const char *ptr, __u64 *long_val) 18int hex2u64(const char *ptr, u64 *long_val)
19{ 19{
20 const char *p = ptr; 20 const char *p = ptr;
21 *long_val = 0; 21 *long_val = 0;
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index 72812c1c9a7a..37b03255b425 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -1,8 +1,8 @@
1#ifndef _PERF_STRING_H_ 1#ifndef _PERF_STRING_H_
2#define _PERF_STRING_H_ 2#define _PERF_STRING_H_
3 3
4#include <linux/types.h> 4#include "../types.h"
5 5
6int hex2u64(const char *ptr, __u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7 7
8#endif 8#endif
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 49a55f813712..86e14375e74e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -9,9 +9,9 @@
9 9
10const char *sym_hist_filter; 10const char *sym_hist_filter;
11 11
12static struct symbol *symbol__new(__u64 start, __u64 len, 12static struct symbol *symbol__new(u64 start, u64 len,
13 const char *name, unsigned int priv_size, 13 const char *name, unsigned int priv_size,
14 __u64 obj_start, int verbose) 14 u64 obj_start, int verbose)
15{ 15{
16 size_t namelen = strlen(name) + 1; 16 size_t namelen = strlen(name) + 1;
17 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 17 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
@@ -21,14 +21,14 @@ static struct symbol *symbol__new(__u64 start, __u64 len,
21 21
22 if (verbose >= 2) 22 if (verbose >= 2)
23 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 23 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
24 (__u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 24 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start);
25 25
26 self->obj_start= obj_start; 26 self->obj_start= obj_start;
27 self->hist = NULL; 27 self->hist = NULL;
28 self->hist_sum = 0; 28 self->hist_sum = 0;
29 29
30 if (sym_hist_filter && !strcmp(name, sym_hist_filter)) 30 if (sym_hist_filter && !strcmp(name, sym_hist_filter))
31 self->hist = calloc(sizeof(__u64), len); 31 self->hist = calloc(sizeof(u64), len);
32 32
33 if (priv_size) { 33 if (priv_size) {
34 memset(self, 0, priv_size); 34 memset(self, 0, priv_size);
@@ -89,7 +89,7 @@ static void dso__insert_symbol(struct dso *self, struct symbol *sym)
89{ 89{
90 struct rb_node **p = &self->syms.rb_node; 90 struct rb_node **p = &self->syms.rb_node;
91 struct rb_node *parent = NULL; 91 struct rb_node *parent = NULL;
92 const __u64 ip = sym->start; 92 const u64 ip = sym->start;
93 struct symbol *s; 93 struct symbol *s;
94 94
95 while (*p != NULL) { 95 while (*p != NULL) {
@@ -104,7 +104,7 @@ static void dso__insert_symbol(struct dso *self, struct symbol *sym)
104 rb_insert_color(&sym->rb_node, &self->syms); 104 rb_insert_color(&sym->rb_node, &self->syms);
105} 105}
106 106
107struct symbol *dso__find_symbol(struct dso *self, __u64 ip) 107struct symbol *dso__find_symbol(struct dso *self, u64 ip)
108{ 108{
109 struct rb_node *n; 109 struct rb_node *n;
110 110
@@ -151,7 +151,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
151 goto out_failure; 151 goto out_failure;
152 152
153 while (!feof(file)) { 153 while (!feof(file)) {
154 __u64 start; 154 u64 start;
155 struct symbol *sym; 155 struct symbol *sym;
156 int line_len, len; 156 int line_len, len;
157 char symbol_type; 157 char symbol_type;
@@ -232,7 +232,7 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verb
232 goto out_failure; 232 goto out_failure;
233 233
234 while (!feof(file)) { 234 while (!feof(file)) {
235 __u64 start, size; 235 u64 start, size;
236 struct symbol *sym; 236 struct symbol *sym;
237 int line_len, len; 237 int line_len, len;
238 238
@@ -353,7 +353,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
353{ 353{
354 uint32_t nr_rel_entries, idx; 354 uint32_t nr_rel_entries, idx;
355 GElf_Sym sym; 355 GElf_Sym sym;
356 __u64 plt_offset; 356 u64 plt_offset;
357 GElf_Shdr shdr_plt; 357 GElf_Shdr shdr_plt;
358 struct symbol *f; 358 struct symbol *f;
359 GElf_Shdr shdr_rel_plt; 359 GElf_Shdr shdr_rel_plt;
@@ -523,7 +523,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
523 523
524 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 524 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
525 struct symbol *f; 525 struct symbol *f;
526 __u64 obj_start; 526 u64 obj_start;
527 527
528 if (!elf_sym__is_function(&sym)) 528 if (!elf_sym__is_function(&sym))
529 continue; 529 continue;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0d1292bd8270..ea332e56e458 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -2,16 +2,18 @@
2#define _PERF_SYMBOL_ 1 2#define _PERF_SYMBOL_ 1
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include "../types.h"
5#include "list.h" 6#include "list.h"
6#include "rbtree.h" 7#include "rbtree.h"
7 8
8struct symbol { 9struct symbol {
9 struct rb_node rb_node; 10 struct rb_node rb_node;
10 __u64 start; 11 u64 start;
11 __u64 end; 12 u64 end;
12 __u64 obj_start; 13 u64 obj_start;
13 __u64 hist_sum; 14 u64 hist_sum;
14 __u64 *hist; 15 u64 *hist;
16 void *priv;
15 char name[0]; 17 char name[0];
16}; 18};
17 19
@@ -19,7 +21,7 @@ struct dso {
19 struct list_head node; 21 struct list_head node;
20 struct rb_root syms; 22 struct rb_root syms;
21 unsigned int sym_priv_size; 23 unsigned int sym_priv_size;
22 struct symbol *(*find_symbol)(struct dso *, __u64 ip); 24 struct symbol *(*find_symbol)(struct dso *, u64 ip);
23 char name[0]; 25 char name[0];
24}; 26};
25 27
@@ -35,7 +37,7 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
35 return ((void *)sym) - self->sym_priv_size; 37 return ((void *)sym) - self->sym_priv_size;
36} 38}
37 39
38struct symbol *dso__find_symbol(struct dso *self, __u64 ip); 40struct symbol *dso__find_symbol(struct dso *self, u64 ip);
39 41
40int dso__load_kernel(struct dso *self, const char *vmlinux, 42int dso__load_kernel(struct dso *self, const char *vmlinux,
41 symbol_filter_t filter, int verbose); 43 symbol_filter_t filter, int verbose);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 76590a16c271..b8cfed776d81 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -100,11 +100,6 @@
100#include <iconv.h> 100#include <iconv.h>
101#endif 101#endif
102 102
103#ifndef NO_OPENSSL
104#include <openssl/ssl.h>
105#include <openssl/err.h>
106#endif
107
108/* On most systems <limits.h> would have given us this, but 103/* On most systems <limits.h> would have given us this, but
109 * not on some systems (e.g. GNU/Hurd). 104 * not on some systems (e.g. GNU/Hurd).
110 */ 105 */
@@ -332,17 +327,20 @@ static inline int has_extension(const char *filename, const char *ext)
332#undef tolower 327#undef tolower
333#undef toupper 328#undef toupper
334extern unsigned char sane_ctype[256]; 329extern unsigned char sane_ctype[256];
335#define GIT_SPACE 0x01 330#define GIT_SPACE 0x01
336#define GIT_DIGIT 0x02 331#define GIT_DIGIT 0x02
337#define GIT_ALPHA 0x04 332#define GIT_ALPHA 0x04
338#define GIT_GLOB_SPECIAL 0x08 333#define GIT_GLOB_SPECIAL 0x08
339#define GIT_REGEX_SPECIAL 0x10 334#define GIT_REGEX_SPECIAL 0x10
335#define GIT_PRINT_EXTRA 0x20
336#define GIT_PRINT 0x3E
340#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) 337#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
341#define isascii(x) (((x) & ~0x7f) == 0) 338#define isascii(x) (((x) & ~0x7f) == 0)
342#define isspace(x) sane_istest(x,GIT_SPACE) 339#define isspace(x) sane_istest(x,GIT_SPACE)
343#define isdigit(x) sane_istest(x,GIT_DIGIT) 340#define isdigit(x) sane_istest(x,GIT_DIGIT)
344#define isalpha(x) sane_istest(x,GIT_ALPHA) 341#define isalpha(x) sane_istest(x,GIT_ALPHA)
345#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 342#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
343#define isprint(x) sane_istest(x,GIT_PRINT)
346#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL) 344#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
347#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL) 345#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
348#define tolower(x) sane_case((unsigned char)(x), 0x20) 346#define tolower(x) sane_case((unsigned char)(x), 0x20)