|
@@ -16,6 +16,7 @@
|
|
|
#include "thread_map.h"
|
|
|
|
|
|
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
|
|
+#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
|
|
|
|
|
|
int __perf_evsel__sample_size(u64 sample_type)
|
|
|
{
|
|
@@ -204,15 +205,16 @@ int __perf_evsel__read(struct perf_evsel *evsel,
|
|
|
}
|
|
|
|
|
|
static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
|
|
- struct thread_map *threads, bool group)
|
|
|
+ struct thread_map *threads, bool group,
|
|
|
+ struct xyarray *group_fds)
|
|
|
{
|
|
|
int cpu, thread;
|
|
|
unsigned long flags = 0;
|
|
|
- int pid = -1;
|
|
|
+ int pid = -1, err;
|
|
|
|
|
|
if (evsel->fd == NULL &&
|
|
|
perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
|
|
|
- return -1;
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
if (evsel->cgrp) {
|
|
|
flags = PERF_FLAG_PID_CGROUP;
|
|
@@ -220,7 +222,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
|
|
}
|
|
|
|
|
|
for (cpu = 0; cpu < cpus->nr; cpu++) {
|
|
|
- int group_fd = -1;
|
|
|
+ int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
|
|
|
|
|
|
for (thread = 0; thread < threads->nr; thread++) {
|
|
|
|
|
@@ -231,8 +233,10 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
|
|
pid,
|
|
|
cpus->map[cpu],
|
|
|
group_fd, flags);
|
|
|
- if (FD(evsel, cpu, thread) < 0)
|
|
|
+ if (FD(evsel, cpu, thread) < 0) {
|
|
|
+ err = -errno;
|
|
|
goto out_close;
|
|
|
+ }
|
|
|
|
|
|
if (group && group_fd == -1)
|
|
|
group_fd = FD(evsel, cpu, thread);
|
|
@@ -249,7 +253,17 @@ out_close:
|
|
|
}
|
|
|
thread = threads->nr;
|
|
|
} while (--cpu >= 0);
|
|
|
- return -1;
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
|
|
|
+{
|
|
|
+ if (evsel->fd == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ perf_evsel__close_fd(evsel, ncpus, nthreads);
|
|
|
+ perf_evsel__free_fd(evsel);
|
|
|
+ evsel->fd = NULL;
|
|
|
}
|
|
|
|
|
|
static struct {
|
|
@@ -269,7 +283,8 @@ static struct {
|
|
|
};
|
|
|
|
|
|
int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
|
|
- struct thread_map *threads, bool group)
|
|
|
+ struct thread_map *threads, bool group,
|
|
|
+ struct xyarray *group_fd)
|
|
|
{
|
|
|
if (cpus == NULL) {
|
|
|
/* Work around old compiler warnings about strict aliasing */
|
|
@@ -279,19 +294,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
|
|
|
if (threads == NULL)
|
|
|
threads = &empty_thread_map.map;
|
|
|
|
|
|
- return __perf_evsel__open(evsel, cpus, threads, group);
|
|
|
+ return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
|
|
|
}
|
|
|
|
|
|
int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
|
|
|
- struct cpu_map *cpus, bool group)
|
|
|
+ struct cpu_map *cpus, bool group,
|
|
|
+ struct xyarray *group_fd)
|
|
|
{
|
|
|
- return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group);
|
|
|
+ return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
|
|
|
+ group_fd);
|
|
|
}
|
|
|
|
|
|
int perf_evsel__open_per_thread(struct perf_evsel *evsel,
|
|
|
- struct thread_map *threads, bool group)
|
|
|
+ struct thread_map *threads, bool group,
|
|
|
+ struct xyarray *group_fd)
|
|
|
{
|
|
|
- return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group);
|
|
|
+ return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
|
|
|
+ group_fd);
|
|
|
}
|
|
|
|
|
|
static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
|