libperf: Introduce perf_evlist__for_each_mmap()

Add the perf_evlist__for_each_mmap() function and export it in the
perf/evlist.h header, so that the user can iterate through 'struct
perf_mmap' objects.

Add a internal perf_mmap__link() function to do the actual linking.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jin Yao <yao.jin@linux.intel.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lore.kernel.org/lkml/20191017105918.20873-2-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2019-10-17 12:59:09 +02:00 committed by Arnaldo Carvalho de Melo
parent 6a5f3d94cb
commit 6eb65f7a5c
7 changed files with 47 additions and 6 deletions

View file

@ -347,6 +347,8 @@ static struct perf_mmap* perf_evlist__alloc_mmap(struct perf_evlist *evlist, boo
return NULL; return NULL;
for (i = 0; i < evlist->nr_mmaps; i++) { 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 * When the perf_mmap() call is made we grab one refcount, plus
* one extra to let perf_mmap__consume() get the last * 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 * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and
* thus does perf_mmap__get() on it. * thus does perf_mmap__get() on it.
*/ */
perf_mmap__init(&map[i], overwrite, NULL); perf_mmap__init(&map[i], prev, overwrite, NULL);
} }
return map; 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); 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 static int
mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
int idx, struct perf_mmap_param *mp, int cpu_idx, 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) if (ops->mmap(map, mp, *output, evlist_cpu) < 0)
return -1; return -1;
if (!idx)
perf_evlist__set_mmap_first(evlist, map, overwrite);
} else { } else {
if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
return -1; return -1;
@ -605,3 +619,13 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
zfree(&evlist->mmap); zfree(&evlist->mmap);
zfree(&evlist->mmap_ovw); 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;
}

View file

@ -25,6 +25,8 @@ struct perf_evlist {
struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
struct perf_mmap *mmap; struct perf_mmap *mmap;
struct perf_mmap *mmap_ovw; struct perf_mmap *mmap_ovw;
struct perf_mmap *mmap_first;
struct perf_mmap *mmap_ovw_first;
}; };
typedef void typedef void

View file

@ -32,6 +32,7 @@ struct perf_mmap {
u64 flush; u64 flush;
libperf_unmap_cb_t unmap_cb; libperf_unmap_cb_t unmap_cb;
char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
struct perf_mmap *next;
}; };
struct perf_mmap_param { struct perf_mmap_param {
@ -41,8 +42,8 @@ struct perf_mmap_param {
size_t perf_mmap__mmap_len(struct perf_mmap *map); size_t perf_mmap__mmap_len(struct perf_mmap *map);
void perf_mmap__init(struct perf_mmap *map, bool overwrite, void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev,
libperf_unmap_cb_t unmap_cb); bool overwrite, libperf_unmap_cb_t unmap_cb);
int perf_mmap__mmap(struct perf_mmap *map, struct perf_mmap_param *mp, int perf_mmap__mmap(struct perf_mmap *map, struct perf_mmap_param *mp,
int fd, int cpu); int fd, int cpu);
void perf_mmap__munmap(struct perf_mmap *map); void perf_mmap__munmap(struct perf_mmap *map);

View file

@ -3,6 +3,7 @@
#define __LIBPERF_EVLIST_H #define __LIBPERF_EVLIST_H
#include <perf/core.h> #include <perf/core.h>
#include <stdbool.h>
struct perf_evlist; struct perf_evlist;
struct perf_evsel; 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 int perf_evlist__mmap(struct perf_evlist *evlist, int pages);
LIBPERF_API void perf_evlist__munmap(struct perf_evlist *evlist); 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 */ #endif /* __LIBPERF_EVLIST_H */

View file

@ -43,6 +43,7 @@ LIBPERF_0.0.1 {
perf_evlist__mmap; perf_evlist__mmap;
perf_evlist__munmap; perf_evlist__munmap;
perf_evlist__filter_pollfd; perf_evlist__filter_pollfd;
perf_evlist__next_mmap;
perf_mmap__consume; perf_mmap__consume;
perf_mmap__read_init; perf_mmap__read_init;
perf_mmap__read_done; perf_mmap__read_done;

View file

@ -13,13 +13,15 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include "internal.h" #include "internal.h"
void perf_mmap__init(struct perf_mmap *map, bool overwrite, void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev,
libperf_unmap_cb_t unmap_cb) bool overwrite, libperf_unmap_cb_t unmap_cb)
{ {
map->fd = -1; map->fd = -1;
map->overwrite = overwrite; map->overwrite = overwrite;
map->unmap_cb = unmap_cb; map->unmap_cb = unmap_cb;
refcount_set(&map->refcnt, 0); refcount_set(&map->refcnt, 0);
if (prev)
prev->next = map;
} }
size_t perf_mmap__mmap_len(struct perf_mmap *map) size_t perf_mmap__mmap_len(struct perf_mmap *map)

View file

@ -607,6 +607,8 @@ static struct mmap *evlist__alloc_mmap(struct evlist *evlist,
return NULL; return NULL;
for (i = 0; i < evlist->core.nr_mmaps; i++) { 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 * When the perf_mmap() call is made we grab one refcount, plus
* one extra to let perf_mmap__consume() get the last * 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 * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and
* thus does perf_mmap__get() on it. * 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; return map;