blob: e62cc5e050abf9a2189b6f8f1880d79339cbfd93 [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"
4
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -02005#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
6
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02007struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx)
8{
9 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
10
11 if (evsel != NULL) {
12 evsel->idx = idx;
13 evsel->attr.type = type;
14 evsel->attr.config = config;
15 INIT_LIST_HEAD(&evsel->node);
16 }
17
18 return evsel;
19}
20
21int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
22{
23 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
24 return evsel->fd != NULL ? 0 : -ENOMEM;
25}
26
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -020027int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
28{
29 evsel->counts = zalloc((sizeof(*evsel->counts) +
30 (ncpus * sizeof(struct perf_counts_values))));
31 return evsel->counts != NULL ? 0 : -ENOMEM;
32}
33
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020034void perf_evsel__free_fd(struct perf_evsel *evsel)
35{
36 xyarray__delete(evsel->fd);
37 evsel->fd = NULL;
38}
39
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -020040void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
41{
42 int cpu, thread;
43
44 for (cpu = 0; cpu < ncpus; cpu++)
45 for (thread = 0; thread < nthreads; ++thread) {
46 close(FD(evsel, cpu, thread));
47 FD(evsel, cpu, thread) = -1;
48 }
49}
50
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -020051void perf_evsel__delete(struct perf_evsel *evsel)
52{
53 assert(list_empty(&evsel->node));
54 xyarray__delete(evsel->fd);
55 free(evsel);
56}
Arnaldo Carvalho de Meloc52b12e2011-01-03 17:45:52 -020057
58int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
59 int cpu, int thread, bool scale)
60{
61 struct perf_counts_values count;
62 size_t nv = scale ? 3 : 1;
63
64 if (FD(evsel, cpu, thread) < 0)
65 return -EINVAL;
66
67 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
68 return -errno;
69
70 if (scale) {
71 if (count.run == 0)
72 count.val = 0;
73 else if (count.run < count.ena)
74 count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
75 } else
76 count.ena = count.run = 0;
77
78 evsel->counts->cpu[cpu] = count;
79 return 0;
80}
81
82int __perf_evsel__read(struct perf_evsel *evsel,
83 int ncpus, int nthreads, bool scale)
84{
85 size_t nv = scale ? 3 : 1;
86 int cpu, thread;
87 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
88
89 aggr->val = 0;
90
91 for (cpu = 0; cpu < ncpus; cpu++) {
92 for (thread = 0; thread < nthreads; thread++) {
93 if (FD(evsel, cpu, thread) < 0)
94 continue;
95
96 if (readn(FD(evsel, cpu, thread),
97 &count, nv * sizeof(u64)) < 0)
98 return -errno;
99
100 aggr->val += count.val;
101 if (scale) {
102 aggr->ena += count.ena;
103 aggr->run += count.run;
104 }
105 }
106 }
107
108 evsel->counts->scaled = 0;
109 if (scale) {
110 if (aggr->run == 0) {
111 evsel->counts->scaled = -1;
112 aggr->val = 0;
113 return 0;
114 }
115
116 if (aggr->run < aggr->ena) {
117 evsel->counts->scaled = 1;
118 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
119 }
120 } else
121 aggr->ena = aggr->run = 0;
122
123 return 0;
124}
Arnaldo Carvalho de Melo48290602011-01-03 17:48:12 -0200125
126int perf_evsel__open_per_cpu(struct perf_evsel *evsel, int ncpus, int *cpu_map)
127{
128 int cpu;
129
130 for (cpu = 0; cpu < ncpus; cpu++) {
131 FD(evsel, cpu, 0) = sys_perf_event_open(&evsel->attr, -1,
132 cpu_map[cpu], -1, 0);
133 if (FD(evsel, cpu, 0) < 0)
134 goto out_close;
135 }
136
137 return 0;
138
139out_close:
140 while (--cpu >= 0) {
141 close(FD(evsel, cpu, 0));
142 FD(evsel, cpu, 0) = -1;
143 }
144 return -1;
145}
146
147int perf_evsel__open_per_thread(struct perf_evsel *evsel, int nthreads, int *thread_map)
148{
149 int thread;
150
151 for (thread = 0; thread < nthreads; thread++) {
152 FD(evsel, 0, thread) = sys_perf_event_open(&evsel->attr,
153 thread_map[thread], -1, -1, 0);
154 if (FD(evsel, 0, thread) < 0)
155 goto out_close;
156 }
157
158 return 0;
159
160out_close:
161 while (--thread >= 0) {
162 close(FD(evsel, 0, thread));
163 FD(evsel, 0, thread) = -1;
164 }
165 return -1;
166}
167
168int perf_evsel__open(struct perf_evsel *evsel, int ncpus, int nthreads,
169 int *cpu_map, int *thread_map)
170{
171 if (nthreads < 0)
172 return perf_evsel__open_per_cpu(evsel, ncpus, cpu_map);
173
174 return perf_evsel__open_per_thread(evsel, nthreads, thread_map);
175}