diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 65045614c938bfbb3a80979bfeac497c347a74a4..854efff1519d19bb5efcce1e4166b205b8354356 100644 --- a/tools/perf/lib/evlist.c +++ b/tools/perf/lib/evlist.c @@ -347,6 +347,8 @@ static struct perf_mmap* perf_evlist__alloc_mmap(struct perf_evlist *evlist, boo return NULL; for (i = 0; i < evlist->nr_mmaps; i++) { + struct perf_mmap *prev = i ? &map[i - 1] : NULL; + /* * When the perf_mmap() call is made we grab one refcount, plus * one extra to let perf_mmap__consume() get the last @@ -356,7 +358,7 @@ static struct perf_mmap* perf_evlist__alloc_mmap(struct perf_evlist *evlist, boo * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and * thus does perf_mmap__get() on it. */ - perf_mmap__init(&map[i], overwrite, NULL); + perf_mmap__init(&map[i], prev, overwrite, NULL); } return map; @@ -405,6 +407,15 @@ perf_evlist__mmap_cb_mmap(struct perf_mmap *map, struct perf_mmap_param *mp, return perf_mmap__mmap(map, mp, output, cpu); } +static void perf_evlist__set_mmap_first(struct perf_evlist *evlist, struct perf_mmap *map, + bool overwrite) +{ + if (overwrite) + evlist->mmap_ovw_first = map; + else + evlist->mmap_first = map; +} + static int mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, int idx, struct perf_mmap_param *mp, int cpu_idx, @@ -460,6 +471,9 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, if (ops->mmap(map, mp, *output, evlist_cpu) < 0) return -1; + + if (!idx) + perf_evlist__set_mmap_first(evlist, map, overwrite); } else { if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) return -1; @@ -605,3 +619,13 @@ void perf_evlist__munmap(struct perf_evlist *evlist) zfree(&evlist->mmap); zfree(&evlist->mmap_ovw); } + +struct perf_mmap* +perf_evlist__next_mmap(struct perf_evlist *evlist, struct perf_mmap *map, + bool overwrite) +{ + if (map) + return map->next; + + return overwrite ? evlist->mmap_ovw_first : evlist->mmap_first; +} diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h index be0b25a70730f523ba7d625d419c68f3273fb80a..20d90e29fc0eb07908a8b0740a916e0187fa0fc8 100644 --- a/tools/perf/lib/include/internal/evlist.h +++ b/tools/perf/lib/include/internal/evlist.h @@ -25,6 +25,8 @@ struct perf_evlist { struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; struct perf_mmap *mmap; struct perf_mmap *mmap_ovw; + struct perf_mmap *mmap_first; + struct perf_mmap *mmap_ovw_first; }; typedef void diff --git a/tools/perf/lib/include/internal/mmap.h b/tools/perf/lib/include/internal/mmap.h index ee536c4441bb9675355f2a2134109fdfdc07f8f0..be7556e0a2b26311f14631a78a26adddac71ba67 100644 --- a/tools/perf/lib/include/internal/mmap.h +++ b/tools/perf/lib/include/internal/mmap.h @@ -32,6 +32,7 @@ struct perf_mmap { u64 flush; libperf_unmap_cb_t unmap_cb; char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); + struct perf_mmap *next; }; struct perf_mmap_param { @@ -41,8 +42,8 @@ struct perf_mmap_param { size_t perf_mmap__mmap_len(struct perf_mmap *map); -void perf_mmap__init(struct perf_mmap *map, bool overwrite, - libperf_unmap_cb_t unmap_cb); +void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev, + bool overwrite, libperf_unmap_cb_t unmap_cb); int perf_mmap__mmap(struct perf_mmap *map, struct perf_mmap_param *mp, int fd, int cpu); void perf_mmap__munmap(struct perf_mmap *map); diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h index 16f526e74d136e3d0aec420dba1b0a81348c4fca..8c4b3c28535ef8b78c9d956a956f3a9c6a8d279a 100644 --- a/tools/perf/lib/include/perf/evlist.h +++ b/tools/perf/lib/include/perf/evlist.h @@ -3,6 +3,7 @@ #define __LIBPERF_EVLIST_H #include <perf/core.h> +#include <stdbool.h> struct perf_evlist; struct perf_evsel; @@ -38,4 +39,12 @@ LIBPERF_API int perf_evlist__filter_pollfd(struct perf_evlist *evlist, LIBPERF_API int perf_evlist__mmap(struct perf_evlist *evlist, int pages); LIBPERF_API void perf_evlist__munmap(struct perf_evlist *evlist); +LIBPERF_API struct perf_mmap *perf_evlist__next_mmap(struct perf_evlist *evlist, + struct perf_mmap *map, + bool overwrite); +#define perf_evlist__for_each_mmap(evlist, pos, overwrite) \ + for ((pos) = perf_evlist__next_mmap((evlist), NULL, overwrite); \ + (pos) != NULL; \ + (pos) = perf_evlist__next_mmap((evlist), (pos), overwrite)) + #endif /* __LIBPERF_EVLIST_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index 2184aba36c3f214e15d5e0b3f7ac3db00503ba55..8be02afc324b369080c58949e0129dd6b732d1a1 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -43,6 +43,7 @@ LIBPERF_0.0.1 { perf_evlist__mmap; perf_evlist__munmap; perf_evlist__filter_pollfd; + perf_evlist__next_mmap; perf_mmap__consume; perf_mmap__read_init; perf_mmap__read_done; diff --git a/tools/perf/lib/mmap.c b/tools/perf/lib/mmap.c index 0752c193b0fba5890a789bef9940ad0d035b85f7..79d5ed6c38cc524243ae77f918e213a20b3d6340 100644 --- a/tools/perf/lib/mmap.c +++ b/tools/perf/lib/mmap.c @@ -13,13 +13,15 @@ #include <linux/kernel.h> #include "internal.h" -void perf_mmap__init(struct perf_mmap *map, bool overwrite, - libperf_unmap_cb_t unmap_cb) +void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev, + bool overwrite, libperf_unmap_cb_t unmap_cb) { map->fd = -1; map->overwrite = overwrite; map->unmap_cb = unmap_cb; refcount_set(&map->refcnt, 0); + if (prev) + prev->next = map; } size_t perf_mmap__mmap_len(struct perf_mmap *map) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 0f9cd703e7256a9858877fe58af1261d4e37206c..6cda5a311ba5b1d98e0e5ad0820fd314f0d5b06e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -607,6 +607,8 @@ static struct mmap *evlist__alloc_mmap(struct evlist *evlist, return NULL; for (i = 0; i < evlist->core.nr_mmaps; i++) { + struct perf_mmap *prev = i ? &map[i - 1].core : NULL; + /* * When the perf_mmap() call is made we grab one refcount, plus * one extra to let perf_mmap__consume() get the last @@ -616,7 +618,7 @@ static struct mmap *evlist__alloc_mmap(struct evlist *evlist, * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and * thus does perf_mmap__get() on it. */ - perf_mmap__init(&map[i].core, overwrite, perf_mmap__unmap_cb); + perf_mmap__init(&map[i].core, prev, overwrite, perf_mmap__unmap_cb); } return map;