summaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/evlist.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 61d18dc83e8e..3cebc9a8d52e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,11 +25,12 @@
#include <linux/bitops.h>
#include <linux/hash.h>
+static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
+static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
+
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
-static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
-
void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
struct thread_map *threads)
{
@@ -426,16 +427,38 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
return 0;
}
+static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx)
+{
+ int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
+ /*
+ * Save the idx so that when we filter out fds POLLHUP'ed we can
+ * close the associated evlist->mmap[] entry.
+ */
+ if (pos >= 0) {
+ evlist->pollfd.priv[pos].idx = idx;
+
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ }
+
+ return pos;
+}
+
int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
{
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ return __perf_evlist__add_pollfd(evlist, fd, -1);
+}
+
+static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
+{
+ struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd);
- return fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
+ perf_evlist__mmap_put(evlist, fda->priv[fd].idx);
}
int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
{
- return fdarray__filter(&evlist->pollfd, revents_and_mask, NULL);
+ return fdarray__filter(&evlist->pollfd, revents_and_mask,
+ perf_evlist__munmap_filtered);
}
int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
@@ -777,7 +800,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
perf_evlist__mmap_get(evlist, idx);
}
- if (perf_evlist__add_pollfd(evlist, fd) < 0) {
+ if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
perf_evlist__mmap_put(evlist, idx);
return -1;
}