aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-11-03 01:10:07 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-11-03 01:10:07 -0500
commit7a53c7f56bbfc9b0ef892e68f5cfae3d902544d1 (patch)
tree19dec256fc80ad06d631ece78b9eb68a457ce66b /tools/perf/util
parente57130698fe3dd2b7d617d90bbf86474473cb40c (diff)
parent012abeea669ea49636cf952d13298bb68654146a (diff)
Merge commit 'v2.6.32-rc5' into for-linus
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/event.h14
-rw-r--r--tools/perf/util/header.c73
-rw-r--r--tools/perf/util/header.h14
-rw-r--r--tools/perf/util/module.c96
-rw-r--r--tools/perf/util/parse-events.c315
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-options.h2
-rw-r--r--tools/perf/util/svghelper.c500
-rw-r--r--tools/perf/util/svghelper.h28
-rw-r--r--tools/perf/util/symbol.c20
-rw-r--r--tools/perf/util/thread.c4
-rw-r--r--tools/perf/util/thread.h9
-rw-r--r--tools/perf/util/trace-event-info.c15
-rw-r--r--tools/perf/util/trace-event-parse.c62
-rw-r--r--tools/perf/util/trace-event-read.c6
-rw-r--r--tools/perf/util/trace-event.h7
16 files changed, 988 insertions, 179 deletions
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index fa2d4e91d329..2c9c26d6ded0 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -1,5 +1,5 @@
1#ifndef __PERF_EVENT_H 1#ifndef __PERF_RECORD_H
2#define __PERF_EVENT_H 2#define __PERF_RECORD_H
3#include "../perf.h" 3#include "../perf.h"
4#include "util.h" 4#include "util.h"
5#include <linux/list.h> 5#include <linux/list.h>
@@ -39,6 +39,7 @@ struct fork_event {
39 struct perf_event_header header; 39 struct perf_event_header header;
40 u32 pid, ppid; 40 u32 pid, ppid;
41 u32 tid, ptid; 41 u32 tid, ptid;
42 u64 time;
42}; 43};
43 44
44struct lost_event { 45struct lost_event {
@@ -52,13 +53,19 @@ struct lost_event {
52 */ 53 */
53struct read_event { 54struct read_event {
54 struct perf_event_header header; 55 struct perf_event_header header;
55 u32 pid,tid; 56 u32 pid, tid;
56 u64 value; 57 u64 value;
57 u64 time_enabled; 58 u64 time_enabled;
58 u64 time_running; 59 u64 time_running;
59 u64 id; 60 u64 id;
60}; 61};
61 62
63struct sample_event{
64 struct perf_event_header header;
65 u64 array[];
66};
67
68
62typedef union event_union { 69typedef union event_union {
63 struct perf_event_header header; 70 struct perf_event_header header;
64 struct ip_event ip; 71 struct ip_event ip;
@@ -67,6 +74,7 @@ typedef union event_union {
67 struct fork_event fork; 74 struct fork_event fork;
68 struct lost_event lost; 75 struct lost_event lost;
69 struct read_event read; 76 struct read_event read;
77 struct sample_event sample;
70} event_t; 78} event_t;
71 79
72struct map { 80struct map {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ec4d4c2f9522..e306857b2c2b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -7,10 +7,9 @@
7#include "header.h" 7#include "header.h"
8 8
9/* 9/*
10 * 10 * Create new perf.data header attribute:
11 */ 11 */
12 12struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr)
13struct perf_header_attr *perf_header_attr__new(struct perf_counter_attr *attr)
14{ 13{
15 struct perf_header_attr *self = malloc(sizeof(*self)); 14 struct perf_header_attr *self = malloc(sizeof(*self));
16 15
@@ -43,9 +42,8 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
43} 42}
44 43
45/* 44/*
46 * 45 * Create new perf.data header:
47 */ 46 */
48
49struct perf_header *perf_header__new(void) 47struct perf_header *perf_header__new(void)
50{ 48{
51 struct perf_header *self = malloc(sizeof(*self)); 49 struct perf_header *self = malloc(sizeof(*self));
@@ -86,6 +84,46 @@ void perf_header__add_attr(struct perf_header *self,
86 self->attr[pos] = attr; 84 self->attr[pos] = attr;
87} 85}
88 86
87#define MAX_EVENT_NAME 64
88
89struct perf_trace_event_type {
90 u64 event_id;
91 char name[MAX_EVENT_NAME];
92};
93
94static int event_count;
95static struct perf_trace_event_type *events;
96
97void perf_header__push_event(u64 id, const char *name)
98{
99 if (strlen(name) > MAX_EVENT_NAME)
100 printf("Event %s will be truncated\n", name);
101
102 if (!events) {
103 events = malloc(sizeof(struct perf_trace_event_type));
104 if (!events)
105 die("nomem");
106 } else {
107 events = realloc(events, (event_count + 1) * sizeof(struct perf_trace_event_type));
108 if (!events)
109 die("nomem");
110 }
111 memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
112 events[event_count].event_id = id;
113 strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
114 event_count++;
115}
116
117char *perf_header__find_event(u64 id)
118{
119 int i;
120 for (i = 0 ; i < event_count; i++) {
121 if (events[i].event_id == id)
122 return events[i].name;
123 }
124 return NULL;
125}
126
89static const char *__perf_magic = "PERFFILE"; 127static const char *__perf_magic = "PERFFILE";
90 128
91#define PERF_MAGIC (*(u64 *)__perf_magic) 129#define PERF_MAGIC (*(u64 *)__perf_magic)
@@ -96,7 +134,7 @@ struct perf_file_section {
96}; 134};
97 135
98struct perf_file_attr { 136struct perf_file_attr {
99 struct perf_counter_attr attr; 137 struct perf_event_attr attr;
100 struct perf_file_section ids; 138 struct perf_file_section ids;
101}; 139};
102 140
@@ -106,6 +144,7 @@ struct perf_file_header {
106 u64 attr_size; 144 u64 attr_size;
107 struct perf_file_section attrs; 145 struct perf_file_section attrs;
108 struct perf_file_section data; 146 struct perf_file_section data;
147 struct perf_file_section event_types;
109}; 148};
110 149
111static void do_write(int fd, void *buf, size_t size) 150static void do_write(int fd, void *buf, size_t size)
@@ -154,6 +193,11 @@ void perf_header__write(struct perf_header *self, int fd)
154 do_write(fd, &f_attr, sizeof(f_attr)); 193 do_write(fd, &f_attr, sizeof(f_attr));
155 } 194 }
156 195
196 self->event_offset = lseek(fd, 0, SEEK_CUR);
197 self->event_size = event_count * sizeof(struct perf_trace_event_type);
198 if (events)
199 do_write(fd, events, self->event_size);
200
157 201
158 self->data_offset = lseek(fd, 0, SEEK_CUR); 202 self->data_offset = lseek(fd, 0, SEEK_CUR);
159 203
@@ -169,6 +213,10 @@ void perf_header__write(struct perf_header *self, int fd)
169 .offset = self->data_offset, 213 .offset = self->data_offset,
170 .size = self->data_size, 214 .size = self->data_size,
171 }, 215 },
216 .event_types = {
217 .offset = self->event_offset,
218 .size = self->event_size,
219 },
172 }; 220 };
173 221
174 lseek(fd, 0, SEEK_SET); 222 lseek(fd, 0, SEEK_SET);
@@ -234,6 +282,17 @@ struct perf_header *perf_header__read(int fd)
234 lseek(fd, tmp, SEEK_SET); 282 lseek(fd, tmp, SEEK_SET);
235 } 283 }
236 284
285 if (f_header.event_types.size) {
286 lseek(fd, f_header.event_types.offset, SEEK_SET);
287 events = malloc(f_header.event_types.size);
288 if (!events)
289 die("nomem");
290 do_read(fd, events, f_header.event_types.size);
291 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
292 }
293 self->event_offset = f_header.event_types.offset;
294 self->event_size = f_header.event_types.size;
295
237 self->data_offset = f_header.data.offset; 296 self->data_offset = f_header.data.offset;
238 self->data_size = f_header.data.size; 297 self->data_size = f_header.data.size;
239 298
@@ -261,7 +320,7 @@ u64 perf_header__sample_type(struct perf_header *header)
261 return type; 320 return type;
262} 321}
263 322
264struct perf_counter_attr * 323struct perf_event_attr *
265perf_header__find_attr(u64 id, struct perf_header *header) 324perf_header__find_attr(u64 id, struct perf_header *header)
266{ 325{
267 int i; 326 int i;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 5d0a72ecc919..a0761bc7863c 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,12 +1,12 @@
1#ifndef _PERF_HEADER_H 1#ifndef _PERF_HEADER_H
2#define _PERF_HEADER_H 2#define _PERF_HEADER_H
3 3
4#include "../../../include/linux/perf_counter.h" 4#include "../../../include/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
6#include "types.h" 6#include "types.h"
7 7
8struct perf_header_attr { 8struct perf_header_attr {
9 struct perf_counter_attr attr; 9 struct perf_event_attr attr;
10 int ids, size; 10 int ids, size;
11 u64 *id; 11 u64 *id;
12 off_t id_offset; 12 off_t id_offset;
@@ -19,6 +19,8 @@ struct perf_header {
19 s64 attr_offset; 19 s64 attr_offset;
20 u64 data_offset; 20 u64 data_offset;
21 u64 data_size; 21 u64 data_size;
22 u64 event_offset;
23 u64 event_size;
22}; 24};
23 25
24struct perf_header *perf_header__read(int fd); 26struct perf_header *perf_header__read(int fd);
@@ -27,12 +29,16 @@ void perf_header__write(struct perf_header *self, int fd);
27void perf_header__add_attr(struct perf_header *self, 29void perf_header__add_attr(struct perf_header *self,
28 struct perf_header_attr *attr); 30 struct perf_header_attr *attr);
29 31
32void perf_header__push_event(u64 id, const char *name);
33char *perf_header__find_event(u64 id);
34
35
30struct perf_header_attr * 36struct perf_header_attr *
31perf_header_attr__new(struct perf_counter_attr *attr); 37perf_header_attr__new(struct perf_event_attr *attr);
32void perf_header_attr__add_id(struct perf_header_attr *self, u64 id); 38void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
33 39
34u64 perf_header__sample_type(struct perf_header *header); 40u64 perf_header__sample_type(struct perf_header *header);
35struct perf_counter_attr * 41struct perf_event_attr *
36perf_header__find_attr(u64 id, struct perf_header *header); 42perf_header__find_attr(u64 id, struct perf_header *header);
37 43
38 44
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
index 3d567fe59c79..0d8c85defcd2 100644
--- a/tools/perf/util/module.c
+++ b/tools/perf/util/module.c
@@ -4,6 +4,7 @@
4#include "module.h" 4#include "module.h"
5 5
6#include <libelf.h> 6#include <libelf.h>
7#include <libgen.h>
7#include <gelf.h> 8#include <gelf.h>
8#include <elf.h> 9#include <elf.h>
9#include <dirent.h> 10#include <dirent.h>
@@ -409,35 +410,40 @@ out_failure:
409static int mod_dso__load_module_paths(struct mod_dso *self) 410static int mod_dso__load_module_paths(struct mod_dso *self)
410{ 411{
411 struct utsname uts; 412 struct utsname uts;
412 int count = 0, len; 413 int count = 0, len, err = -1;
413 char *line = NULL; 414 char *line = NULL;
414 FILE *file; 415 FILE *file;
415 char *path; 416 char *dpath, *dir;
416 size_t n; 417 size_t n;
417 418
418 if (uname(&uts) < 0) 419 if (uname(&uts) < 0)
419 goto out_failure; 420 return err;
420 421
421 len = strlen("/lib/modules/"); 422 len = strlen("/lib/modules/");
422 len += strlen(uts.release); 423 len += strlen(uts.release);
423 len += strlen("/modules.dep"); 424 len += strlen("/modules.dep");
424 425
425 path = calloc(1, len); 426 dpath = calloc(1, len + 1);
426 if (path == NULL) 427 if (dpath == NULL)
427 goto out_failure; 428 return err;
428 429
429 strcat(path, "/lib/modules/"); 430 strcat(dpath, "/lib/modules/");
430 strcat(path, uts.release); 431 strcat(dpath, uts.release);
431 strcat(path, "/modules.dep"); 432 strcat(dpath, "/modules.dep");
432 433
433 file = fopen(path, "r"); 434 file = fopen(dpath, "r");
434 free(path);
435 if (file == NULL) 435 if (file == NULL)
436 goto out_failure; 436 goto out_failure;
437 437
438 dir = dirname(dpath);
439 if (!dir)
440 goto out_failure;
441 strcat(dir, "/");
442
438 while (!feof(file)) { 443 while (!feof(file)) {
439 char *name, *tmp;
440 struct module *module; 444 struct module *module;
445 char *name, *path, *tmp;
446 FILE *modfile;
441 int line_len; 447 int line_len;
442 448
443 line_len = getline(&line, &n, file); 449 line_len = getline(&line, &n, file);
@@ -445,17 +451,41 @@ static int mod_dso__load_module_paths(struct mod_dso *self)
445 break; 451 break;
446 452
447 if (!line) 453 if (!line)
448 goto out_failure; 454 break;
449 455
450 line[--line_len] = '\0'; /* \n */ 456 line[--line_len] = '\0'; /* \n */
451 457
452 path = strtok(line, ":"); 458 path = strchr(line, ':');
459 if (!path)
460 break;
461 *path = '\0';
462
463 path = strdup(line);
453 if (!path) 464 if (!path)
454 goto out_failure; 465 break;
466
467 if (!strstr(path, dir)) {
468 if (strncmp(path, "kernel/", 7))
469 break;
470
471 free(path);
472 path = calloc(1, strlen(dir) + strlen(line) + 1);
473 if (!path)
474 break;
475 strcat(path, dir);
476 strcat(path, line);
477 }
478
479 modfile = fopen(path, "r");
480 if (modfile == NULL)
481 break;
482 fclose(modfile);
455 483
456 name = strdup(path); 484 name = strdup(path);
457 name = strtok(name, "/"); 485 if (!name)
486 break;
458 487
488 name = strtok(name, "/");
459 tmp = name; 489 tmp = name;
460 490
461 while (tmp) { 491 while (tmp) {
@@ -463,26 +493,25 @@ static int mod_dso__load_module_paths(struct mod_dso *self)
463 if (tmp) 493 if (tmp)
464 name = tmp; 494 name = tmp;
465 } 495 }
496
466 name = strsep(&name, "."); 497 name = strsep(&name, ".");
498 if (!name)
499 break;
467 500
468 /* Quirk: replace '-' with '_' in sound modules */ 501 /* Quirk: replace '-' with '_' in all modules */
469 for (len = strlen(name); len; len--) { 502 for (len = strlen(name); len; len--) {
470 if (*(name+len) == '-') 503 if (*(name+len) == '-')
471 *(name+len) = '_'; 504 *(name+len) = '_';
472 } 505 }
473 506
474 module = module__new(name, path); 507 module = module__new(name, path);
475 if (!module) { 508 if (!module)
476 fprintf(stderr, "load_module_paths: allocation error\n"); 509 break;
477 goto out_failure;
478 }
479 mod_dso__insert_module(self, module); 510 mod_dso__insert_module(self, module);
480 511
481 module->sections = sec_dso__new_dso("sections"); 512 module->sections = sec_dso__new_dso("sections");
482 if (!module->sections) { 513 if (!module->sections)
483 fprintf(stderr, "load_module_paths: allocation error\n"); 514 break;
484 goto out_failure;
485 }
486 515
487 module->active = mod_dso__load_sections(module); 516 module->active = mod_dso__load_sections(module);
488 517
@@ -490,13 +519,20 @@ static int mod_dso__load_module_paths(struct mod_dso *self)
490 count++; 519 count++;
491 } 520 }
492 521
493 free(line); 522 if (feof(file))
494 fclose(file); 523 err = count;
495 524 else
496 return count; 525 fprintf(stderr, "load_module_paths: modules.dep parsing failure!\n");
497 526
498out_failure: 527out_failure:
499 return -1; 528 if (dpath)
529 free(dpath);
530 if (file)
531 fclose(file);
532 if (line)
533 free(line);
534
535 return err;
500} 536}
501 537
502int mod_dso__load_modules(struct mod_dso *dso) 538int mod_dso__load_modules(struct mod_dso *dso)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a587d41ae3c9..8cfb48cbbea0 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,10 +6,11 @@
6#include "exec_cmd.h" 6#include "exec_cmd.h"
7#include "string.h" 7#include "string.h"
8#include "cache.h" 8#include "cache.h"
9#include "header.h"
9 10
10int nr_counters; 11int nr_counters;
11 12
12struct perf_counter_attr attrs[MAX_COUNTERS]; 13struct perf_event_attr attrs[MAX_COUNTERS];
13 14
14struct event_symbol { 15struct event_symbol {
15 u8 type; 16 u8 type;
@@ -18,6 +19,12 @@ struct event_symbol {
18 const char *alias; 19 const char *alias;
19}; 20};
20 21
22enum event_result {
23 EVT_FAILED,
24 EVT_HANDLED,
25 EVT_HANDLED_ALL
26};
27
21char debugfs_path[MAXPATHLEN]; 28char debugfs_path[MAXPATHLEN];
22 29
23#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 30#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
@@ -41,13 +48,13 @@ static struct event_symbol event_symbols[] = {
41 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 48 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
42}; 49};
43 50
44#define __PERF_COUNTER_FIELD(config, name) \ 51#define __PERF_EVENT_FIELD(config, name) \
45 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT) 52 ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
46 53
47#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW) 54#define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW)
48#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG) 55#define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG)
49#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE) 56#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
50#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT) 57#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
51 58
52static const char *hw_event_names[] = { 59static const char *hw_event_names[] = {
53 "cycles", 60 "cycles",
@@ -139,7 +146,7 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
139 (strcmp(evt_dirent.d_name, "..")) && \ 146 (strcmp(evt_dirent.d_name, "..")) && \
140 (!tp_event_has_id(&sys_dirent, &evt_dirent))) 147 (!tp_event_has_id(&sys_dirent, &evt_dirent)))
141 148
142#define MAX_EVENT_LENGTH 30 149#define MAX_EVENT_LENGTH 512
143 150
144int valid_debugfs_mount(const char *debugfs) 151int valid_debugfs_mount(const char *debugfs)
145{ 152{
@@ -158,33 +165,31 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
158 DIR *sys_dir, *evt_dir; 165 DIR *sys_dir, *evt_dir;
159 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 166 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
160 char id_buf[4]; 167 char id_buf[4];
161 int sys_dir_fd, fd; 168 int fd;
162 u64 id; 169 u64 id;
163 char evt_path[MAXPATHLEN]; 170 char evt_path[MAXPATHLEN];
171 char dir_path[MAXPATHLEN];
164 172
165 if (valid_debugfs_mount(debugfs_path)) 173 if (valid_debugfs_mount(debugfs_path))
166 return NULL; 174 return NULL;
167 175
168 sys_dir = opendir(debugfs_path); 176 sys_dir = opendir(debugfs_path);
169 if (!sys_dir) 177 if (!sys_dir)
170 goto cleanup; 178 return NULL;
171 sys_dir_fd = dirfd(sys_dir);
172 179
173 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 180 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
174 int dfd = openat(sys_dir_fd, sys_dirent.d_name, 181
175 O_RDONLY|O_DIRECTORY), evt_dir_fd; 182 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
176 if (dfd == -1) 183 sys_dirent.d_name);
177 continue; 184 evt_dir = opendir(dir_path);
178 evt_dir = fdopendir(dfd); 185 if (!evt_dir)
179 if (!evt_dir) {
180 close(dfd);
181 continue; 186 continue;
182 } 187
183 evt_dir_fd = dirfd(evt_dir);
184 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 188 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
185 snprintf(evt_path, MAXPATHLEN, "%s/id", 189
190 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
186 evt_dirent.d_name); 191 evt_dirent.d_name);
187 fd = openat(evt_dir_fd, evt_path, O_RDONLY); 192 fd = open(evt_path, O_RDONLY);
188 if (fd < 0) 193 if (fd < 0)
189 continue; 194 continue;
190 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 195 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
@@ -218,7 +223,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
218 closedir(evt_dir); 223 closedir(evt_dir);
219 } 224 }
220 225
221cleanup:
222 closedir(sys_dir); 226 closedir(sys_dir);
223 return NULL; 227 return NULL;
224} 228}
@@ -344,8 +348,8 @@ static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int
344 return -1; 348 return -1;
345} 349}
346 350
347static int 351static enum event_result
348parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) 352parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
349{ 353{
350 const char *s = *str; 354 const char *s = *str;
351 int cache_type = -1, cache_op = -1, cache_result = -1; 355 int cache_type = -1, cache_op = -1, cache_result = -1;
@@ -356,7 +360,7 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
356 * then bail out: 360 * then bail out:
357 */ 361 */
358 if (cache_type == -1) 362 if (cache_type == -1)
359 return 0; 363 return EVT_FAILED;
360 364
361 while ((cache_op == -1 || cache_result == -1) && *s == '-') { 365 while ((cache_op == -1 || cache_result == -1) && *s == '-') {
362 ++s; 366 ++s;
@@ -402,27 +406,115 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
402 attr->type = PERF_TYPE_HW_CACHE; 406 attr->type = PERF_TYPE_HW_CACHE;
403 407
404 *str = s; 408 *str = s;
405 return 1; 409 return EVT_HANDLED;
410}
411
412static enum event_result
413parse_single_tracepoint_event(char *sys_name,
414 const char *evt_name,
415 unsigned int evt_length,
416 char *flags,
417 struct perf_event_attr *attr,
418 const char **strp)
419{
420 char evt_path[MAXPATHLEN];
421 char id_buf[4];
422 u64 id;
423 int fd;
424
425 if (flags) {
426 if (!strncmp(flags, "record", strlen(flags))) {
427 attr->sample_type |= PERF_SAMPLE_RAW;
428 attr->sample_type |= PERF_SAMPLE_TIME;
429 attr->sample_type |= PERF_SAMPLE_CPU;
430 }
431 }
432
433 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
434 sys_name, evt_name);
435
436 fd = open(evt_path, O_RDONLY);
437 if (fd < 0)
438 return EVT_FAILED;
439
440 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
441 close(fd);
442 return EVT_FAILED;
443 }
444
445 close(fd);
446 id = atoll(id_buf);
447 attr->config = id;
448 attr->type = PERF_TYPE_TRACEPOINT;
449 *strp = evt_name + evt_length;
450
451 return EVT_HANDLED;
452}
453
454/* sys + ':' + event + ':' + flags*/
455#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
456static enum event_result
457parse_subsystem_tracepoint_event(char *sys_name, char *flags)
458{
459 char evt_path[MAXPATHLEN];
460 struct dirent *evt_ent;
461 DIR *evt_dir;
462
463 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
464 evt_dir = opendir(evt_path);
465
466 if (!evt_dir) {
467 perror("Can't open event dir");
468 return EVT_FAILED;
469 }
470
471 while ((evt_ent = readdir(evt_dir))) {
472 char event_opt[MAX_EVOPT_LEN + 1];
473 int len;
474 unsigned int rem = MAX_EVOPT_LEN;
475
476 if (!strcmp(evt_ent->d_name, ".")
477 || !strcmp(evt_ent->d_name, "..")
478 || !strcmp(evt_ent->d_name, "enable")
479 || !strcmp(evt_ent->d_name, "filter"))
480 continue;
481
482 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
483 evt_ent->d_name);
484 if (len < 0)
485 return EVT_FAILED;
486
487 rem -= len;
488 if (flags) {
489 if (rem < strlen(flags) + 1)
490 return EVT_FAILED;
491
492 strcat(event_opt, ":");
493 strcat(event_opt, flags);
494 }
495
496 if (parse_events(NULL, event_opt, 0))
497 return EVT_FAILED;
498 }
499
500 return EVT_HANDLED_ALL;
406} 501}
407 502
408static int parse_tracepoint_event(const char **strp, 503
409 struct perf_counter_attr *attr) 504static enum event_result parse_tracepoint_event(const char **strp,
505 struct perf_event_attr *attr)
410{ 506{
411 const char *evt_name; 507 const char *evt_name;
412 char *flags; 508 char *flags;
413 char sys_name[MAX_EVENT_LENGTH]; 509 char sys_name[MAX_EVENT_LENGTH];
414 char id_buf[4];
415 int fd;
416 unsigned int sys_length, evt_length; 510 unsigned int sys_length, evt_length;
417 u64 id;
418 char evt_path[MAXPATHLEN];
419 511
420 if (valid_debugfs_mount(debugfs_path)) 512 if (valid_debugfs_mount(debugfs_path))
421 return 0; 513 return 0;
422 514
423 evt_name = strchr(*strp, ':'); 515 evt_name = strchr(*strp, ':');
424 if (!evt_name) 516 if (!evt_name)
425 return 0; 517 return EVT_FAILED;
426 518
427 sys_length = evt_name - *strp; 519 sys_length = evt_name - *strp;
428 if (sys_length >= MAX_EVENT_LENGTH) 520 if (sys_length >= MAX_EVENT_LENGTH)
@@ -434,32 +526,22 @@ static int parse_tracepoint_event(const char **strp,
434 526
435 flags = strchr(evt_name, ':'); 527 flags = strchr(evt_name, ':');
436 if (flags) { 528 if (flags) {
437 *flags = '\0'; 529 /* split it out: */
530 evt_name = strndup(evt_name, flags - evt_name);
438 flags++; 531 flags++;
439 if (!strncmp(flags, "record", strlen(flags)))
440 attr->sample_type |= PERF_SAMPLE_RAW;
441 } 532 }
442 533
443 evt_length = strlen(evt_name); 534 evt_length = strlen(evt_name);
444 if (evt_length >= MAX_EVENT_LENGTH) 535 if (evt_length >= MAX_EVENT_LENGTH)
445 return 0; 536 return EVT_FAILED;
446 537
447 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 538 if (!strcmp(evt_name, "*")) {
448 sys_name, evt_name); 539 *strp = evt_name + evt_length;
449 fd = open(evt_path, O_RDONLY); 540 return parse_subsystem_tracepoint_event(sys_name, flags);
450 if (fd < 0) 541 } else
451 return 0; 542 return parse_single_tracepoint_event(sys_name, evt_name,
452 543 evt_length, flags,
453 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 544 attr, strp);
454 close(fd);
455 return 0;
456 }
457 close(fd);
458 id = atoll(id_buf);
459 attr->config = id;
460 attr->type = PERF_TYPE_TRACEPOINT;
461 *strp = evt_name + evt_length;
462 return 1;
463} 545}
464 546
465static int check_events(const char *str, unsigned int i) 547static int check_events(const char *str, unsigned int i)
@@ -477,8 +559,8 @@ static int check_events(const char *str, unsigned int i)
477 return 0; 559 return 0;
478} 560}
479 561
480static int 562static enum event_result
481parse_symbolic_event(const char **strp, struct perf_counter_attr *attr) 563parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
482{ 564{
483 const char *str = *strp; 565 const char *str = *strp;
484 unsigned int i; 566 unsigned int i;
@@ -490,32 +572,33 @@ parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
490 attr->type = event_symbols[i].type; 572 attr->type = event_symbols[i].type;
491 attr->config = event_symbols[i].config; 573 attr->config = event_symbols[i].config;
492 *strp = str + n; 574 *strp = str + n;
493 return 1; 575 return EVT_HANDLED;
494 } 576 }
495 } 577 }
496 return 0; 578 return EVT_FAILED;
497} 579}
498 580
499static int parse_raw_event(const char **strp, struct perf_counter_attr *attr) 581static enum event_result
582parse_raw_event(const char **strp, struct perf_event_attr *attr)
500{ 583{
501 const char *str = *strp; 584 const char *str = *strp;
502 u64 config; 585 u64 config;
503 int n; 586 int n;
504 587
505 if (*str != 'r') 588 if (*str != 'r')
506 return 0; 589 return EVT_FAILED;
507 n = hex2u64(str + 1, &config); 590 n = hex2u64(str + 1, &config);
508 if (n > 0) { 591 if (n > 0) {
509 *strp = str + n + 1; 592 *strp = str + n + 1;
510 attr->type = PERF_TYPE_RAW; 593 attr->type = PERF_TYPE_RAW;
511 attr->config = config; 594 attr->config = config;
512 return 1; 595 return EVT_HANDLED;
513 } 596 }
514 return 0; 597 return EVT_FAILED;
515} 598}
516 599
517static int 600static enum event_result
518parse_numeric_event(const char **strp, struct perf_counter_attr *attr) 601parse_numeric_event(const char **strp, struct perf_event_attr *attr)
519{ 602{
520 const char *str = *strp; 603 const char *str = *strp;
521 char *endp; 604 char *endp;
@@ -530,14 +613,14 @@ parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
530 attr->type = type; 613 attr->type = type;
531 attr->config = config; 614 attr->config = config;
532 *strp = endp; 615 *strp = endp;
533 return 1; 616 return EVT_HANDLED;
534 } 617 }
535 } 618 }
536 return 0; 619 return EVT_FAILED;
537} 620}
538 621
539static int 622static enum event_result
540parse_event_modifier(const char **strp, struct perf_counter_attr *attr) 623parse_event_modifier(const char **strp, struct perf_event_attr *attr)
541{ 624{
542 const char *str = *strp; 625 const char *str = *strp;
543 int eu = 1, ek = 1, eh = 1; 626 int eu = 1, ek = 1, eh = 1;
@@ -569,37 +652,87 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
569 * Each event can have multiple symbolic names. 652 * Each event can have multiple symbolic names.
570 * Symbolic names are (almost) exactly matched. 653 * Symbolic names are (almost) exactly matched.
571 */ 654 */
572static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) 655static enum event_result
656parse_event_symbols(const char **str, struct perf_event_attr *attr)
573{ 657{
574 if (!(parse_tracepoint_event(str, attr) || 658 enum event_result ret;
575 parse_raw_event(str, attr) || 659
576 parse_numeric_event(str, attr) || 660 ret = parse_tracepoint_event(str, attr);
577 parse_symbolic_event(str, attr) || 661 if (ret != EVT_FAILED)
578 parse_generic_hw_event(str, attr))) 662 goto modifier;
579 return 0; 663
664 ret = parse_raw_event(str, attr);
665 if (ret != EVT_FAILED)
666 goto modifier;
580 667
668 ret = parse_numeric_event(str, attr);
669 if (ret != EVT_FAILED)
670 goto modifier;
671
672 ret = parse_symbolic_event(str, attr);
673 if (ret != EVT_FAILED)
674 goto modifier;
675
676 ret = parse_generic_hw_event(str, attr);
677 if (ret != EVT_FAILED)
678 goto modifier;
679
680 return EVT_FAILED;
681
682modifier:
581 parse_event_modifier(str, attr); 683 parse_event_modifier(str, attr);
582 684
583 return 1; 685 return ret;
584} 686}
585 687
688static void store_event_type(const char *orgname)
689{
690 char filename[PATH_MAX], *c;
691 FILE *file;
692 int id;
693
694 sprintf(filename, "%s/", debugfs_path);
695 strncat(filename, orgname, strlen(orgname));
696 strcat(filename, "/id");
697
698 c = strchr(filename, ':');
699 if (c)
700 *c = '/';
701
702 file = fopen(filename, "r");
703 if (!file)
704 return;
705 if (fscanf(file, "%i", &id) < 1)
706 die("cannot store event ID");
707 fclose(file);
708 perf_header__push_event(id, orgname);
709}
710
711
586int parse_events(const struct option *opt __used, const char *str, int unset __used) 712int parse_events(const struct option *opt __used, const char *str, int unset __used)
587{ 713{
588 struct perf_counter_attr attr; 714 struct perf_event_attr attr;
715 enum event_result ret;
716
717 if (strchr(str, ':'))
718 store_event_type(str);
589 719
590 for (;;) { 720 for (;;) {
591 if (nr_counters == MAX_COUNTERS) 721 if (nr_counters == MAX_COUNTERS)
592 return -1; 722 return -1;
593 723
594 memset(&attr, 0, sizeof(attr)); 724 memset(&attr, 0, sizeof(attr));
595 if (!parse_event_symbols(&str, &attr)) 725 ret = parse_event_symbols(&str, &attr);
726 if (ret == EVT_FAILED)
596 return -1; 727 return -1;
597 728
598 if (!(*str == 0 || *str == ',' || isspace(*str))) 729 if (!(*str == 0 || *str == ',' || isspace(*str)))
599 return -1; 730 return -1;
600 731
601 attrs[nr_counters] = attr; 732 if (ret != EVT_HANDLED_ALL) {
602 nr_counters++; 733 attrs[nr_counters] = attr;
734 nr_counters++;
735 }
603 736
604 if (*str == 0) 737 if (*str == 0)
605 break; 738 break;
@@ -628,28 +761,24 @@ static void print_tracepoint_events(void)
628{ 761{
629 DIR *sys_dir, *evt_dir; 762 DIR *sys_dir, *evt_dir;
630 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 763 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
631 int sys_dir_fd;
632 char evt_path[MAXPATHLEN]; 764 char evt_path[MAXPATHLEN];
765 char dir_path[MAXPATHLEN];
633 766
634 if (valid_debugfs_mount(debugfs_path)) 767 if (valid_debugfs_mount(debugfs_path))
635 return; 768 return;
636 769
637 sys_dir = opendir(debugfs_path); 770 sys_dir = opendir(debugfs_path);
638 if (!sys_dir) 771 if (!sys_dir)
639 goto cleanup; 772 return;
640 sys_dir_fd = dirfd(sys_dir);
641 773
642 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 774 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
643 int dfd = openat(sys_dir_fd, sys_dirent.d_name, 775
644 O_RDONLY|O_DIRECTORY), evt_dir_fd; 776 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
645 if (dfd == -1) 777 sys_dirent.d_name);
646 continue; 778 evt_dir = opendir(dir_path);
647 evt_dir = fdopendir(dfd); 779 if (!evt_dir)
648 if (!evt_dir) {
649 close(dfd);
650 continue; 780 continue;
651 } 781
652 evt_dir_fd = dirfd(evt_dir);
653 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 782 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
654 snprintf(evt_path, MAXPATHLEN, "%s:%s", 783 snprintf(evt_path, MAXPATHLEN, "%s:%s",
655 sys_dirent.d_name, evt_dirent.d_name); 784 sys_dirent.d_name, evt_dirent.d_name);
@@ -658,8 +787,6 @@ static void print_tracepoint_events(void)
658 } 787 }
659 closedir(evt_dir); 788 closedir(evt_dir);
660 } 789 }
661
662cleanup:
663 closedir(sys_dir); 790 closedir(sys_dir);
664} 791}
665 792
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 60704c15961f..30c608112845 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -16,7 +16,7 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
16 16
17extern int nr_counters; 17extern int nr_counters;
18 18
19extern struct perf_counter_attr attrs[MAX_COUNTERS]; 19extern struct perf_event_attr attrs[MAX_COUNTERS];
20 20
21extern const char *event_name(int ctr); 21extern const char *event_name(int ctr);
22extern const char *__event_name(int type, u64 config); 22extern const char *__event_name(int type, u64 config);
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 8aa3464c7090..2ee248ff27e5 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -104,6 +104,8 @@ struct option {
104 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } 104 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
105#define OPT_CALLBACK(s, l, v, a, h, f) \ 105#define OPT_CALLBACK(s, l, v, a, h, f) \
106 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) } 106 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) }
107#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
108 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
107#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ 109#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
108 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } 110 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
109 111
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
new file mode 100644
index 000000000000..856655d8b0b8
--- /dev/null
+++ b/tools/perf/util/svghelper.c
@@ -0,0 +1,500 @@
1/*
2 * svghelper.c - helper functions for outputting svg
3 *
4 * (C) Copyright 2009 Intel Corporation
5 *
6 * Authors:
7 * Arjan van de Ven <arjan@linux.intel.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; version 2
12 * of the License.
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <string.h>
19
20#include "svghelper.h"
21
22static u64 first_time, last_time;
23static u64 turbo_frequency, max_freq;
24
25
26#define SLOT_MULT 30.0
27#define SLOT_HEIGHT 25.0
28
29int svg_page_width = 1000;
30
31#define MIN_TEXT_SIZE 0.01
32
33static u64 total_height;
34static FILE *svgfile;
35
36static double cpu2slot(int cpu)
37{
38 return 2 * cpu + 1;
39}
40
41static double cpu2y(int cpu)
42{
43 return cpu2slot(cpu) * SLOT_MULT;
44}
45
46static double time2pixels(u64 time)
47{
48 double X;
49
50 X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time);
51 return X;
52}
53
54/*
55 * Round text sizes so that the svg viewer only needs a discrete
56 * number of renderings of the font
57 */
58static double round_text_size(double size)
59{
60 int loop = 100;
61 double target = 10.0;
62
63 if (size >= 10.0)
64 return size;
65 while (loop--) {
66 if (size >= target)
67 return target;
68 target = target / 2.0;
69 }
70 return size;
71}
72
73void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
74{
75 int new_width;
76
77 svgfile = fopen(filename, "w");
78 if (!svgfile) {
79 fprintf(stderr, "Cannot open %s for output\n", filename);
80 return;
81 }
82 first_time = start;
83 first_time = first_time / 100000000 * 100000000;
84 last_time = end;
85
86 /*
87 * if the recording is short, we default to a width of 1000, but
88 * for longer recordings we want at least 200 units of width per second
89 */
90 new_width = (last_time - first_time) / 5000000;
91
92 if (new_width > svg_page_width)
93 svg_page_width = new_width;
94
95 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
96 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
97 fprintf(svgfile, "<svg width=\"%i\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
98
99 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
100
101 fprintf(svgfile, " rect { stroke-width: 1; }\n");
102 fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n");
103 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
104 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
105 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
106 fprintf(svgfile, " rect.waiting { fill:rgb(214,214, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
107 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
108 fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
109 fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
110 fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n");
111 fprintf(svgfile, " rect.c2 { fill:rgb(255,172,172); fill-opacity:0.5; stroke-width:0; } \n");
112 fprintf(svgfile, " rect.c3 { fill:rgb(255,130,130); fill-opacity:0.5; stroke-width:0; } \n");
113 fprintf(svgfile, " rect.c4 { fill:rgb(255, 88, 88); fill-opacity:0.5; stroke-width:0; } \n");
114 fprintf(svgfile, " rect.c5 { fill:rgb(255, 44, 44); fill-opacity:0.5; stroke-width:0; } \n");
115 fprintf(svgfile, " rect.c6 { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; } \n");
116 fprintf(svgfile, " line.pstate { stroke:rgb(255,255, 0); stroke-opacity:0.8; stroke-width:2; } \n");
117
118 fprintf(svgfile, " ]]>\n </style>\n</defs>\n");
119}
120
121void svg_box(int Yslot, u64 start, u64 end, const char *type)
122{
123 if (!svgfile)
124 return;
125
126 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
127 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
128}
129
130void svg_sample(int Yslot, int cpu, u64 start, u64 end)
131{
132 double text_size;
133 if (!svgfile)
134 return;
135
136 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n",
137 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT);
138
139 text_size = (time2pixels(end)-time2pixels(start));
140 if (cpu > 9)
141 text_size = text_size/2;
142 if (text_size > 1.25)
143 text_size = 1.25;
144 text_size = round_text_size(text_size);
145
146 if (text_size > MIN_TEXT_SIZE)
147 fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
148 time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1);
149
150}
151
152static char *time_to_string(u64 duration)
153{
154 static char text[80];
155
156 text[0] = 0;
157
158 if (duration < 1000) /* less than 1 usec */
159 return text;
160
161 if (duration < 1000 * 1000) { /* less than 1 msec */
162 sprintf(text, "%4.1f us", duration / 1000.0);
163 return text;
164 }
165 sprintf(text, "%4.1f ms", duration / 1000.0 / 1000);
166
167 return text;
168}
169
170void svg_waiting(int Yslot, u64 start, u64 end)
171{
172 char *text;
173 const char *style;
174 double font_size;
175
176 if (!svgfile)
177 return;
178
179 style = "waiting";
180
181 if (end-start > 10 * 1000000) /* 10 msec */
182 style = "WAITING";
183
184 text = time_to_string(end-start);
185
186 font_size = 1.0 * (time2pixels(end)-time2pixels(start));
187
188 if (font_size > 3)
189 font_size = 3;
190
191 font_size = round_text_size(font_size);
192
193 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
194 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
195 time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
196 if (font_size > MIN_TEXT_SIZE)
197 fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%1.8fpt\"> %s</text>\n",
198 font_size, text);
199 fprintf(svgfile, "</g>\n");
200}
201
202static char *cpu_model(void)
203{
204 static char cpu_m[255];
205 char buf[256];
206 FILE *file;
207
208 cpu_m[0] = 0;
209 /* CPU type */
210 file = fopen("/proc/cpuinfo", "r");
211 if (file) {
212 while (fgets(buf, 255, file)) {
213 if (strstr(buf, "model name")) {
214 strncpy(cpu_m, &buf[13], 255);
215 break;
216 }
217 }
218 fclose(file);
219 }
220
221 /* CPU type */
222 file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r");
223 if (file) {
224 while (fgets(buf, 255, file)) {
225 unsigned int freq;
226 freq = strtoull(buf, NULL, 10);
227 if (freq > max_freq)
228 max_freq = freq;
229 }
230 fclose(file);
231 }
232 return cpu_m;
233}
234
235void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
236{
237 char cpu_string[80];
238 if (!svgfile)
239 return;
240
241 max_freq = __max_freq;
242 turbo_frequency = __turbo_freq;
243
244 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n",
245 time2pixels(first_time),
246 time2pixels(last_time)-time2pixels(first_time),
247 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
248
249 sprintf(cpu_string, "CPU %i", (int)cpu+1);
250 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
251 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
252
253 fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
254 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
255}
256
257void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name)
258{
259 double width;
260
261 if (!svgfile)
262 return;
263
264
265 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
266 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
267 time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
268 width = time2pixels(end)-time2pixels(start);
269 if (width > 6)
270 width = 6;
271
272 width = round_text_size(width);
273
274 if (width > MIN_TEXT_SIZE)
275 fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n",
276 width, name);
277
278 fprintf(svgfile, "</g>\n");
279}
280
281void svg_cstate(int cpu, u64 start, u64 end, int type)
282{
283 double width;
284 char style[128];
285
286 if (!svgfile)
287 return;
288
289
290 if (type > 6)
291 type = 6;
292 sprintf(style, "c%i", type);
293
294 fprintf(svgfile, "<rect class=\"%s\" x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\"/>\n",
295 style,
296 time2pixels(start), time2pixels(end)-time2pixels(start),
297 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
298
299 width = (time2pixels(end)-time2pixels(start))/2.0;
300 if (width > 6)
301 width = 6;
302
303 width = round_text_size(width);
304
305 if (width > MIN_TEXT_SIZE)
306 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
307 time2pixels(start), cpu2y(cpu)+width, width, type);
308}
309
310static char *HzToHuman(unsigned long hz)
311{
312 static char buffer[1024];
313 unsigned long long Hz;
314
315 memset(buffer, 0, 1024);
316
317 Hz = hz;
318
319 /* default: just put the Number in */
320 sprintf(buffer, "%9lli", Hz);
321
322 if (Hz > 1000)
323 sprintf(buffer, " %6lli Mhz", (Hz+500)/1000);
324
325 if (Hz > 1500000)
326 sprintf(buffer, " %6.2f Ghz", (Hz+5000.0)/1000000);
327
328 if (Hz == turbo_frequency)
329 sprintf(buffer, "Turbo");
330
331 return buffer;
332}
333
334void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
335{
336 double height = 0;
337
338 if (!svgfile)
339 return;
340
341 if (max_freq)
342 height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT);
343 height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
344 fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n",
345 time2pixels(start), time2pixels(end), height, height);
346 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
347 time2pixels(start), height+0.9, HzToHuman(freq));
348
349}
350
351
352void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2)
353{
354 double height;
355
356 if (!svgfile)
357 return;
358
359
360 if (row1 < row2) {
361 if (row1) {
362 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
363 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
364 if (desc2)
365 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
366 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
367 }
368 if (row2) {
369 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
370 time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
371 if (desc1)
372 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
373 time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
374 }
375 } else {
376 if (row2) {
377 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
378 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
379 if (desc1)
380 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
381 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
382 }
383 if (row1) {
384 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
385 time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
386 if (desc2)
387 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
388 time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
389 }
390 }
391 height = row1 * SLOT_MULT;
392 if (row2 > row1)
393 height += SLOT_HEIGHT;
394 if (row1)
395 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
396 time2pixels(start), height);
397}
398
399void svg_wakeline(u64 start, int row1, int row2)
400{
401 double height;
402
403 if (!svgfile)
404 return;
405
406
407 if (row1 < row2)
408 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
409 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT);
410 else
411 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
412 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT);
413
414 height = row1 * SLOT_MULT;
415 if (row2 > row1)
416 height += SLOT_HEIGHT;
417 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
418 time2pixels(start), height);
419}
420
421void svg_interrupt(u64 start, int row)
422{
423 if (!svgfile)
424 return;
425
426 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
427 time2pixels(start), row * SLOT_MULT);
428 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
429 time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT);
430}
431
432void svg_text(int Yslot, u64 start, const char *text)
433{
434 if (!svgfile)
435 return;
436
437 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
438 time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text);
439}
440
441static void svg_legenda_box(int X, const char *text, const char *style)
442{
443 double boxsize;
444 boxsize = SLOT_HEIGHT / 2;
445
446 fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
447 X, boxsize, boxsize, style);
448 fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n",
449 X + boxsize + 5, boxsize, 0.8 * boxsize, text);
450}
451
452void svg_legenda(void)
453{
454 if (!svgfile)
455 return;
456
457 svg_legenda_box(0, "Running", "sample");
458 svg_legenda_box(100, "Idle","rect.c1");
459 svg_legenda_box(200, "Deeper Idle", "rect.c3");
460 svg_legenda_box(350, "Deepest Idle", "rect.c6");
461 svg_legenda_box(550, "Sleeping", "process2");
462 svg_legenda_box(650, "Waiting for cpu", "waiting");
463 svg_legenda_box(800, "Blocked on IO", "blocked");
464}
465
466void svg_time_grid(void)
467{
468 u64 i;
469
470 if (!svgfile)
471 return;
472
473 i = first_time;
474 while (i < last_time) {
475 int color = 220;
476 double thickness = 0.075;
477 if ((i % 100000000) == 0) {
478 thickness = 0.5;
479 color = 192;
480 }
481 if ((i % 1000000000) == 0) {
482 thickness = 2.0;
483 color = 128;
484 }
485
486 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%llu\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%1.3f\"/>\n",
487 time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness);
488
489 i += 10000000;
490 }
491}
492
493void svg_close(void)
494{
495 if (svgfile) {
496 fprintf(svgfile, "</svg>\n");
497 fclose(svgfile);
498 svgfile = NULL;
499 }
500}
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
new file mode 100644
index 000000000000..cd93195aedb3
--- /dev/null
+++ b/tools/perf/util/svghelper.h
@@ -0,0 +1,28 @@
1#ifndef _INCLUDE_GUARD_SVG_HELPER_
2#define _INCLUDE_GUARD_SVG_HELPER_
3
4#include "types.h"
5
6extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
7extern void svg_box(int Yslot, u64 start, u64 end, const char *type);
8extern void svg_sample(int Yslot, int cpu, u64 start, u64 end);
9extern void svg_waiting(int Yslot, u64 start, u64 end);
10extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);
11
12
13extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name);
14extern void svg_cstate(int cpu, u64 start, u64 end, int type);
15extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq);
16
17
18extern void svg_time_grid(void);
19extern void svg_legenda(void);
20extern void svg_wakeline(u64 start, int row1, int row2);
21extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
22extern void svg_interrupt(u64 start, int row);
23extern void svg_text(int Yslot, u64 start, const char *text);
24extern void svg_close(void);
25
26extern int svg_page_width;
27
28#endif
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index fd3d9c8e90fc..47ea0609a760 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -324,8 +324,7 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
324{ 324{
325 return elf_sym__type(sym) == STT_FUNC && 325 return elf_sym__type(sym) == STT_FUNC &&
326 sym->st_name != 0 && 326 sym->st_name != 0 &&
327 sym->st_shndx != SHN_UNDEF && 327 sym->st_shndx != SHN_UNDEF;
328 sym->st_size != 0;
329} 328}
330 329
331static inline int elf_sym__is_label(const GElf_Sym *sym) 330static inline int elf_sym__is_label(const GElf_Sym *sym)
@@ -833,7 +832,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int v)
833 struct mod_dso *mods = mod_dso__new_dso("modules"); 832 struct mod_dso *mods = mod_dso__new_dso("modules");
834 struct module *pos; 833 struct module *pos;
835 struct rb_node *next; 834 struct rb_node *next;
836 int err; 835 int err, count = 0;
837 836
838 err = mod_dso__load_modules(mods); 837 err = mod_dso__load_modules(mods);
839 838
@@ -852,14 +851,16 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int v)
852 break; 851 break;
853 852
854 next = rb_next(&pos->rb_node); 853 next = rb_next(&pos->rb_node);
854 count += err;
855 } 855 }
856 856
857 if (err < 0) { 857 if (err < 0) {
858 mod_dso__delete_modules(mods); 858 mod_dso__delete_modules(mods);
859 mod_dso__delete_self(mods); 859 mod_dso__delete_self(mods);
860 return err;
860 } 861 }
861 862
862 return err; 863 return count;
863} 864}
864 865
865static inline void dso__fill_symbol_holes(struct dso *self) 866static inline void dso__fill_symbol_holes(struct dso *self)
@@ -913,8 +914,15 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
913 914
914 if (vmlinux) { 915 if (vmlinux) {
915 err = dso__load_vmlinux(self, vmlinux, filter, v); 916 err = dso__load_vmlinux(self, vmlinux, filter, v);
916 if (err > 0 && use_modules) 917 if (err > 0 && use_modules) {
917 err = dso__load_modules(self, filter, v); 918 int syms = dso__load_modules(self, filter, v);
919
920 if (syms < 0) {
921 fprintf(stderr, "dso__load_modules failed!\n");
922 return syms;
923 }
924 err += syms;
925 }
918 } 926 }
919 927
920 if (err <= 0) 928 if (err <= 0)
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 7635928ca278..45efb5db0d19 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -8,7 +8,7 @@
8 8
9static struct thread *thread__new(pid_t pid) 9static struct thread *thread__new(pid_t pid)
10{ 10{
11 struct thread *self = malloc(sizeof(*self)); 11 struct thread *self = calloc(1, sizeof(*self));
12 12
13 if (self != NULL) { 13 if (self != NULL) {
14 self->pid = pid; 14 self->pid = pid;
@@ -85,7 +85,7 @@ register_idle_thread(struct rb_root *threads, struct thread **last_match)
85{ 85{
86 struct thread *thread = threads__findnew(0, threads, last_match); 86 struct thread *thread = threads__findnew(0, threads, last_match);
87 87
88 if (!thread || thread__set_comm(thread, "[init]")) { 88 if (!thread || thread__set_comm(thread, "swapper")) {
89 fprintf(stderr, "problem inserting idle task.\n"); 89 fprintf(stderr, "problem inserting idle task.\n");
90 exit(-1); 90 exit(-1);
91 } 91 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 634f2809a342..32aea3c1c2ad 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -4,10 +4,11 @@
4#include "symbol.h" 4#include "symbol.h"
5 5
6struct thread { 6struct thread {
7 struct rb_node rb_node; 7 struct rb_node rb_node;
8 struct list_head maps; 8 struct list_head maps;
9 pid_t pid; 9 pid_t pid;
10 char *comm; 10 char shortname[3];
11 char *comm;
11}; 12};
12 13
13int thread__set_comm(struct thread *self, const char *comm); 14int thread__set_comm(struct thread *self, const char *comm);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 6c9302a7274c..af4b0573b37f 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -458,7 +458,7 @@ static void read_proc_kallsyms(void)
458static void read_ftrace_printk(void) 458static void read_ftrace_printk(void)
459{ 459{
460 unsigned int size, check_size; 460 unsigned int size, check_size;
461 const char *path; 461 char *path;
462 struct stat st; 462 struct stat st;
463 int ret; 463 int ret;
464 464
@@ -468,23 +468,24 @@ static void read_ftrace_printk(void)
468 /* not found */ 468 /* not found */
469 size = 0; 469 size = 0;
470 write_or_die(&size, 4); 470 write_or_die(&size, 4);
471 return; 471 goto out;
472 } 472 }
473 size = get_size(path); 473 size = get_size(path);
474 write_or_die(&size, 4); 474 write_or_die(&size, 4);
475 check_size = copy_file(path); 475 check_size = copy_file(path);
476 if (size != check_size) 476 if (size != check_size)
477 die("error in size of file '%s'", path); 477 die("error in size of file '%s'", path);
478 478out:
479 put_tracing_file(path);
479} 480}
480 481
481static struct tracepoint_path * 482static struct tracepoint_path *
482get_tracepoints_path(struct perf_counter_attr *pattrs, int nb_counters) 483get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
483{ 484{
484 struct tracepoint_path path, *ppath = &path; 485 struct tracepoint_path path, *ppath = &path;
485 int i; 486 int i;
486 487
487 for (i = 0; i < nb_counters; i++) { 488 for (i = 0; i < nb_events; i++) {
488 if (pattrs[i].type != PERF_TYPE_TRACEPOINT) 489 if (pattrs[i].type != PERF_TYPE_TRACEPOINT)
489 continue; 490 continue;
490 ppath->next = tracepoint_id_to_path(pattrs[i].config); 491 ppath->next = tracepoint_id_to_path(pattrs[i].config);
@@ -495,7 +496,7 @@ get_tracepoints_path(struct perf_counter_attr *pattrs, int nb_counters)
495 496
496 return path.next; 497 return path.next;
497} 498}
498void read_tracing_data(struct perf_counter_attr *pattrs, int nb_counters) 499void read_tracing_data(struct perf_event_attr *pattrs, int nb_events)
499{ 500{
500 char buf[BUFSIZ]; 501 char buf[BUFSIZ];
501 struct tracepoint_path *tps; 502 struct tracepoint_path *tps;
@@ -529,7 +530,7 @@ void read_tracing_data(struct perf_counter_attr *pattrs, int nb_counters)
529 page_size = getpagesize(); 530 page_size = getpagesize();
530 write_or_die(&page_size, 4); 531 write_or_die(&page_size, 4);
531 532
532 tps = get_tracepoints_path(pattrs, nb_counters); 533 tps = get_tracepoints_path(pattrs, nb_events);
533 534
534 read_header_files(); 535 read_header_files();
535 read_ftrace_files(tps); 536 read_ftrace_files(tps);
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 629e602d9405..55c9659a56e2 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -618,7 +618,7 @@ static int test_type(enum event_type type, enum event_type expect)
618} 618}
619 619
620static int test_type_token(enum event_type type, char *token, 620static int test_type_token(enum event_type type, char *token,
621 enum event_type expect, char *expect_tok) 621 enum event_type expect, const char *expect_tok)
622{ 622{
623 if (type != expect) { 623 if (type != expect) {
624 die("Error: expected type %d but read %d", 624 die("Error: expected type %d but read %d",
@@ -650,7 +650,7 @@ static int read_expect_type(enum event_type expect, char **tok)
650 return __read_expect_type(expect, tok, 1); 650 return __read_expect_type(expect, tok, 1);
651} 651}
652 652
653static int __read_expected(enum event_type expect, char *str, int newline_ok) 653static int __read_expected(enum event_type expect, const char *str, int newline_ok)
654{ 654{
655 enum event_type type; 655 enum event_type type;
656 char *token; 656 char *token;
@@ -668,12 +668,12 @@ static int __read_expected(enum event_type expect, char *str, int newline_ok)
668 return 0; 668 return 0;
669} 669}
670 670
671static int read_expected(enum event_type expect, char *str) 671static int read_expected(enum event_type expect, const char *str)
672{ 672{
673 return __read_expected(expect, str, 1); 673 return __read_expected(expect, str, 1);
674} 674}
675 675
676static int read_expected_item(enum event_type expect, char *str) 676static int read_expected_item(enum event_type expect, const char *str)
677{ 677{
678 return __read_expected(expect, str, 0); 678 return __read_expected(expect, str, 0);
679} 679}
@@ -1776,6 +1776,29 @@ static unsigned long long read_size(void *ptr, int size)
1776 } 1776 }
1777} 1777}
1778 1778
1779unsigned long long
1780raw_field_value(struct event *event, const char *name, void *data)
1781{
1782 struct format_field *field;
1783
1784 field = find_any_field(event, name);
1785 if (!field)
1786 return 0ULL;
1787
1788 return read_size(data + field->offset, field->size);
1789}
1790
1791void *raw_field_ptr(struct event *event, const char *name, void *data)
1792{
1793 struct format_field *field;
1794
1795 field = find_any_field(event, name);
1796 if (!field)
1797 return NULL;
1798
1799 return data + field->offset;
1800}
1801
1779static int get_common_info(const char *type, int *offset, int *size) 1802static int get_common_info(const char *type, int *offset, int *size)
1780{ 1803{
1781 struct event *event; 1804 struct event *event;
@@ -1799,7 +1822,7 @@ static int get_common_info(const char *type, int *offset, int *size)
1799 return 0; 1822 return 0;
1800} 1823}
1801 1824
1802static int parse_common_type(void *data) 1825int trace_parse_common_type(void *data)
1803{ 1826{
1804 static int type_offset; 1827 static int type_offset;
1805 static int type_size; 1828 static int type_size;
@@ -1832,7 +1855,7 @@ static int parse_common_pid(void *data)
1832 return read_size(data + pid_offset, pid_size); 1855 return read_size(data + pid_offset, pid_size);
1833} 1856}
1834 1857
1835static struct event *find_event(int id) 1858struct event *trace_find_event(int id)
1836{ 1859{
1837 struct event *event; 1860 struct event *event;
1838 1861
@@ -1945,10 +1968,11 @@ static const struct flag flags[] = {
1945 { "NET_TX_SOFTIRQ", 2 }, 1968 { "NET_TX_SOFTIRQ", 2 },
1946 { "NET_RX_SOFTIRQ", 3 }, 1969 { "NET_RX_SOFTIRQ", 3 },
1947 { "BLOCK_SOFTIRQ", 4 }, 1970 { "BLOCK_SOFTIRQ", 4 },
1948 { "TASKLET_SOFTIRQ", 5 }, 1971 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
1949 { "SCHED_SOFTIRQ", 6 }, 1972 { "TASKLET_SOFTIRQ", 6 },
1950 { "HRTIMER_SOFTIRQ", 7 }, 1973 { "SCHED_SOFTIRQ", 7 },
1951 { "RCU_SOFTIRQ", 8 }, 1974 { "HRTIMER_SOFTIRQ", 8 },
1975 { "RCU_SOFTIRQ", 9 },
1952 1976
1953 { "HRTIMER_NORESTART", 0 }, 1977 { "HRTIMER_NORESTART", 0 },
1954 { "HRTIMER_RESTART", 1 }, 1978 { "HRTIMER_RESTART", 1 },
@@ -2420,8 +2444,8 @@ get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2420 int type; 2444 int type;
2421 int pid; 2445 int pid;
2422 2446
2423 type = parse_common_type(next->data); 2447 type = trace_parse_common_type(next->data);
2424 event = find_event(type); 2448 event = trace_find_event(type);
2425 if (!event) 2449 if (!event)
2426 return NULL; 2450 return NULL;
2427 2451
@@ -2502,8 +2526,8 @@ print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec)
2502 int type; 2526 int type;
2503 int i; 2527 int i;
2504 2528
2505 type = parse_common_type(ret_rec->data); 2529 type = trace_parse_common_type(ret_rec->data);
2506 ret_event = find_event(type); 2530 ret_event = trace_find_event(type);
2507 2531
2508 field = find_field(ret_event, "rettime"); 2532 field = find_field(ret_event, "rettime");
2509 if (!field) 2533 if (!field)
@@ -2696,11 +2720,13 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2696 nsecs -= secs * NSECS_PER_SEC; 2720 nsecs -= secs * NSECS_PER_SEC;
2697 usecs = nsecs / NSECS_PER_USEC; 2721 usecs = nsecs / NSECS_PER_USEC;
2698 2722
2699 type = parse_common_type(data); 2723 type = trace_parse_common_type(data);
2700 2724
2701 event = find_event(type); 2725 event = trace_find_event(type);
2702 if (!event) 2726 if (!event) {
2703 die("ug! no event found for type %d", type); 2727 printf("ug! no event found for type %d\n", type);
2728 return;
2729 }
2704 2730
2705 pid = parse_common_pid(data); 2731 pid = parse_common_pid(data);
2706 2732
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index a1217a10632f..1b5c847d2c22 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -458,12 +458,13 @@ struct record *trace_read_data(int cpu)
458 return data; 458 return data;
459} 459}
460 460
461void trace_report (void) 461void trace_report(void)
462{ 462{
463 const char *input_file = "trace.info"; 463 const char *input_file = "trace.info";
464 char buf[BUFSIZ]; 464 char buf[BUFSIZ];
465 char test[] = { 23, 8, 68 }; 465 char test[] = { 23, 8, 68 };
466 char *version; 466 char *version;
467 int show_version = 0;
467 int show_funcs = 0; 468 int show_funcs = 0;
468 int show_printk = 0; 469 int show_printk = 0;
469 470
@@ -480,7 +481,8 @@ void trace_report (void)
480 die("not a trace file (missing tracing)"); 481 die("not a trace file (missing tracing)");
481 482
482 version = read_string(); 483 version = read_string();
483 printf("version = %s\n", version); 484 if (show_version)
485 printf("version = %s\n", version);
484 free(version); 486 free(version);
485 487
486 read_or_die(buf, 1); 488 read_or_die(buf, 1);
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 420294a5773e..693f815c9429 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -234,7 +234,12 @@ extern int header_page_data_offset;
234extern int header_page_data_size; 234extern int header_page_data_size;
235 235
236int parse_header_page(char *buf, unsigned long size); 236int parse_header_page(char *buf, unsigned long size);
237int trace_parse_common_type(void *data);
238struct event *trace_find_event(int id);
239unsigned long long
240raw_field_value(struct event *event, const char *name, void *data);
241void *raw_field_ptr(struct event *event, const char *name, void *data);
237 242
238void read_tracing_data(struct perf_counter_attr *pattrs, int nb_counters); 243void read_tracing_data(struct perf_event_attr *pattrs, int nb_events);
239 244
240#endif /* _TRACE_EVENTS_H */ 245#endif /* _TRACE_EVENTS_H */