Commit | Line | Data |
---|---|---|
69aad6f1 ACM |
1 | #include "evsel.h" |
2 | #include "util.h" | |
3 | ||
c52b12ed ACM |
4 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
5 | ||
69aad6f1 ACM |
6 | struct perf_evsel *perf_evsel__new(u32 type, u64 config, int idx) |
7 | { | |
8 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); | |
9 | ||
10 | if (evsel != NULL) { | |
11 | evsel->idx = idx; | |
12 | evsel->attr.type = type; | |
13 | evsel->attr.config = config; | |
14 | INIT_LIST_HEAD(&evsel->node); | |
15 | } | |
16 | ||
17 | return evsel; | |
18 | } | |
19 | ||
20 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | |
21 | { | |
22 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); | |
23 | return evsel->fd != NULL ? 0 : -ENOMEM; | |
24 | } | |
25 | ||
c52b12ed ACM |
26 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) |
27 | { | |
28 | evsel->counts = zalloc((sizeof(*evsel->counts) + | |
29 | (ncpus * sizeof(struct perf_counts_values)))); | |
30 | return evsel->counts != NULL ? 0 : -ENOMEM; | |
31 | } | |
32 | ||
69aad6f1 ACM |
33 | void perf_evsel__free_fd(struct perf_evsel *evsel) |
34 | { | |
35 | xyarray__delete(evsel->fd); | |
36 | evsel->fd = NULL; | |
37 | } | |
38 | ||
c52b12ed ACM |
39 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
40 | { | |
41 | int cpu, thread; | |
42 | ||
43 | for (cpu = 0; cpu < ncpus; cpu++) | |
44 | for (thread = 0; thread < nthreads; ++thread) { | |
45 | close(FD(evsel, cpu, thread)); | |
46 | FD(evsel, cpu, thread) = -1; | |
47 | } | |
48 | } | |
49 | ||
69aad6f1 ACM |
50 | void perf_evsel__delete(struct perf_evsel *evsel) |
51 | { | |
52 | assert(list_empty(&evsel->node)); | |
53 | xyarray__delete(evsel->fd); | |
54 | free(evsel); | |
55 | } | |
c52b12ed ACM |
56 | |
57 | int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, | |
58 | int cpu, int thread, bool scale) | |
59 | { | |
60 | struct perf_counts_values count; | |
61 | size_t nv = scale ? 3 : 1; | |
62 | ||
63 | if (FD(evsel, cpu, thread) < 0) | |
64 | return -EINVAL; | |
65 | ||
66 | if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) | |
67 | return -errno; | |
68 | ||
69 | if (scale) { | |
70 | if (count.run == 0) | |
71 | count.val = 0; | |
72 | else if (count.run < count.ena) | |
73 | count.val = (u64)((double)count.val * count.ena / count.run + 0.5); | |
74 | } else | |
75 | count.ena = count.run = 0; | |
76 | ||
77 | evsel->counts->cpu[cpu] = count; | |
78 | return 0; | |
79 | } | |
80 | ||
81 | int __perf_evsel__read(struct perf_evsel *evsel, | |
82 | int ncpus, int nthreads, bool scale) | |
83 | { | |
84 | size_t nv = scale ? 3 : 1; | |
85 | int cpu, thread; | |
86 | struct perf_counts_values *aggr = &evsel->counts->aggr, count; | |
87 | ||
88 | aggr->val = 0; | |
89 | ||
90 | for (cpu = 0; cpu < ncpus; cpu++) { | |
91 | for (thread = 0; thread < nthreads; thread++) { | |
92 | if (FD(evsel, cpu, thread) < 0) | |
93 | continue; | |
94 | ||
95 | if (readn(FD(evsel, cpu, thread), | |
96 | &count, nv * sizeof(u64)) < 0) | |
97 | return -errno; | |
98 | ||
99 | aggr->val += count.val; | |
100 | if (scale) { | |
101 | aggr->ena += count.ena; | |
102 | aggr->run += count.run; | |
103 | } | |
104 | } | |
105 | } | |
106 | ||
107 | evsel->counts->scaled = 0; | |
108 | if (scale) { | |
109 | if (aggr->run == 0) { | |
110 | evsel->counts->scaled = -1; | |
111 | aggr->val = 0; | |
112 | return 0; | |
113 | } | |
114 | ||
115 | if (aggr->run < aggr->ena) { | |
116 | evsel->counts->scaled = 1; | |
117 | aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5); | |
118 | } | |
119 | } else | |
120 | aggr->ena = aggr->run = 0; | |
121 | ||
122 | return 0; | |
123 | } |