diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-03 13:39:04 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-03 13:39:04 -0500 |
commit | 69aad6f1ee69546dea8535ab8f3da9f445d57328 (patch) | |
tree | b328ec140a6a90703a049fcc661d623025d7e81f /tools/perf/util | |
parent | 56f4c400349157289b474a3fd49ee96acab0a4d7 (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.c | 35 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 24 | ||||
-rw-r--r-- | tools/perf/util/header.c | 9 | ||||
-rw-r--r-- | tools/perf/util/header.h | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 47 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 17 | ||||
-rw-r--r-- | tools/perf/util/trace-event-info.c | 30 | ||||
-rw-r--r-- | tools/perf/util/trace-event.h | 5 | ||||
-rw-r--r-- | tools/perf/util/xyarray.c | 20 | ||||
-rw-r--r-- | tools/perf/util/xyarray.h | 20 |
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 | |||
4 | struct 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 | |||
18 | int 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 | |||
24 | void perf_evsel__free_fd(struct perf_evsel *evsel) | ||
25 | { | ||
26 | xyarray__delete(evsel->fd); | ||
27 | evsel->fd = NULL; | ||
28 | } | ||
29 | |||
30 | void 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 | |||
9 | struct 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 | |||
18 | struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx); | ||
19 | void perf_evsel__delete(struct perf_evsel *evsel); | ||
20 | |||
21 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | ||
22 | void 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 | ||
1134 | int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | 1134 | int 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, | |||
113 | int event__process_event_type(event_t *self, | 113 | int event__process_event_type(event_t *self, |
114 | struct perf_session *session); | 114 | struct perf_session *session); |
115 | 115 | ||
116 | int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | 116 | int 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); |
120 | int event__process_tracing_data(event_t *self, | 119 | int 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 | ||
13 | int nr_counters; | 14 | int nr_counters; |
14 | 15 | ||
15 | struct perf_event_attr attrs[MAX_COUNTERS]; | 16 | LIST_HEAD(evsel_list); |
16 | char *filters[MAX_COUNTERS]; | ||
17 | 17 | ||
18 | struct event_symbol { | 18 | struct 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 | ||
269 | const char *event_name(int counter) | 269 | const 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 | |||
844 | int parse_filter(const struct option *opt __used, const char *str, | 846 | int 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 | |||
974 | int 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 | |||
9 | struct list_head; | ||
10 | struct perf_evsel; | ||
11 | |||
12 | extern struct list_head evsel_list; | ||
13 | |||
14 | int perf_evsel_list__create_default(void); | ||
15 | |||
7 | struct option; | 16 | struct option; |
8 | 17 | ||
9 | struct tracepoint_path { | 18 | struct tracepoint_path { |
@@ -13,14 +22,11 @@ struct tracepoint_path { | |||
13 | }; | 22 | }; |
14 | 23 | ||
15 | extern struct tracepoint_path *tracepoint_id_to_path(u64 config); | 24 | extern struct tracepoint_path *tracepoint_id_to_path(u64 config); |
16 | extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events); | 25 | extern bool have_tracepoints(struct list_head *evsel_list); |
17 | 26 | ||
18 | extern int nr_counters; | 27 | extern int nr_counters; |
19 | 28 | ||
20 | extern struct perf_event_attr attrs[MAX_COUNTERS]; | 29 | const char *event_name(struct perf_evsel *event); |
21 | extern char *filters[MAX_COUNTERS]; | ||
22 | |||
23 | extern const char *event_name(int ctr); | ||
24 | extern const char *__event_name(int type, u64 config); | 30 | extern const char *__event_name(int type, u64 config); |
25 | 31 | ||
26 | extern int parse_events(const struct option *opt, const char *str, int unset); | 32 | extern int parse_events(const struct option *opt, const char *str, int unset); |
@@ -33,5 +39,4 @@ extern void print_events(void); | |||
33 | extern char debugfs_path[]; | 39 | extern char debugfs_path[]; |
34 | extern int valid_debugfs_mount(const char *debugfs); | 40 | extern 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 | ||
471 | static struct tracepoint_path * | 473 | static struct tracepoint_path * |
472 | get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events) | 474 | get_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 | ||
490 | bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events) | 493 | bool 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 | ||
501 | int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events) | 504 | int 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 | ||
548 | ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, | 551 | ssize_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); | |||
262 | void *raw_field_ptr(struct event *event, const char *name, void *data); | 262 | void *raw_field_ptr(struct event *event, const char *name, void *data); |
263 | unsigned long long eval_flag(const char *flag); | 263 | unsigned long long eval_flag(const char *flag); |
264 | 264 | ||
265 | int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); | 265 | int read_tracing_data(int fd, struct list_head *pattrs); |
266 | ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, | 266 | ssize_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 */ |
270 | enum trace_flag_type { | 269 | enum 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 | |||
4 | struct 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 | |||
17 | void 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 | |||
6 | struct xyarray { | ||
7 | size_t row_size; | ||
8 | size_t entry_size; | ||
9 | char contents[]; | ||
10 | }; | ||
11 | |||
12 | struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size); | ||
13 | void xyarray__delete(struct xyarray *xy); | ||
14 | |||
15 | static 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_ */ | ||