aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-09-24 18:13:11 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-24 18:13:11 -0400
commit8b3f6af86378d0a10ca2f1ded1da124aef13b62c (patch)
treede6ca90295730343c495be8d98be8efa322140ef /tools/perf/util
parent139d6065c83071d5f66cd013a274a43699f8e2c1 (diff)
parent94e0fb086fc5663c38bbc0fe86d698be8314f82f (diff)
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts: drivers/staging/Kconfig drivers/staging/Makefile drivers/staging/cpc-usb/TODO drivers/staging/cpc-usb/cpc-usb_drv.c drivers/staging/cpc-usb/cpc.h drivers/staging/cpc-usb/cpc_int.h drivers/staging/cpc-usb/cpcusb.h
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/parse-events.c263
-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.c488
-rw-r--r--tools/perf/util/svghelper.h28
-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.c45
-rw-r--r--tools/perf/util/trace-event-read.c6
-rw-r--r--tools/perf/util/trace-event.h7
14 files changed, 864 insertions, 106 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/parse-events.c b/tools/perf/util/parse-events.c
index a587d41ae3c9..13ab4b842d49 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{
@@ -344,8 +351,8 @@ static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int
344 return -1; 351 return -1;
345} 352}
346 353
347static int 354static enum event_result
348parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) 355parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
349{ 356{
350 const char *s = *str; 357 const char *s = *str;
351 int cache_type = -1, cache_op = -1, cache_result = -1; 358 int cache_type = -1, cache_op = -1, cache_result = -1;
@@ -356,7 +363,7 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
356 * then bail out: 363 * then bail out:
357 */ 364 */
358 if (cache_type == -1) 365 if (cache_type == -1)
359 return 0; 366 return EVT_FAILED;
360 367
361 while ((cache_op == -1 || cache_result == -1) && *s == '-') { 368 while ((cache_op == -1 || cache_result == -1) && *s == '-') {
362 ++s; 369 ++s;
@@ -402,27 +409,115 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
402 attr->type = PERF_TYPE_HW_CACHE; 409 attr->type = PERF_TYPE_HW_CACHE;
403 410
404 *str = s; 411 *str = s;
405 return 1; 412 return EVT_HANDLED;
413}
414
415static enum event_result
416parse_single_tracepoint_event(char *sys_name,
417 const char *evt_name,
418 unsigned int evt_length,
419 char *flags,
420 struct perf_event_attr *attr,
421 const char **strp)
422{
423 char evt_path[MAXPATHLEN];
424 char id_buf[4];
425 u64 id;
426 int fd;
427
428 if (flags) {
429 if (!strncmp(flags, "record", strlen(flags))) {
430 attr->sample_type |= PERF_SAMPLE_RAW;
431 attr->sample_type |= PERF_SAMPLE_TIME;
432 attr->sample_type |= PERF_SAMPLE_CPU;
433 }
434 }
435
436 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
437 sys_name, evt_name);
438
439 fd = open(evt_path, O_RDONLY);
440 if (fd < 0)
441 return EVT_FAILED;
442
443 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
444 close(fd);
445 return EVT_FAILED;
446 }
447
448 close(fd);
449 id = atoll(id_buf);
450 attr->config = id;
451 attr->type = PERF_TYPE_TRACEPOINT;
452 *strp = evt_name + evt_length;
453
454 return EVT_HANDLED;
455}
456
457/* sys + ':' + event + ':' + flags*/
458#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
459static enum event_result
460parse_subsystem_tracepoint_event(char *sys_name, char *flags)
461{
462 char evt_path[MAXPATHLEN];
463 struct dirent *evt_ent;
464 DIR *evt_dir;
465
466 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
467 evt_dir = opendir(evt_path);
468
469 if (!evt_dir) {
470 perror("Can't open event dir");
471 return EVT_FAILED;
472 }
473
474 while ((evt_ent = readdir(evt_dir))) {
475 char event_opt[MAX_EVOPT_LEN + 1];
476 int len;
477 unsigned int rem = MAX_EVOPT_LEN;
478
479 if (!strcmp(evt_ent->d_name, ".")
480 || !strcmp(evt_ent->d_name, "..")
481 || !strcmp(evt_ent->d_name, "enable")
482 || !strcmp(evt_ent->d_name, "filter"))
483 continue;
484
485 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
486 evt_ent->d_name);
487 if (len < 0)
488 return EVT_FAILED;
489
490 rem -= len;
491 if (flags) {
492 if (rem < strlen(flags) + 1)
493 return EVT_FAILED;
494
495 strcat(event_opt, ":");
496 strcat(event_opt, flags);
497 }
498
499 if (parse_events(NULL, event_opt, 0))
500 return EVT_FAILED;
501 }
502
503 return EVT_HANDLED_ALL;
406} 504}
407 505
408static int parse_tracepoint_event(const char **strp, 506
409 struct perf_counter_attr *attr) 507static enum event_result parse_tracepoint_event(const char **strp,
508 struct perf_event_attr *attr)
410{ 509{
411 const char *evt_name; 510 const char *evt_name;
412 char *flags; 511 char *flags;
413 char sys_name[MAX_EVENT_LENGTH]; 512 char sys_name[MAX_EVENT_LENGTH];
414 char id_buf[4];
415 int fd;
416 unsigned int sys_length, evt_length; 513 unsigned int sys_length, evt_length;
417 u64 id;
418 char evt_path[MAXPATHLEN];
419 514
420 if (valid_debugfs_mount(debugfs_path)) 515 if (valid_debugfs_mount(debugfs_path))
421 return 0; 516 return 0;
422 517
423 evt_name = strchr(*strp, ':'); 518 evt_name = strchr(*strp, ':');
424 if (!evt_name) 519 if (!evt_name)
425 return 0; 520 return EVT_FAILED;
426 521
427 sys_length = evt_name - *strp; 522 sys_length = evt_name - *strp;
428 if (sys_length >= MAX_EVENT_LENGTH) 523 if (sys_length >= MAX_EVENT_LENGTH)
@@ -434,32 +529,22 @@ static int parse_tracepoint_event(const char **strp,
434 529
435 flags = strchr(evt_name, ':'); 530 flags = strchr(evt_name, ':');
436 if (flags) { 531 if (flags) {
437 *flags = '\0'; 532 /* split it out: */
533 evt_name = strndup(evt_name, flags - evt_name);
438 flags++; 534 flags++;
439 if (!strncmp(flags, "record", strlen(flags)))
440 attr->sample_type |= PERF_SAMPLE_RAW;
441 } 535 }
442 536
443 evt_length = strlen(evt_name); 537 evt_length = strlen(evt_name);
444 if (evt_length >= MAX_EVENT_LENGTH) 538 if (evt_length >= MAX_EVENT_LENGTH)
445 return 0; 539 return EVT_FAILED;
446
447 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
448 sys_name, evt_name);
449 fd = open(evt_path, O_RDONLY);
450 if (fd < 0)
451 return 0;
452 540
453 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 541 if (!strcmp(evt_name, "*")) {
454 close(fd); 542 *strp = evt_name + evt_length;
455 return 0; 543 return parse_subsystem_tracepoint_event(sys_name, flags);
456 } 544 } else
457 close(fd); 545 return parse_single_tracepoint_event(sys_name, evt_name,
458 id = atoll(id_buf); 546 evt_length, flags,
459 attr->config = id; 547 attr, strp);
460 attr->type = PERF_TYPE_TRACEPOINT;
461 *strp = evt_name + evt_length;
462 return 1;
463} 548}
464 549
465static int check_events(const char *str, unsigned int i) 550static int check_events(const char *str, unsigned int i)
@@ -477,8 +562,8 @@ static int check_events(const char *str, unsigned int i)
477 return 0; 562 return 0;
478} 563}
479 564
480static int 565static enum event_result
481parse_symbolic_event(const char **strp, struct perf_counter_attr *attr) 566parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
482{ 567{
483 const char *str = *strp; 568 const char *str = *strp;
484 unsigned int i; 569 unsigned int i;
@@ -490,32 +575,33 @@ parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
490 attr->type = event_symbols[i].type; 575 attr->type = event_symbols[i].type;
491 attr->config = event_symbols[i].config; 576 attr->config = event_symbols[i].config;
492 *strp = str + n; 577 *strp = str + n;
493 return 1; 578 return EVT_HANDLED;
494 } 579 }
495 } 580 }
496 return 0; 581 return EVT_FAILED;
497} 582}
498 583
499static int parse_raw_event(const char **strp, struct perf_counter_attr *attr) 584static enum event_result
585parse_raw_event(const char **strp, struct perf_event_attr *attr)
500{ 586{
501 const char *str = *strp; 587 const char *str = *strp;
502 u64 config; 588 u64 config;
503 int n; 589 int n;
504 590
505 if (*str != 'r') 591 if (*str != 'r')
506 return 0; 592 return EVT_FAILED;
507 n = hex2u64(str + 1, &config); 593 n = hex2u64(str + 1, &config);
508 if (n > 0) { 594 if (n > 0) {
509 *strp = str + n + 1; 595 *strp = str + n + 1;
510 attr->type = PERF_TYPE_RAW; 596 attr->type = PERF_TYPE_RAW;
511 attr->config = config; 597 attr->config = config;
512 return 1; 598 return EVT_HANDLED;
513 } 599 }
514 return 0; 600 return EVT_FAILED;
515} 601}
516 602
517static int 603static enum event_result
518parse_numeric_event(const char **strp, struct perf_counter_attr *attr) 604parse_numeric_event(const char **strp, struct perf_event_attr *attr)
519{ 605{
520 const char *str = *strp; 606 const char *str = *strp;
521 char *endp; 607 char *endp;
@@ -530,14 +616,14 @@ parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
530 attr->type = type; 616 attr->type = type;
531 attr->config = config; 617 attr->config = config;
532 *strp = endp; 618 *strp = endp;
533 return 1; 619 return EVT_HANDLED;
534 } 620 }
535 } 621 }
536 return 0; 622 return EVT_FAILED;
537} 623}
538 624
539static int 625static enum event_result
540parse_event_modifier(const char **strp, struct perf_counter_attr *attr) 626parse_event_modifier(const char **strp, struct perf_event_attr *attr)
541{ 627{
542 const char *str = *strp; 628 const char *str = *strp;
543 int eu = 1, ek = 1, eh = 1; 629 int eu = 1, ek = 1, eh = 1;
@@ -569,37 +655,84 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
569 * Each event can have multiple symbolic names. 655 * Each event can have multiple symbolic names.
570 * Symbolic names are (almost) exactly matched. 656 * Symbolic names are (almost) exactly matched.
571 */ 657 */
572static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) 658static enum event_result
659parse_event_symbols(const char **str, struct perf_event_attr *attr)
573{ 660{
574 if (!(parse_tracepoint_event(str, attr) || 661 enum event_result ret;
575 parse_raw_event(str, attr) || 662
576 parse_numeric_event(str, attr) || 663 ret = parse_tracepoint_event(str, attr);
577 parse_symbolic_event(str, attr) || 664 if (ret != EVT_FAILED)
578 parse_generic_hw_event(str, attr))) 665 goto modifier;
579 return 0; 666
667 ret = parse_raw_event(str, attr);
668 if (ret != EVT_FAILED)
669 goto modifier;
670
671 ret = parse_numeric_event(str, attr);
672 if (ret != EVT_FAILED)
673 goto modifier;
674
675 ret = parse_symbolic_event(str, attr);
676 if (ret != EVT_FAILED)
677 goto modifier;
580 678
679 ret = parse_generic_hw_event(str, attr);
680 if (ret != EVT_FAILED)
681 goto modifier;
682
683 return EVT_FAILED;
684
685modifier:
581 parse_event_modifier(str, attr); 686 parse_event_modifier(str, attr);
582 687
583 return 1; 688 return ret;
584} 689}
585 690
691static void store_event_type(const char *orgname)
692{
693 char filename[PATH_MAX], *c;
694 FILE *file;
695 int id;
696
697 sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
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;
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..a778fd0f4ae4
--- /dev/null
+++ b/tools/perf/util/svghelper.c
@@ -0,0 +1,488 @@
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.001
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 return cpu_m;
221}
222
223void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
224{
225 char cpu_string[80];
226 if (!svgfile)
227 return;
228
229 max_freq = __max_freq;
230 turbo_frequency = __turbo_freq;
231
232 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n",
233 time2pixels(first_time),
234 time2pixels(last_time)-time2pixels(first_time),
235 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
236
237 sprintf(cpu_string, "CPU %i", (int)cpu+1);
238 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
239 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
240
241 fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
242 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
243}
244
245void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name)
246{
247 double width;
248
249 if (!svgfile)
250 return;
251
252
253 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
254 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
255 time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
256 width = time2pixels(end)-time2pixels(start);
257 if (width > 6)
258 width = 6;
259
260 width = round_text_size(width);
261
262 if (width > MIN_TEXT_SIZE)
263 fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n",
264 width, name);
265
266 fprintf(svgfile, "</g>\n");
267}
268
269void svg_cstate(int cpu, u64 start, u64 end, int type)
270{
271 double width;
272 char style[128];
273
274 if (!svgfile)
275 return;
276
277
278 if (type > 6)
279 type = 6;
280 sprintf(style, "c%i", type);
281
282 fprintf(svgfile, "<rect class=\"%s\" x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\"/>\n",
283 style,
284 time2pixels(start), time2pixels(end)-time2pixels(start),
285 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
286
287 width = (time2pixels(end)-time2pixels(start))/2.0;
288 if (width > 6)
289 width = 6;
290
291 width = round_text_size(width);
292
293 if (width > MIN_TEXT_SIZE)
294 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
295 time2pixels(start), cpu2y(cpu)+width, width, type);
296}
297
298static char *HzToHuman(unsigned long hz)
299{
300 static char buffer[1024];
301 unsigned long long Hz;
302
303 memset(buffer, 0, 1024);
304
305 Hz = hz;
306
307 /* default: just put the Number in */
308 sprintf(buffer, "%9lli", Hz);
309
310 if (Hz > 1000)
311 sprintf(buffer, " %6lli Mhz", (Hz+500)/1000);
312
313 if (Hz > 1500000)
314 sprintf(buffer, " %6.2f Ghz", (Hz+5000.0)/1000000);
315
316 if (Hz == turbo_frequency)
317 sprintf(buffer, "Turbo");
318
319 return buffer;
320}
321
322void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
323{
324 double height = 0;
325
326 if (!svgfile)
327 return;
328
329 if (max_freq)
330 height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT);
331 height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
332 fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n",
333 time2pixels(start), time2pixels(end), height, height);
334 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
335 time2pixels(start), height+0.9, HzToHuman(freq));
336
337}
338
339
340void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2)
341{
342 double height;
343
344 if (!svgfile)
345 return;
346
347
348 if (row1 < row2) {
349 if (row1) {
350 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",
351 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
352 if (desc2)
353 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
354 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
355 }
356 if (row2) {
357 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",
358 time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
359 if (desc1)
360 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
361 time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
362 }
363 } else {
364 if (row2) {
365 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",
366 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
367 if (desc1)
368 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
369 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
370 }
371 if (row1) {
372 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",
373 time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
374 if (desc2)
375 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
376 time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
377 }
378 }
379 height = row1 * SLOT_MULT;
380 if (row2 > row1)
381 height += SLOT_HEIGHT;
382 if (row1)
383 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
384 time2pixels(start), height);
385}
386
387void svg_wakeline(u64 start, int row1, int row2)
388{
389 double height;
390
391 if (!svgfile)
392 return;
393
394
395 if (row1 < row2)
396 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",
397 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT);
398 else
399 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",
400 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT);
401
402 height = row1 * SLOT_MULT;
403 if (row2 > row1)
404 height += SLOT_HEIGHT;
405 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
406 time2pixels(start), height);
407}
408
409void svg_interrupt(u64 start, int row)
410{
411 if (!svgfile)
412 return;
413
414 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
415 time2pixels(start), row * SLOT_MULT);
416 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
417 time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT);
418}
419
420void svg_text(int Yslot, u64 start, const char *text)
421{
422 if (!svgfile)
423 return;
424
425 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
426 time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text);
427}
428
429static void svg_legenda_box(int X, const char *text, const char *style)
430{
431 double boxsize;
432 boxsize = SLOT_HEIGHT / 2;
433
434 fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
435 X, boxsize, boxsize, style);
436 fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n",
437 X + boxsize + 5, boxsize, 0.8 * boxsize, text);
438}
439
440void svg_legenda(void)
441{
442 if (!svgfile)
443 return;
444
445 svg_legenda_box(0, "Running", "sample");
446 svg_legenda_box(100, "Idle","rect.c1");
447 svg_legenda_box(200, "Deeper Idle", "rect.c3");
448 svg_legenda_box(350, "Deepest Idle", "rect.c6");
449 svg_legenda_box(550, "Sleeping", "process2");
450 svg_legenda_box(650, "Waiting for cpu", "waiting");
451 svg_legenda_box(800, "Blocked on IO", "blocked");
452}
453
454void svg_time_grid(void)
455{
456 u64 i;
457
458 if (!svgfile)
459 return;
460
461 i = first_time;
462 while (i < last_time) {
463 int color = 220;
464 double thickness = 0.075;
465 if ((i % 100000000) == 0) {
466 thickness = 0.5;
467 color = 192;
468 }
469 if ((i % 1000000000) == 0) {
470 thickness = 2.0;
471 color = 128;
472 }
473
474 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",
475 time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness);
476
477 i += 10000000;
478 }
479}
480
481void svg_close(void)
482{
483 if (svgfile) {
484 fprintf(svgfile, "</svg>\n");
485 fclose(svgfile);
486 svgfile = NULL;
487 }
488}
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/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..f6a8437141c8 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -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
@@ -2420,8 +2443,8 @@ get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2420 int type; 2443 int type;
2421 int pid; 2444 int pid;
2422 2445
2423 type = parse_common_type(next->data); 2446 type = trace_parse_common_type(next->data);
2424 event = find_event(type); 2447 event = trace_find_event(type);
2425 if (!event) 2448 if (!event)
2426 return NULL; 2449 return NULL;
2427 2450
@@ -2502,8 +2525,8 @@ print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec)
2502 int type; 2525 int type;
2503 int i; 2526 int i;
2504 2527
2505 type = parse_common_type(ret_rec->data); 2528 type = trace_parse_common_type(ret_rec->data);
2506 ret_event = find_event(type); 2529 ret_event = trace_find_event(type);
2507 2530
2508 field = find_field(ret_event, "rettime"); 2531 field = find_field(ret_event, "rettime");
2509 if (!field) 2532 if (!field)
@@ -2696,11 +2719,13 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2696 nsecs -= secs * NSECS_PER_SEC; 2719 nsecs -= secs * NSECS_PER_SEC;
2697 usecs = nsecs / NSECS_PER_USEC; 2720 usecs = nsecs / NSECS_PER_USEC;
2698 2721
2699 type = parse_common_type(data); 2722 type = trace_parse_common_type(data);
2700 2723
2701 event = find_event(type); 2724 event = trace_find_event(type);
2702 if (!event) 2725 if (!event) {
2703 die("ug! no event found for type %d", type); 2726 printf("ug! no event found for type %d\n", type);
2727 return;
2728 }
2704 2729
2705 pid = parse_common_pid(data); 2730 pid = parse_common_pid(data);
2706 2731
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 */