Adding perf_evlist__for_each_mmap function and exporting it in perf/evlist.h header, so user can iterate through 'struct perf_mmap' objects.
Adding internal perf_mmap__link function to do the actual linking. Link: http://lkml.kernel.org/n/tip-5h62ytvpxgozhqix2y41c...@git.kernel.org Signed-off-by: Jiri Olsa <jo...@kernel.org> --- tools/perf/lib/evlist.c | 26 +++++++++++++++++++++++- tools/perf/lib/include/internal/evlist.h | 2 ++ tools/perf/lib/include/internal/mmap.h | 5 +++-- tools/perf/lib/include/perf/evlist.h | 9 ++++++++ tools/perf/lib/libperf.map | 1 + tools/perf/lib/mmap.c | 6 ++++-- tools/perf/util/evlist.c | 4 +++- 7 files changed, 47 insertions(+), 6 deletions(-) diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c index 65045614c938..854efff1519d 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 be0b25a70730..20d90e29fc0e 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 ee536c4441bb..be7556e0a2b2 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 16f526e74d13..8c4b3c28535e 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 2184aba36c3f..8be02afc324b 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 0752c193b0fb..79d5ed6c38cc 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 0f9cd703e725..6cda5a311ba5 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; -- 2.21.0