7 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
9 struct perf_evsel
*perf_evsel__new(struct perf_event_attr
*attr
, int idx
)
11 struct perf_evsel
*evsel
= zalloc(sizeof(*evsel
));
16 INIT_LIST_HEAD(&evsel
->node
);
22 int perf_evsel__alloc_fd(struct perf_evsel
*evsel
, int ncpus
, int nthreads
)
24 evsel
->fd
= xyarray__new(ncpus
, nthreads
, sizeof(int));
25 return evsel
->fd
!= NULL
? 0 : -ENOMEM
;
28 int perf_evsel__alloc_counts(struct perf_evsel
*evsel
, int ncpus
)
30 evsel
->counts
= zalloc((sizeof(*evsel
->counts
) +
31 (ncpus
* sizeof(struct perf_counts_values
))));
32 return evsel
->counts
!= NULL
? 0 : -ENOMEM
;
35 void perf_evsel__free_fd(struct perf_evsel
*evsel
)
37 xyarray__delete(evsel
->fd
);
41 void perf_evsel__close_fd(struct perf_evsel
*evsel
, int ncpus
, int nthreads
)
45 for (cpu
= 0; cpu
< ncpus
; cpu
++)
46 for (thread
= 0; thread
< nthreads
; ++thread
) {
47 close(FD(evsel
, cpu
, thread
));
48 FD(evsel
, cpu
, thread
) = -1;
52 void perf_evsel__delete(struct perf_evsel
*evsel
)
54 assert(list_empty(&evsel
->node
));
55 xyarray__delete(evsel
->fd
);
59 int __perf_evsel__read_on_cpu(struct perf_evsel
*evsel
,
60 int cpu
, int thread
, bool scale
)
62 struct perf_counts_values count
;
63 size_t nv
= scale
? 3 : 1;
65 if (FD(evsel
, cpu
, thread
) < 0)
68 if (evsel
->counts
== NULL
&& perf_evsel__alloc_counts(evsel
, cpu
+ 1) < 0)
71 if (readn(FD(evsel
, cpu
, thread
), &count
, nv
* sizeof(u64
)) < 0)
77 else if (count
.run
< count
.ena
)
78 count
.val
= (u64
)((double)count
.val
* count
.ena
/ count
.run
+ 0.5);
80 count
.ena
= count
.run
= 0;
82 evsel
->counts
->cpu
[cpu
] = count
;
86 int __perf_evsel__read(struct perf_evsel
*evsel
,
87 int ncpus
, int nthreads
, bool scale
)
89 size_t nv
= scale
? 3 : 1;
91 struct perf_counts_values
*aggr
= &evsel
->counts
->aggr
, count
;
95 for (cpu
= 0; cpu
< ncpus
; cpu
++) {
96 for (thread
= 0; thread
< nthreads
; thread
++) {
97 if (FD(evsel
, cpu
, thread
) < 0)
100 if (readn(FD(evsel
, cpu
, thread
),
101 &count
, nv
* sizeof(u64
)) < 0)
104 aggr
->val
+= count
.val
;
106 aggr
->ena
+= count
.ena
;
107 aggr
->run
+= count
.run
;
112 evsel
->counts
->scaled
= 0;
114 if (aggr
->run
== 0) {
115 evsel
->counts
->scaled
= -1;
120 if (aggr
->run
< aggr
->ena
) {
121 evsel
->counts
->scaled
= 1;
122 aggr
->val
= (u64
)((double)aggr
->val
* aggr
->ena
/ aggr
->run
+ 0.5);
125 aggr
->ena
= aggr
->run
= 0;
130 static int __perf_evsel__open(struct perf_evsel
*evsel
, struct cpu_map
*cpus
,
131 struct thread_map
*threads
)
135 if (evsel
->fd
== NULL
&&
136 perf_evsel__alloc_fd(evsel
, cpus
->nr
, threads
->nr
) < 0)
139 for (cpu
= 0; cpu
< cpus
->nr
; cpu
++) {
140 for (thread
= 0; thread
< threads
->nr
; thread
++) {
141 FD(evsel
, cpu
, thread
) = sys_perf_event_open(&evsel
->attr
,
142 threads
->map
[thread
],
143 cpus
->map
[cpu
], -1, 0);
144 if (FD(evsel
, cpu
, thread
) < 0)
153 while (--thread
>= 0) {
154 close(FD(evsel
, cpu
, thread
));
155 FD(evsel
, cpu
, thread
) = -1;
157 thread
= threads
->nr
;
158 } while (--cpu
>= 0);
171 struct thread_map map
;
173 } empty_thread_map
= {
178 int perf_evsel__open(struct perf_evsel
*evsel
,
179 struct cpu_map
*cpus
, struct thread_map
*threads
)
183 /* Work around old compiler warnings about strict aliasing */
184 cpus
= &empty_cpu_map
.map
;
188 threads
= &empty_thread_map
.map
;
190 return __perf_evsel__open(evsel
, cpus
, threads
);
193 int perf_evsel__open_per_cpu(struct perf_evsel
*evsel
, struct cpu_map
*cpus
)
195 return __perf_evsel__open(evsel
, cpus
, &empty_thread_map
.map
);
198 int perf_evsel__open_per_thread(struct perf_evsel
*evsel
, struct thread_map
*threads
)
200 return __perf_evsel__open(evsel
, &empty_cpu_map
.map
, threads
);