blob: e44be528c09fe8f25b592b6d711267477ce31d4d [file] [log] [blame]
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02001#include "evsel.h"
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -02002#include "../perf.h"
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02003#include "util.h"
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -02004#include "cpumap.h"
5#include "thread.h"
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02006
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -02007#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
8
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02009struct 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
23int 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
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -020029int 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
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020036void perf_evsel__free_fd(struct perf_evsel *evsel)
37{
38 xyarray__delete(evsel->fd);
39 evsel->fd = NULL;
40}
41
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -020042void 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
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020053void perf_evsel__delete(struct perf_evsel *evsel)
54{
55 assert(list_empty(&evsel->node));
56 xyarray__delete(evsel->fd);
57 free(evsel);
58}
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -020059
60int __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 (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
70 return -errno;
71
72 if (scale) {
73 if (count.run == 0)
74 count.val = 0;
75 else if (count.run < count.ena)
76 count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
77 } else
78 count.ena = count.run = 0;
79
80 evsel->counts->cpu[cpu] = count;
81 return 0;
82}
83
84int __perf_evsel__read(struct perf_evsel *evsel,
85 int ncpus, int nthreads, bool scale)
86{
87 size_t nv = scale ? 3 : 1;
88 int cpu, thread;
89 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
90
91 aggr->val = 0;
92
93 for (cpu = 0; cpu < ncpus; cpu++) {
94 for (thread = 0; thread < nthreads; thread++) {
95 if (FD(evsel, cpu, thread) < 0)
96 continue;
97
98 if (readn(FD(evsel, cpu, thread),
99 &count, nv * sizeof(u64)) < 0)
100 return -errno;
101
102 aggr->val += count.val;
103 if (scale) {
104 aggr->ena += count.ena;
105 aggr->run += count.run;
106 }
107 }
108 }
109
110 evsel->counts->scaled = 0;
111 if (scale) {
112 if (aggr->run == 0) {
113 evsel->counts->scaled = -1;
114 aggr->val = 0;
115 return 0;
116 }
117
118 if (aggr->run < aggr->ena) {
119 evsel->counts->scaled = 1;
120 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
121 }
122 } else
123 aggr->ena = aggr->run = 0;
124
125 return 0;
126}
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200127
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200128int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus)
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200129{
130 int cpu;
131
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200132 for (cpu = 0; cpu < cpus->nr; cpu++) {
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200133 FD(evsel, cpu, 0) = sys_perf_event_open(&evsel->attr, -1,
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200134 cpus->map[cpu], -1, 0);
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200135 if (FD(evsel, cpu, 0) < 0)
136 goto out_close;
137 }
138
139 return 0;
140
141out_close:
142 while (--cpu >= 0) {
143 close(FD(evsel, cpu, 0));
144 FD(evsel, cpu, 0) = -1;
145 }
146 return -1;
147}
148
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200149int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads)
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200150{
151 int thread;
152
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200153 for (thread = 0; thread < threads->nr; thread++) {
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200154 FD(evsel, 0, thread) = sys_perf_event_open(&evsel->attr,
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200155 threads->map[thread], -1, -1, 0);
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200156 if (FD(evsel, 0, thread) < 0)
157 goto out_close;
158 }
159
160 return 0;
161
162out_close:
163 while (--thread >= 0) {
164 close(FD(evsel, 0, thread));
165 FD(evsel, 0, thread) = -1;
166 }
167 return -1;
168}
169
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200170int perf_evsel__open(struct perf_evsel *evsel,
171 struct cpu_map *cpus, struct thread_map *threads)
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200172{
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200173 if (threads == NULL)
174 return perf_evsel__open_per_cpu(evsel, cpus);
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200175
Arnaldo Carvalho de Melo86bd5e82011-01-03 23:09:46 -0200176 return perf_evsel__open_per_thread(evsel, threads);
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200177}