diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/cpumap.c | 123 | ||||
-rw-r--r-- | tools/perf/util/cpumap.h | 10 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 186 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 115 | ||||
-rw-r--r-- | tools/perf/util/header.c | 15 | ||||
-rw-r--r-- | tools/perf/util/header.h | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 58 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 18 | ||||
-rw-r--r-- | tools/perf/util/session.c | 22 | ||||
-rw-r--r-- | tools/perf/util/session.h | 1 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 43 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 15 | ||||
-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/util.c | 17 | ||||
-rw-r--r-- | tools/perf/util/util.h | 1 | ||||
-rw-r--r-- | tools/perf/util/xyarray.c | 20 | ||||
-rw-r--r-- | tools/perf/util/xyarray.h | 20 |
18 files changed, 586 insertions, 116 deletions
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 0f9b8d7a7d7..3ccaa104338 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
@@ -4,32 +4,53 @@ | |||
4 | #include <assert.h> | 4 | #include <assert.h> |
5 | #include <stdio.h> | 5 | #include <stdio.h> |
6 | 6 | ||
7 | int cpumap[MAX_NR_CPUS]; | 7 | static struct cpu_map *cpu_map__default_new(void) |
8 | |||
9 | static int default_cpu_map(void) | ||
10 | { | 8 | { |
11 | int nr_cpus, i; | 9 | struct cpu_map *cpus; |
10 | int nr_cpus; | ||
12 | 11 | ||
13 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | 12 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); |
14 | assert(nr_cpus <= MAX_NR_CPUS); | 13 | if (nr_cpus < 0) |
15 | assert((int)nr_cpus >= 0); | 14 | return NULL; |
15 | |||
16 | cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int)); | ||
17 | if (cpus != NULL) { | ||
18 | int i; | ||
19 | for (i = 0; i < nr_cpus; ++i) | ||
20 | cpus->map[i] = i; | ||
16 | 21 | ||
17 | for (i = 0; i < nr_cpus; ++i) | 22 | cpus->nr = nr_cpus; |
18 | cpumap[i] = i; | 23 | } |
19 | 24 | ||
20 | return nr_cpus; | 25 | return cpus; |
21 | } | 26 | } |
22 | 27 | ||
23 | static int read_all_cpu_map(void) | 28 | static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) |
24 | { | 29 | { |
30 | size_t payload_size = nr_cpus * sizeof(int); | ||
31 | struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size); | ||
32 | |||
33 | if (cpus != NULL) { | ||
34 | cpus->nr = nr_cpus; | ||
35 | memcpy(cpus->map, tmp_cpus, payload_size); | ||
36 | } | ||
37 | |||
38 | return cpus; | ||
39 | } | ||
40 | |||
41 | static struct cpu_map *cpu_map__read_all_cpu_map(void) | ||
42 | { | ||
43 | struct cpu_map *cpus = NULL; | ||
25 | FILE *onlnf; | 44 | FILE *onlnf; |
26 | int nr_cpus = 0; | 45 | int nr_cpus = 0; |
46 | int *tmp_cpus = NULL, *tmp; | ||
47 | int max_entries = 0; | ||
27 | int n, cpu, prev; | 48 | int n, cpu, prev; |
28 | char sep; | 49 | char sep; |
29 | 50 | ||
30 | onlnf = fopen("/sys/devices/system/cpu/online", "r"); | 51 | onlnf = fopen("/sys/devices/system/cpu/online", "r"); |
31 | if (!onlnf) | 52 | if (!onlnf) |
32 | return default_cpu_map(); | 53 | return cpu_map__default_new(); |
33 | 54 | ||
34 | sep = 0; | 55 | sep = 0; |
35 | prev = -1; | 56 | prev = -1; |
@@ -38,12 +59,28 @@ static int read_all_cpu_map(void) | |||
38 | if (n <= 0) | 59 | if (n <= 0) |
39 | break; | 60 | break; |
40 | if (prev >= 0) { | 61 | if (prev >= 0) { |
41 | assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS); | 62 | int new_max = nr_cpus + cpu - prev - 1; |
63 | |||
64 | if (new_max >= max_entries) { | ||
65 | max_entries = new_max + MAX_NR_CPUS / 2; | ||
66 | tmp = realloc(tmp_cpus, max_entries * sizeof(int)); | ||
67 | if (tmp == NULL) | ||
68 | goto out_free_tmp; | ||
69 | tmp_cpus = tmp; | ||
70 | } | ||
71 | |||
42 | while (++prev < cpu) | 72 | while (++prev < cpu) |
43 | cpumap[nr_cpus++] = prev; | 73 | tmp_cpus[nr_cpus++] = prev; |
74 | } | ||
75 | if (nr_cpus == max_entries) { | ||
76 | max_entries += MAX_NR_CPUS; | ||
77 | tmp = realloc(tmp_cpus, max_entries * sizeof(int)); | ||
78 | if (tmp == NULL) | ||
79 | goto out_free_tmp; | ||
80 | tmp_cpus = tmp; | ||
44 | } | 81 | } |
45 | assert (nr_cpus < MAX_NR_CPUS); | 82 | |
46 | cpumap[nr_cpus++] = cpu; | 83 | tmp_cpus[nr_cpus++] = cpu; |
47 | if (n == 2 && sep == '-') | 84 | if (n == 2 && sep == '-') |
48 | prev = cpu; | 85 | prev = cpu; |
49 | else | 86 | else |
@@ -51,24 +88,31 @@ static int read_all_cpu_map(void) | |||
51 | if (n == 1 || sep == '\n') | 88 | if (n == 1 || sep == '\n') |
52 | break; | 89 | break; |
53 | } | 90 | } |
54 | fclose(onlnf); | ||
55 | if (nr_cpus > 0) | ||
56 | return nr_cpus; | ||
57 | 91 | ||
58 | return default_cpu_map(); | 92 | if (nr_cpus > 0) |
93 | cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); | ||
94 | else | ||
95 | cpus = cpu_map__default_new(); | ||
96 | out_free_tmp: | ||
97 | free(tmp_cpus); | ||
98 | fclose(onlnf); | ||
99 | return cpus; | ||
59 | } | 100 | } |
60 | 101 | ||
61 | int read_cpu_map(const char *cpu_list) | 102 | struct cpu_map *cpu_map__new(const char *cpu_list) |
62 | { | 103 | { |
104 | struct cpu_map *cpus = NULL; | ||
63 | unsigned long start_cpu, end_cpu = 0; | 105 | unsigned long start_cpu, end_cpu = 0; |
64 | char *p = NULL; | 106 | char *p = NULL; |
65 | int i, nr_cpus = 0; | 107 | int i, nr_cpus = 0; |
108 | int *tmp_cpus = NULL, *tmp; | ||
109 | int max_entries = 0; | ||
66 | 110 | ||
67 | if (!cpu_list) | 111 | if (!cpu_list) |
68 | return read_all_cpu_map(); | 112 | return cpu_map__read_all_cpu_map(); |
69 | 113 | ||
70 | if (!isdigit(*cpu_list)) | 114 | if (!isdigit(*cpu_list)) |
71 | goto invalid; | 115 | goto out; |
72 | 116 | ||
73 | while (isdigit(*cpu_list)) { | 117 | while (isdigit(*cpu_list)) { |
74 | p = NULL; | 118 | p = NULL; |
@@ -94,21 +138,42 @@ int read_cpu_map(const char *cpu_list) | |||
94 | for (; start_cpu <= end_cpu; start_cpu++) { | 138 | for (; start_cpu <= end_cpu; start_cpu++) { |
95 | /* check for duplicates */ | 139 | /* check for duplicates */ |
96 | for (i = 0; i < nr_cpus; i++) | 140 | for (i = 0; i < nr_cpus; i++) |
97 | if (cpumap[i] == (int)start_cpu) | 141 | if (tmp_cpus[i] == (int)start_cpu) |
98 | goto invalid; | 142 | goto invalid; |
99 | 143 | ||
100 | assert(nr_cpus < MAX_NR_CPUS); | 144 | if (nr_cpus == max_entries) { |
101 | cpumap[nr_cpus++] = (int)start_cpu; | 145 | max_entries += MAX_NR_CPUS; |
146 | tmp = realloc(tmp_cpus, max_entries * sizeof(int)); | ||
147 | if (tmp == NULL) | ||
148 | goto invalid; | ||
149 | tmp_cpus = tmp; | ||
150 | } | ||
151 | tmp_cpus[nr_cpus++] = (int)start_cpu; | ||
102 | } | 152 | } |
103 | if (*p) | 153 | if (*p) |
104 | ++p; | 154 | ++p; |
105 | 155 | ||
106 | cpu_list = p; | 156 | cpu_list = p; |
107 | } | 157 | } |
108 | if (nr_cpus > 0) | ||
109 | return nr_cpus; | ||
110 | 158 | ||
111 | return default_cpu_map(); | 159 | if (nr_cpus > 0) |
160 | cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); | ||
161 | else | ||
162 | cpus = cpu_map__default_new(); | ||
112 | invalid: | 163 | invalid: |
113 | return -1; | 164 | free(tmp_cpus); |
165 | out: | ||
166 | return cpus; | ||
167 | } | ||
168 | |||
169 | struct cpu_map *cpu_map__dummy_new(void) | ||
170 | { | ||
171 | struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); | ||
172 | |||
173 | if (cpus != NULL) { | ||
174 | cpus->nr = 1; | ||
175 | cpus->map[0] = -1; | ||
176 | } | ||
177 | |||
178 | return cpus; | ||
114 | } | 179 | } |
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 3e60f56e490..f7a4f42f630 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h | |||
@@ -1,7 +1,13 @@ | |||
1 | #ifndef __PERF_CPUMAP_H | 1 | #ifndef __PERF_CPUMAP_H |
2 | #define __PERF_CPUMAP_H | 2 | #define __PERF_CPUMAP_H |
3 | 3 | ||
4 | extern int read_cpu_map(const char *cpu_list); | 4 | struct cpu_map { |
5 | extern int cpumap[]; | 5 | int nr; |
6 | int map[]; | ||
7 | }; | ||
8 | |||
9 | struct cpu_map *cpu_map__new(const char *cpu_list); | ||
10 | struct cpu_map *cpu_map__dummy_new(void); | ||
11 | void *cpu_map__delete(struct cpu_map *map); | ||
6 | 12 | ||
7 | #endif /* __PERF_CPUMAP_H */ | 13 | #endif /* __PERF_CPUMAP_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c new file mode 100644 index 00000000000..c95267e63c5 --- /dev/null +++ b/tools/perf/util/evsel.c | |||
@@ -0,0 +1,186 @@ | |||
1 | #include "evsel.h" | ||
2 | #include "../perf.h" | ||
3 | #include "util.h" | ||
4 | #include "cpumap.h" | ||
5 | #include "thread.h" | ||
6 | |||
7 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | ||
8 | |||
9 | struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx) | ||
10 | { | ||
11 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); | ||
12 | |||
13 | if (evsel != NULL) { | ||
14 | evsel->idx = idx; | ||
15 | evsel->attr.type = type; | ||
16 | evsel->attr.config = config; | ||
17 | INIT_LIST_HEAD(&evsel->node); | ||
18 | } | ||
19 | |||
20 | return evsel; | ||
21 | } | ||
22 | |||
23 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | ||
24 | { | ||
25 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); | ||
26 | return evsel->fd != NULL ? 0 : -ENOMEM; | ||
27 | } | ||
28 | |||
29 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) | ||
30 | { | ||
31 | evsel->counts = zalloc((sizeof(*evsel->counts) + | ||
32 | (ncpus * sizeof(struct perf_counts_values)))); | ||
33 | return evsel->counts != NULL ? 0 : -ENOMEM; | ||
34 | } | ||
35 | |||
36 | void perf_evsel__free_fd(struct perf_evsel *evsel) | ||
37 | { | ||
38 | xyarray__delete(evsel->fd); | ||
39 | evsel->fd = NULL; | ||
40 | } | ||
41 | |||
42 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | ||
43 | { | ||
44 | int cpu, thread; | ||
45 | |||
46 | for (cpu = 0; cpu < ncpus; cpu++) | ||
47 | for (thread = 0; thread < nthreads; ++thread) { | ||
48 | close(FD(evsel, cpu, thread)); | ||
49 | FD(evsel, cpu, thread) = -1; | ||
50 | } | ||
51 | } | ||
52 | |||
53 | void perf_evsel__delete(struct perf_evsel *evsel) | ||
54 | { | ||
55 | assert(list_empty(&evsel->node)); | ||
56 | xyarray__delete(evsel->fd); | ||
57 | free(evsel); | ||
58 | } | ||
59 | |||
60 | int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, | ||
61 | int cpu, int thread, bool scale) | ||
62 | { | ||
63 | struct perf_counts_values count; | ||
64 | size_t nv = scale ? 3 : 1; | ||
65 | |||
66 | if (FD(evsel, cpu, thread) < 0) | ||
67 | return -EINVAL; | ||
68 | |||
69 | if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0) | ||
70 | return -ENOMEM; | ||
71 | |||
72 | if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) | ||
73 | return -errno; | ||
74 | |||
75 | if (scale) { | ||
76 | if (count.run == 0) | ||
77 | count.val = 0; | ||
78 | else if (count.run < count.ena) | ||
79 | count.val = (u64)((double)count.val * count.ena / count.run + 0.5); | ||
80 | } else | ||
81 | count.ena = count.run = 0; | ||
82 | |||
83 | evsel->counts->cpu[cpu] = count; | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | int __perf_evsel__read(struct perf_evsel *evsel, | ||
88 | int ncpus, int nthreads, bool scale) | ||
89 | { | ||
90 | size_t nv = scale ? 3 : 1; | ||
91 | int cpu, thread; | ||
92 | struct perf_counts_values *aggr = &evsel->counts->aggr, count; | ||
93 | |||
94 | aggr->val = 0; | ||
95 | |||
96 | for (cpu = 0; cpu < ncpus; cpu++) { | ||
97 | for (thread = 0; thread < nthreads; thread++) { | ||
98 | if (FD(evsel, cpu, thread) < 0) | ||
99 | continue; | ||
100 | |||
101 | if (readn(FD(evsel, cpu, thread), | ||
102 | &count, nv * sizeof(u64)) < 0) | ||
103 | return -errno; | ||
104 | |||
105 | aggr->val += count.val; | ||
106 | if (scale) { | ||
107 | aggr->ena += count.ena; | ||
108 | aggr->run += count.run; | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | evsel->counts->scaled = 0; | ||
114 | if (scale) { | ||
115 | if (aggr->run == 0) { | ||
116 | evsel->counts->scaled = -1; | ||
117 | aggr->val = 0; | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | if (aggr->run < aggr->ena) { | ||
122 | evsel->counts->scaled = 1; | ||
123 | aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5); | ||
124 | } | ||
125 | } else | ||
126 | aggr->ena = aggr->run = 0; | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus) | ||
132 | { | ||
133 | int cpu; | ||
134 | |||
135 | if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, cpus->nr, 1) < 0) | ||
136 | return -1; | ||
137 | |||
138 | for (cpu = 0; cpu < cpus->nr; cpu++) { | ||
139 | FD(evsel, cpu, 0) = sys_perf_event_open(&evsel->attr, -1, | ||
140 | cpus->map[cpu], -1, 0); | ||
141 | if (FD(evsel, cpu, 0) < 0) | ||
142 | goto out_close; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | |||
147 | out_close: | ||
148 | while (--cpu >= 0) { | ||
149 | close(FD(evsel, cpu, 0)); | ||
150 | FD(evsel, cpu, 0) = -1; | ||
151 | } | ||
152 | return -1; | ||
153 | } | ||
154 | |||
155 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads) | ||
156 | { | ||
157 | int thread; | ||
158 | |||
159 | if (evsel->fd == NULL && perf_evsel__alloc_fd(evsel, 1, threads->nr)) | ||
160 | return -1; | ||
161 | |||
162 | for (thread = 0; thread < threads->nr; thread++) { | ||
163 | FD(evsel, 0, thread) = sys_perf_event_open(&evsel->attr, | ||
164 | threads->map[thread], -1, -1, 0); | ||
165 | if (FD(evsel, 0, thread) < 0) | ||
166 | goto out_close; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | |||
171 | out_close: | ||
172 | while (--thread >= 0) { | ||
173 | close(FD(evsel, 0, thread)); | ||
174 | FD(evsel, 0, thread) = -1; | ||
175 | } | ||
176 | return -1; | ||
177 | } | ||
178 | |||
179 | int perf_evsel__open(struct perf_evsel *evsel, | ||
180 | struct cpu_map *cpus, struct thread_map *threads) | ||
181 | { | ||
182 | if (threads == NULL) | ||
183 | return perf_evsel__open_per_cpu(evsel, cpus); | ||
184 | |||
185 | return perf_evsel__open_per_thread(evsel, threads); | ||
186 | } | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h new file mode 100644 index 00000000000..863d78d5ef1 --- /dev/null +++ b/tools/perf/util/evsel.h | |||
@@ -0,0 +1,115 @@ | |||
1 | #ifndef __PERF_EVSEL_H | ||
2 | #define __PERF_EVSEL_H 1 | ||
3 | |||
4 | #include <linux/list.h> | ||
5 | #include <stdbool.h> | ||
6 | #include <linux/perf_event.h> | ||
7 | #include "types.h" | ||
8 | #include "xyarray.h" | ||
9 | |||
10 | struct perf_counts_values { | ||
11 | union { | ||
12 | struct { | ||
13 | u64 val; | ||
14 | u64 ena; | ||
15 | u64 run; | ||
16 | }; | ||
17 | u64 values[3]; | ||
18 | }; | ||
19 | }; | ||
20 | |||
21 | struct perf_counts { | ||
22 | s8 scaled; | ||
23 | struct perf_counts_values aggr; | ||
24 | struct perf_counts_values cpu[]; | ||
25 | }; | ||
26 | |||
27 | struct perf_evsel { | ||
28 | struct list_head node; | ||
29 | struct perf_event_attr attr; | ||
30 | char *filter; | ||
31 | struct xyarray *fd; | ||
32 | struct perf_counts *counts; | ||
33 | int idx; | ||
34 | void *priv; | ||
35 | }; | ||
36 | |||
37 | struct cpu_map; | ||
38 | struct thread_map; | ||
39 | |||
40 | struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx); | ||
41 | void perf_evsel__delete(struct perf_evsel *evsel); | ||
42 | |||
43 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | ||
44 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); | ||
45 | void perf_evsel__free_fd(struct perf_evsel *evsel); | ||
46 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | ||
47 | |||
48 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus); | ||
49 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads); | ||
50 | int perf_evsel__open(struct perf_evsel *evsel, | ||
51 | struct cpu_map *cpus, struct thread_map *threads); | ||
52 | |||
53 | #define perf_evsel__match(evsel, t, c) \ | ||
54 | (evsel->attr.type == PERF_TYPE_##t && \ | ||
55 | evsel->attr.config == PERF_COUNT_##c) | ||
56 | |||
57 | int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, | ||
58 | int cpu, int thread, bool scale); | ||
59 | |||
60 | /** | ||
61 | * perf_evsel__read_on_cpu - Read out the results on a CPU and thread | ||
62 | * | ||
63 | * @evsel - event selector to read value | ||
64 | * @cpu - CPU of interest | ||
65 | * @thread - thread of interest | ||
66 | */ | ||
67 | static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel, | ||
68 | int cpu, int thread) | ||
69 | { | ||
70 | return __perf_evsel__read_on_cpu(evsel, cpu, thread, false); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * perf_evsel__read_on_cpu_scaled - Read out the results on a CPU and thread, scaled | ||
75 | * | ||
76 | * @evsel - event selector to read value | ||
77 | * @cpu - CPU of interest | ||
78 | * @thread - thread of interest | ||
79 | */ | ||
80 | static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel, | ||
81 | int cpu, int thread) | ||
82 | { | ||
83 | return __perf_evsel__read_on_cpu(evsel, cpu, thread, true); | ||
84 | } | ||
85 | |||
86 | int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads, | ||
87 | bool scale); | ||
88 | |||
89 | /** | ||
90 | * perf_evsel__read - Read the aggregate results on all CPUs | ||
91 | * | ||
92 | * @evsel - event selector to read value | ||
93 | * @ncpus - Number of cpus affected, from zero | ||
94 | * @nthreads - Number of threads affected, from zero | ||
95 | */ | ||
96 | static inline int perf_evsel__read(struct perf_evsel *evsel, | ||
97 | int ncpus, int nthreads) | ||
98 | { | ||
99 | return __perf_evsel__read(evsel, ncpus, nthreads, false); | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled | ||
104 | * | ||
105 | * @evsel - event selector to read value | ||
106 | * @ncpus - Number of cpus affected, from zero | ||
107 | * @nthreads - Number of threads affected, from zero | ||
108 | */ | ||
109 | static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, | ||
110 | int ncpus, int nthreads) | ||
111 | { | ||
112 | return __perf_evsel__read(evsel, ncpus, nthreads, true); | ||
113 | } | ||
114 | |||
115 | #endif /* __PERF_EVSEL_H */ | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4b8c8397a94..989fa2dee2f 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -463,7 +463,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) | |||
463 | 463 | ||
464 | /* Write trace info */ | 464 | /* Write trace info */ |
465 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); | 465 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); |
466 | read_tracing_data(fd, attrs, nr_counters); | 466 | read_tracing_data(fd, &evsel_list); |
467 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; | 467 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; |
468 | } | 468 | } |
469 | 469 | ||
@@ -606,7 +606,7 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
606 | static int perf_header__getbuffer64(struct perf_header *self, | 606 | static int perf_header__getbuffer64(struct perf_header *self, |
607 | int fd, void *buf, size_t size) | 607 | int fd, void *buf, size_t size) |
608 | { | 608 | { |
609 | if (do_read(fd, buf, size) <= 0) | 609 | if (readn(fd, buf, size) <= 0) |
610 | return -1; | 610 | return -1; |
611 | 611 | ||
612 | if (self->needs_swap) | 612 | if (self->needs_swap) |
@@ -662,7 +662,7 @@ int perf_file_header__read(struct perf_file_header *self, | |||
662 | { | 662 | { |
663 | lseek(fd, 0, SEEK_SET); | 663 | lseek(fd, 0, SEEK_SET); |
664 | 664 | ||
665 | if (do_read(fd, self, sizeof(*self)) <= 0 || | 665 | if (readn(fd, self, sizeof(*self)) <= 0 || |
666 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 666 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
667 | return -1; | 667 | return -1; |
668 | 668 | ||
@@ -823,7 +823,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, | |||
823 | struct perf_header *ph, int fd, | 823 | struct perf_header *ph, int fd, |
824 | bool repipe) | 824 | bool repipe) |
825 | { | 825 | { |
826 | if (do_read(fd, self, sizeof(*self)) <= 0 || | 826 | if (readn(fd, self, sizeof(*self)) <= 0 || |
827 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) | 827 | memcmp(&self->magic, __perf_magic, sizeof(self->magic))) |
828 | return -1; | 828 | return -1; |
829 | 829 | ||
@@ -1133,8 +1133,7 @@ int event__process_event_type(event_t *self, | |||
1133 | return 0; | 1133 | return 0; |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | 1136 | int event__synthesize_tracing_data(int fd, struct list_head *pattrs, |
1137 | int nb_events, | ||
1138 | event__handler_t process, | 1137 | event__handler_t process, |
1139 | struct perf_session *session __unused) | 1138 | struct perf_session *session __unused) |
1140 | { | 1139 | { |
@@ -1145,7 +1144,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | |||
1145 | memset(&ev, 0, sizeof(ev)); | 1144 | memset(&ev, 0, sizeof(ev)); |
1146 | 1145 | ||
1147 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; | 1146 | ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; |
1148 | size = read_tracing_data_size(fd, pattrs, nb_events); | 1147 | size = read_tracing_data_size(fd, pattrs); |
1149 | if (size <= 0) | 1148 | if (size <= 0) |
1150 | return size; | 1149 | return size; |
1151 | aligned_size = ALIGN(size, sizeof(u64)); | 1150 | aligned_size = ALIGN(size, sizeof(u64)); |
@@ -1155,7 +1154,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | |||
1155 | 1154 | ||
1156 | process(&ev, NULL, session); | 1155 | process(&ev, NULL, session); |
1157 | 1156 | ||
1158 | err = read_tracing_data(fd, pattrs, nb_events); | 1157 | err = read_tracing_data(fd, pattrs); |
1159 | write_padded(fd, NULL, 0, padding); | 1158 | write_padded(fd, NULL, 0, padding); |
1160 | 1159 | ||
1161 | return aligned_size; | 1160 | return aligned_size; |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 6335965e1f9..33f16be7b72 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 c305305a388..3a142e90d60 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,26 @@ 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 | } | ||
985 | |||
986 | void perf_evsel_list__delete(void) | ||
987 | { | ||
988 | struct perf_evsel *pos, *n; | ||
989 | |||
990 | list_for_each_entry_safe(pos, n, &evsel_list, node) { | ||
991 | list_del_init(&pos->node); | ||
992 | perf_evsel__delete(pos); | ||
993 | } | ||
994 | nr_counters = 0; | ||
995 | } | ||
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index fc4ab3fe877..0a0abc1d10e 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -4,6 +4,16 @@ | |||
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 | void perf_evsel_list__delete(void); | ||
16 | |||
7 | struct option; | 17 | struct option; |
8 | 18 | ||
9 | struct tracepoint_path { | 19 | struct tracepoint_path { |
@@ -13,14 +23,11 @@ struct tracepoint_path { | |||
13 | }; | 23 | }; |
14 | 24 | ||
15 | extern struct tracepoint_path *tracepoint_id_to_path(u64 config); | 25 | extern struct tracepoint_path *tracepoint_id_to_path(u64 config); |
16 | extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events); | 26 | extern bool have_tracepoints(struct list_head *evsel_list); |
17 | 27 | ||
18 | extern int nr_counters; | 28 | extern int nr_counters; |
19 | 29 | ||
20 | extern struct perf_event_attr attrs[MAX_COUNTERS]; | 30 | 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); | 31 | extern const char *__event_name(int type, u64 config); |
25 | 32 | ||
26 | extern int parse_events(const struct option *opt, const char *str, int unset); | 33 | extern int parse_events(const struct option *opt, const char *str, int unset); |
@@ -33,5 +40,4 @@ extern void print_events(void); | |||
33 | extern char debugfs_path[]; | 40 | extern char debugfs_path[]; |
34 | extern int valid_debugfs_mount(const char *debugfs); | 41 | extern int valid_debugfs_mount(const char *debugfs); |
35 | 42 | ||
36 | |||
37 | #endif /* __PERF_PARSE_EVENTS_H */ | 43 | #endif /* __PERF_PARSE_EVENTS_H */ |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0f7e544544f..b163dfd6cbc 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -838,23 +838,6 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se | |||
838 | return thread; | 838 | return thread; |
839 | } | 839 | } |
840 | 840 | ||
841 | int do_read(int fd, void *buf, size_t size) | ||
842 | { | ||
843 | void *buf_start = buf; | ||
844 | |||
845 | while (size) { | ||
846 | int ret = read(fd, buf, size); | ||
847 | |||
848 | if (ret <= 0) | ||
849 | return ret; | ||
850 | |||
851 | size -= ret; | ||
852 | buf += ret; | ||
853 | } | ||
854 | |||
855 | return buf - buf_start; | ||
856 | } | ||
857 | |||
858 | #define session_done() (*(volatile int *)(&session_done)) | 841 | #define session_done() (*(volatile int *)(&session_done)) |
859 | volatile int session_done; | 842 | volatile int session_done; |
860 | 843 | ||
@@ -872,7 +855,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self, | |||
872 | 855 | ||
873 | head = 0; | 856 | head = 0; |
874 | more: | 857 | more: |
875 | err = do_read(self->fd, &event, sizeof(struct perf_event_header)); | 858 | err = readn(self->fd, &event, sizeof(struct perf_event_header)); |
876 | if (err <= 0) { | 859 | if (err <= 0) { |
877 | if (err == 0) | 860 | if (err == 0) |
878 | goto done; | 861 | goto done; |
@@ -892,8 +875,7 @@ more: | |||
892 | p += sizeof(struct perf_event_header); | 875 | p += sizeof(struct perf_event_header); |
893 | 876 | ||
894 | if (size - sizeof(struct perf_event_header)) { | 877 | if (size - sizeof(struct perf_event_header)) { |
895 | err = do_read(self->fd, p, | 878 | err = readn(self->fd, p, size - sizeof(struct perf_event_header)); |
896 | size - sizeof(struct perf_event_header)); | ||
897 | if (err <= 0) { | 879 | if (err <= 0) { |
898 | if (err == 0) { | 880 | if (err == 0) { |
899 | pr_err("unexpected end of event stream\n"); | 881 | pr_err("unexpected end of event stream\n"); |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index ffe4b98db8f..decd83f274f 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -109,7 +109,6 @@ void mem_bswap_64(void *src, int byte_size); | |||
109 | 109 | ||
110 | int perf_session__create_kernel_maps(struct perf_session *self); | 110 | int perf_session__create_kernel_maps(struct perf_session *self); |
111 | 111 | ||
112 | int do_read(int fd, void *buf, size_t size); | ||
113 | void perf_session__update_sample_type(struct perf_session *self); | 112 | void perf_session__update_sample_type(struct perf_session *self); |
114 | void perf_session__set_sample_id_all(struct perf_session *session, bool value); | 113 | void perf_session__set_sample_id_all(struct perf_session *session, bool value); |
115 | void perf_session__set_sample_type(struct perf_session *session, u64 type); | 114 | void perf_session__set_sample_type(struct perf_session *session, u64 type); |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 8c72d888e44..00f4eade2e3 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -16,35 +16,50 @@ static int filter(const struct dirent *dir) | |||
16 | return 1; | 16 | return 1; |
17 | } | 17 | } |
18 | 18 | ||
19 | int find_all_tid(int pid, pid_t ** all_tid) | 19 | struct thread_map *thread_map__new_by_pid(pid_t pid) |
20 | { | 20 | { |
21 | struct thread_map *threads; | ||
21 | char name[256]; | 22 | char name[256]; |
22 | int items; | 23 | int items; |
23 | struct dirent **namelist = NULL; | 24 | struct dirent **namelist = NULL; |
24 | int ret = 0; | ||
25 | int i; | 25 | int i; |
26 | 26 | ||
27 | sprintf(name, "/proc/%d/task", pid); | 27 | sprintf(name, "/proc/%d/task", pid); |
28 | items = scandir(name, &namelist, filter, NULL); | 28 | items = scandir(name, &namelist, filter, NULL); |
29 | if (items <= 0) | 29 | if (items <= 0) |
30 | return -ENOENT; | 30 | return NULL; |
31 | *all_tid = malloc(sizeof(pid_t) * items); | ||
32 | if (!*all_tid) { | ||
33 | ret = -ENOMEM; | ||
34 | goto failure; | ||
35 | } | ||
36 | |||
37 | for (i = 0; i < items; i++) | ||
38 | (*all_tid)[i] = atoi(namelist[i]->d_name); | ||
39 | 31 | ||
40 | ret = items; | 32 | threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); |
33 | if (threads != NULL) { | ||
34 | for (i = 0; i < items; i++) | ||
35 | threads->map[i] = atoi(namelist[i]->d_name); | ||
36 | threads->nr = items; | ||
37 | } | ||
41 | 38 | ||
42 | failure: | ||
43 | for (i=0; i<items; i++) | 39 | for (i=0; i<items; i++) |
44 | free(namelist[i]); | 40 | free(namelist[i]); |
45 | free(namelist); | 41 | free(namelist); |
46 | 42 | ||
47 | return ret; | 43 | return threads; |
44 | } | ||
45 | |||
46 | struct thread_map *thread_map__new_by_tid(pid_t tid) | ||
47 | { | ||
48 | struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t)); | ||
49 | |||
50 | if (threads != NULL) { | ||
51 | threads->map[0] = tid; | ||
52 | threads->nr = 1; | ||
53 | } | ||
54 | |||
55 | return threads; | ||
56 | } | ||
57 | |||
58 | struct thread_map *thread_map__new(pid_t pid, pid_t tid) | ||
59 | { | ||
60 | if (pid != -1) | ||
61 | return thread_map__new_by_pid(pid); | ||
62 | return thread_map__new_by_tid(tid); | ||
48 | } | 63 | } |
49 | 64 | ||
50 | static struct thread *thread__new(pid_t pid) | 65 | static struct thread *thread__new(pid_t pid) |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 688500ff826..d7574101054 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -18,11 +18,24 @@ struct thread { | |||
18 | int comm_len; | 18 | int comm_len; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | struct thread_map { | ||
22 | int nr; | ||
23 | int map[]; | ||
24 | }; | ||
25 | |||
21 | struct perf_session; | 26 | struct perf_session; |
22 | 27 | ||
23 | void thread__delete(struct thread *self); | 28 | void thread__delete(struct thread *self); |
24 | 29 | ||
25 | int find_all_tid(int pid, pid_t ** all_tid); | 30 | struct thread_map *thread_map__new_by_pid(pid_t pid); |
31 | struct thread_map *thread_map__new_by_tid(pid_t tid); | ||
32 | struct thread_map *thread_map__new(pid_t pid, pid_t tid); | ||
33 | |||
34 | static inline void thread_map__delete(struct thread_map *threads) | ||
35 | { | ||
36 | free(threads); | ||
37 | } | ||
38 | |||
26 | int thread__set_comm(struct thread *self, const char *comm); | 39 | int thread__set_comm(struct thread *self, const char *comm); |
27 | int thread__comm_len(struct thread *self); | 40 | int thread__comm_len(struct thread *self); |
28 | struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); | 41 | struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); |
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index b1572601286..35729f4c40c 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 b3e86b1e444..b5f12ca24d9 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/util.c b/tools/perf/util/util.c index 214265674dd..5b3ea49aa63 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -114,3 +114,20 @@ unsigned long convert_unit(unsigned long value, char *unit) | |||
114 | 114 | ||
115 | return value; | 115 | return value; |
116 | } | 116 | } |
117 | |||
118 | int readn(int fd, void *buf, size_t n) | ||
119 | { | ||
120 | void *buf_start = buf; | ||
121 | |||
122 | while (n) { | ||
123 | int ret = read(fd, buf, n); | ||
124 | |||
125 | if (ret <= 0) | ||
126 | return ret; | ||
127 | |||
128 | n -= ret; | ||
129 | buf += ret; | ||
130 | } | ||
131 | |||
132 | return buf - buf_start; | ||
133 | } | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 7562707ddd1..e833f26f3bf 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -265,6 +265,7 @@ void argv_free(char **argv); | |||
265 | bool strglobmatch(const char *str, const char *pat); | 265 | bool strglobmatch(const char *str, const char *pat); |
266 | bool strlazymatch(const char *str, const char *pat); | 266 | bool strlazymatch(const char *str, const char *pat); |
267 | unsigned long convert_unit(unsigned long value, char *unit); | 267 | unsigned long convert_unit(unsigned long value, char *unit); |
268 | int readn(int fd, void *buf, size_t size); | ||
268 | 269 | ||
269 | #define _STR(x) #x | 270 | #define _STR(x) #x |
270 | #define STR(x) _STR(x) | 271 | #define STR(x) _STR(x) |
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c new file mode 100644 index 00000000000..22afbf6c536 --- /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 00000000000..c488a07275d --- /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_ */ | ||