aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-01-03 13:39:04 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-01-03 13:39:04 -0500
commit69aad6f1ee69546dea8535ab8f3da9f445d57328 (patch)
treeb328ec140a6a90703a049fcc661d623025d7e81f /tools/perf/util
parent56f4c400349157289b474a3fd49ee96acab0a4d7 (diff)
perf tools: Introduce event selectors
Out of ad-hoc code and global arrays with hard coded sizes. This is the first step on having a library that will be first used on regression tests in the 'perf test' tool. [acme@felicio linux]$ size /tmp/perf.before text data bss dec hex filename 1273776 97384 5104416 6475576 62cf38 /tmp/perf.before [acme@felicio linux]$ size /tmp/perf.new text data bss dec hex filename 1275422 97416 1392416 2765254 2a31c6 /tmp/perf.new Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/evsel.c35
-rw-r--r--tools/perf/util/evsel.h24
-rw-r--r--tools/perf/util/header.c9
-rw-r--r--tools/perf/util/header.h3
-rw-r--r--tools/perf/util/parse-events.c47
-rw-r--r--tools/perf/util/parse-events.h17
-rw-r--r--tools/perf/util/trace-event-info.c30
-rw-r--r--tools/perf/util/trace-event.h5
-rw-r--r--tools/perf/util/xyarray.c20
-rw-r--r--tools/perf/util/xyarray.h20
10 files changed, 164 insertions, 46 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
new file mode 100644
index 000000000000..6539ec912c70
--- /dev/null
+++ b/tools/perf/util/evsel.c
@@ -0,0 +1,35 @@
1#include "evsel.h"
2#include "util.h"
3
4struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx)
5{
6 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
7
8 if (evsel != NULL) {
9 evsel->idx = idx;
10 evsel->attr.type = type;
11 evsel->attr.config = config;
12 INIT_LIST_HEAD(&evsel->node);
13 }
14
15 return evsel;
16}
17
18int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
19{
20 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
21 return evsel->fd != NULL ? 0 : -ENOMEM;
22}
23
24void perf_evsel__free_fd(struct perf_evsel *evsel)
25{
26 xyarray__delete(evsel->fd);
27 evsel->fd = NULL;
28}
29
30void perf_evsel__delete(struct perf_evsel *evsel)
31{
32 assert(list_empty(&evsel->node));
33 xyarray__delete(evsel->fd);
34 free(evsel);
35}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
new file mode 100644
index 000000000000..3eb3989a2110
--- /dev/null
+++ b/tools/perf/util/evsel.h
@@ -0,0 +1,24 @@
1#ifndef __PERF_EVSEL_H
2#define __PERF_EVSEL_H 1
3
4#include <linux/list.h>
5#include <linux/perf_event.h>
6#include "types.h"
7#include "xyarray.h"
8
9struct perf_evsel {
10 struct list_head node;
11 struct perf_event_attr attr;
12 char *filter;
13 struct xyarray *fd;
14 int idx;
15 void *priv;
16};
17
18struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx);
19void perf_evsel__delete(struct perf_evsel *evsel);
20
21int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
22void perf_evsel__free_fd(struct perf_evsel *evsel);
23
24#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 16a16021eaa6..ecb5a8444f42 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -461,7 +461,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
461 461
462 /* Write trace info */ 462 /* Write trace info */
463 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 463 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
464 read_tracing_data(fd, attrs, nr_counters); 464 read_tracing_data(fd, &evsel_list);
465 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 465 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
466 } 466 }
467 467
@@ -1131,8 +1131,7 @@ int event__process_event_type(event_t *self,
1131 return 0; 1131 return 0;
1132} 1132}
1133 1133
1134int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 1134int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
1135 int nb_events,
1136 event__handler_t process, 1135 event__handler_t process,
1137 struct perf_session *session __unused) 1136 struct perf_session *session __unused)
1138{ 1137{
@@ -1143,7 +1142,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1143 memset(&ev, 0, sizeof(ev)); 1142 memset(&ev, 0, sizeof(ev));
1144 1143
1145 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 1144 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1146 size = read_tracing_data_size(fd, pattrs, nb_events); 1145 size = read_tracing_data_size(fd, pattrs);
1147 if (size <= 0) 1146 if (size <= 0)
1148 return size; 1147 return size;
1149 aligned_size = ALIGN(size, sizeof(u64)); 1148 aligned_size = ALIGN(size, sizeof(u64));
@@ -1153,7 +1152,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1153 1152
1154 process(&ev, NULL, session); 1153 process(&ev, NULL, session);
1155 1154
1156 err = read_tracing_data(fd, pattrs, nb_events); 1155 err = read_tracing_data(fd, pattrs);
1157 write_padded(fd, NULL, 0, padding); 1156 write_padded(fd, NULL, 0, padding);
1158 1157
1159 return aligned_size; 1158 return aligned_size;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6335965e1f93..33f16be7b72f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -113,8 +113,7 @@ int event__synthesize_event_types(event__handler_t process,
113int event__process_event_type(event_t *self, 113int event__process_event_type(event_t *self,
114 struct perf_session *session); 114 struct perf_session *session);
115 115
116int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 116int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
117 int nb_events,
118 event__handler_t process, 117 event__handler_t process,
119 struct perf_session *session); 118 struct perf_session *session);
120int event__process_tracing_data(event_t *self, 119int event__process_tracing_data(event_t *self,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c305305a3884..2d948ad471f4 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
1#include "../../../include/linux/hw_breakpoint.h" 1#include "../../../include/linux/hw_breakpoint.h"
2#include "util.h" 2#include "util.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "evsel.h"
4#include "parse-options.h" 5#include "parse-options.h"
5#include "parse-events.h" 6#include "parse-events.h"
6#include "exec_cmd.h" 7#include "exec_cmd.h"
@@ -12,8 +13,7 @@
12 13
13int nr_counters; 14int nr_counters;
14 15
15struct perf_event_attr attrs[MAX_COUNTERS]; 16LIST_HEAD(evsel_list);
16char *filters[MAX_COUNTERS];
17 17
18struct event_symbol { 18struct event_symbol {
19 u8 type; 19 u8 type;
@@ -266,10 +266,10 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
266 return name; 266 return name;
267} 267}
268 268
269const char *event_name(int counter) 269const char *event_name(struct perf_evsel *evsel)
270{ 270{
271 u64 config = attrs[counter].config; 271 u64 config = evsel->attr.config;
272 int type = attrs[counter].type; 272 int type = evsel->attr.type;
273 273
274 return __event_name(type, config); 274 return __event_name(type, config);
275} 275}
@@ -814,9 +814,6 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
814 return -1; 814 return -1;
815 815
816 for (;;) { 816 for (;;) {
817 if (nr_counters == MAX_COUNTERS)
818 return -1;
819
820 memset(&attr, 0, sizeof(attr)); 817 memset(&attr, 0, sizeof(attr));
821 ret = parse_event_symbols(&str, &attr); 818 ret = parse_event_symbols(&str, &attr);
822 if (ret == EVT_FAILED) 819 if (ret == EVT_FAILED)
@@ -826,8 +823,13 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
826 return -1; 823 return -1;
827 824
828 if (ret != EVT_HANDLED_ALL) { 825 if (ret != EVT_HANDLED_ALL) {
829 attrs[nr_counters] = attr; 826 struct perf_evsel *evsel;
830 nr_counters++; 827 evsel = perf_evsel__new(attr.type, attr.config,
828 nr_counters);
829 if (evsel == NULL)
830 return -1;
831 list_add_tail(&evsel->node, &evsel_list);
832 ++nr_counters;
831 } 833 }
832 834
833 if (*str == 0) 835 if (*str == 0)
@@ -844,21 +846,22 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
844int parse_filter(const struct option *opt __used, const char *str, 846int parse_filter(const struct option *opt __used, const char *str,
845 int unset __used) 847 int unset __used)
846{ 848{
847 int i = nr_counters - 1; 849 struct perf_evsel *last = NULL;
848 int len = strlen(str);
849 850
850 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) { 851 if (!list_empty(&evsel_list))
852 last = list_entry(evsel_list.prev, struct perf_evsel, node);
853
854 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
851 fprintf(stderr, 855 fprintf(stderr,
852 "-F option should follow a -e tracepoint option\n"); 856 "-F option should follow a -e tracepoint option\n");
853 return -1; 857 return -1;
854 } 858 }
855 859
856 filters[i] = malloc(len + 1); 860 last->filter = strdup(str);
857 if (!filters[i]) { 861 if (last->filter == NULL) {
858 fprintf(stderr, "not enough memory to hold filter string\n"); 862 fprintf(stderr, "not enough memory to hold filter string\n");
859 return -1; 863 return -1;
860 } 864 }
861 strcpy(filters[i], str);
862 865
863 return 0; 866 return 0;
864} 867}
@@ -967,3 +970,15 @@ void print_events(void)
967 970
968 exit(129); 971 exit(129);
969} 972}
973
974int perf_evsel_list__create_default(void)
975{
976 struct perf_evsel *evsel = perf_evsel__new(PERF_TYPE_HARDWARE,
977 PERF_COUNT_HW_CPU_CYCLES, 0);
978 if (evsel == NULL)
979 return -ENOMEM;
980
981 list_add(&evsel->node, &evsel_list);
982 ++nr_counters;
983 return 0;
984}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index fc4ab3fe877a..0f915a01a3f7 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -4,6 +4,15 @@
4 * Parse symbolic events/counts passed in as options: 4 * Parse symbolic events/counts passed in as options:
5 */ 5 */
6 6
7#include <linux/perf_event.h>
8
9struct list_head;
10struct perf_evsel;
11
12extern struct list_head evsel_list;
13
14int perf_evsel_list__create_default(void);
15
7struct option; 16struct option;
8 17
9struct tracepoint_path { 18struct tracepoint_path {
@@ -13,14 +22,11 @@ struct tracepoint_path {
13}; 22};
14 23
15extern struct tracepoint_path *tracepoint_id_to_path(u64 config); 24extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
16extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events); 25extern bool have_tracepoints(struct list_head *evsel_list);
17 26
18extern int nr_counters; 27extern int nr_counters;
19 28
20extern struct perf_event_attr attrs[MAX_COUNTERS]; 29const char *event_name(struct perf_evsel *event);
21extern char *filters[MAX_COUNTERS];
22
23extern const char *event_name(int ctr);
24extern const char *__event_name(int type, u64 config); 30extern const char *__event_name(int type, u64 config);
25 31
26extern int parse_events(const struct option *opt, const char *str, int unset); 32extern int parse_events(const struct option *opt, const char *str, int unset);
@@ -33,5 +39,4 @@ extern void print_events(void);
33extern char debugfs_path[]; 39extern char debugfs_path[];
34extern int valid_debugfs_mount(const char *debugfs); 40extern int valid_debugfs_mount(const char *debugfs);
35 41
36
37#endif /* __PERF_PARSE_EVENTS_H */ 42#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index b1572601286c..35729f4c40cb 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -34,11 +34,13 @@
34#include <ctype.h> 34#include <ctype.h>
35#include <errno.h> 35#include <errno.h>
36#include <stdbool.h> 36#include <stdbool.h>
37#include <linux/list.h>
37#include <linux/kernel.h> 38#include <linux/kernel.h>
38 39
39#include "../perf.h" 40#include "../perf.h"
40#include "trace-event.h" 41#include "trace-event.h"
41#include "debugfs.h" 42#include "debugfs.h"
43#include "evsel.h"
42 44
43#define VERSION "0.5" 45#define VERSION "0.5"
44 46
@@ -469,16 +471,17 @@ out:
469} 471}
470 472
471static struct tracepoint_path * 473static struct tracepoint_path *
472get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events) 474get_tracepoints_path(struct list_head *pattrs)
473{ 475{
474 struct tracepoint_path path, *ppath = &path; 476 struct tracepoint_path path, *ppath = &path;
475 int i, nr_tracepoints = 0; 477 struct perf_evsel *pos;
478 int nr_tracepoints = 0;
476 479
477 for (i = 0; i < nb_events; i++) { 480 list_for_each_entry(pos, pattrs, node) {
478 if (pattrs[i].type != PERF_TYPE_TRACEPOINT) 481 if (pos->attr.type != PERF_TYPE_TRACEPOINT)
479 continue; 482 continue;
480 ++nr_tracepoints; 483 ++nr_tracepoints;
481 ppath->next = tracepoint_id_to_path(pattrs[i].config); 484 ppath->next = tracepoint_id_to_path(pos->attr.config);
482 if (!ppath->next) 485 if (!ppath->next)
483 die("%s\n", "No memory to alloc tracepoints list"); 486 die("%s\n", "No memory to alloc tracepoints list");
484 ppath = ppath->next; 487 ppath = ppath->next;
@@ -487,21 +490,21 @@ get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
487 return nr_tracepoints > 0 ? path.next : NULL; 490 return nr_tracepoints > 0 ? path.next : NULL;
488} 491}
489 492
490bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events) 493bool have_tracepoints(struct list_head *pattrs)
491{ 494{
492 int i; 495 struct perf_evsel *pos;
493 496
494 for (i = 0; i < nb_events; i++) 497 list_for_each_entry(pos, pattrs, node)
495 if (pattrs[i].type == PERF_TYPE_TRACEPOINT) 498 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
496 return true; 499 return true;
497 500
498 return false; 501 return false;
499} 502}
500 503
501int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events) 504int read_tracing_data(int fd, struct list_head *pattrs)
502{ 505{
503 char buf[BUFSIZ]; 506 char buf[BUFSIZ];
504 struct tracepoint_path *tps = get_tracepoints_path(pattrs, nb_events); 507 struct tracepoint_path *tps = get_tracepoints_path(pattrs);
505 508
506 /* 509 /*
507 * What? No tracepoints? No sense writing anything here, bail out. 510 * What? No tracepoints? No sense writing anything here, bail out.
@@ -545,14 +548,13 @@ int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
545 return 0; 548 return 0;
546} 549}
547 550
548ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, 551ssize_t read_tracing_data_size(int fd, struct list_head *pattrs)
549 int nb_events)
550{ 552{
551 ssize_t size; 553 ssize_t size;
552 int err = 0; 554 int err = 0;
553 555
554 calc_data_size = 1; 556 calc_data_size = 1;
555 err = read_tracing_data(fd, pattrs, nb_events); 557 err = read_tracing_data(fd, pattrs);
556 size = calc_data_size - 1; 558 size = calc_data_size - 1;
557 calc_data_size = 0; 559 calc_data_size = 0;
558 560
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b3e86b1e4444..b5f12ca24d99 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -262,9 +262,8 @@ raw_field_value(struct event *event, const char *name, void *data);
262void *raw_field_ptr(struct event *event, const char *name, void *data); 262void *raw_field_ptr(struct event *event, const char *name, void *data);
263unsigned long long eval_flag(const char *flag); 263unsigned long long eval_flag(const char *flag);
264 264
265int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); 265int read_tracing_data(int fd, struct list_head *pattrs);
266ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, 266ssize_t read_tracing_data_size(int fd, struct list_head *pattrs);
267 int nb_events);
268 267
269/* taken from kernel/trace/trace.h */ 268/* taken from kernel/trace/trace.h */
270enum trace_flag_type { 269enum trace_flag_type {
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
new file mode 100644
index 000000000000..22afbf6c536a
--- /dev/null
+++ b/tools/perf/util/xyarray.c
@@ -0,0 +1,20 @@
1#include "xyarray.h"
2#include "util.h"
3
4struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
5{
6 size_t row_size = ylen * entry_size;
7 struct xyarray *xy = zalloc(sizeof(*xy) + xlen * row_size);
8
9 if (xy != NULL) {
10 xy->entry_size = entry_size;
11 xy->row_size = row_size;
12 }
13
14 return xy;
15}
16
17void xyarray__delete(struct xyarray *xy)
18{
19 free(xy);
20}
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
new file mode 100644
index 000000000000..c488a07275dd
--- /dev/null
+++ b/tools/perf/util/xyarray.h
@@ -0,0 +1,20 @@
1#ifndef _PERF_XYARRAY_H_
2#define _PERF_XYARRAY_H_ 1
3
4#include <sys/types.h>
5
6struct xyarray {
7 size_t row_size;
8 size_t entry_size;
9 char contents[];
10};
11
12struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
13void xyarray__delete(struct xyarray *xy);
14
15static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
16{
17 return &xy->contents[x * xy->row_size + y * xy->entry_size];
18}
19
20#endif /* _PERF_XYARRAY_H_ */