diff options
author | Jiri Olsa | 2019-10-07 14:53:18 +0200 |
---|---|---|
committer | Arnaldo Carvalho de Melo | 2019-10-10 11:45:21 -0300 |
commit | 7c4d41824f9afc659ba425a41018546531cffd72 (patch) | |
tree | 5aa23413cb012ea708c708c13d63561621448fd4 /tools/perf/lib | |
parent | 7728fa0cfaeb7d25b12c8865c733359cc8e5fb13 (diff) |
libperf: Adopt perf_mmap__read_init() from tools/perf
Move perf_mmap__read_init() from tools/perf to libperf and export it in
perf/mmap.h header.
And add pr_debug2()/pr_debug3() macros support, because the code is
using them.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20191007125344.14268-11-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/lib')
-rw-r--r-- | tools/perf/lib/include/perf/core.h | 2 | ||||
-rw-r--r-- | tools/perf/lib/include/perf/mmap.h | 1 | ||||
-rw-r--r-- | tools/perf/lib/internal.h | 2 | ||||
-rw-r--r-- | tools/perf/lib/libperf.map | 1 | ||||
-rw-r--r-- | tools/perf/lib/mmap.c | 84 |
5 files changed, 90 insertions, 0 deletions
diff --git a/tools/perf/lib/include/perf/core.h b/tools/perf/lib/include/perf/core.h index cfd70e720c1c..2a80e4b6f819 100644 --- a/tools/perf/lib/include/perf/core.h +++ b/tools/perf/lib/include/perf/core.h @@ -12,6 +12,8 @@ enum libperf_print_level { LIBPERF_WARN, LIBPERF_INFO, LIBPERF_DEBUG, + LIBPERF_DEBUG2, + LIBPERF_DEBUG3, }; typedef int (*libperf_print_fn_t)(enum libperf_print_level level, diff --git a/tools/perf/lib/include/perf/mmap.h b/tools/perf/lib/include/perf/mmap.h index d3678d1834d9..646e9052b003 100644 --- a/tools/perf/lib/include/perf/mmap.h +++ b/tools/perf/lib/include/perf/mmap.h @@ -7,5 +7,6 @@ struct perf_mmap; LIBPERF_API void perf_mmap__consume(struct perf_mmap *map); +LIBPERF_API int perf_mmap__read_init(struct perf_mmap *map); #endif /* __LIBPERF_MMAP_H */ diff --git a/tools/perf/lib/internal.h b/tools/perf/lib/internal.h index dc92f241732e..37db745e1502 100644 --- a/tools/perf/lib/internal.h +++ b/tools/perf/lib/internal.h @@ -14,5 +14,7 @@ do { \ #define pr_warning(fmt, ...) __pr(LIBPERF_WARN, fmt, ##__VA_ARGS__) #define pr_info(fmt, ...) __pr(LIBPERF_INFO, fmt, ##__VA_ARGS__) #define pr_debug(fmt, ...) __pr(LIBPERF_DEBUG, fmt, ##__VA_ARGS__) +#define pr_debug2(fmt, ...) __pr(LIBPERF_DEBUG2, fmt, ##__VA_ARGS__) +#define pr_debug3(fmt, ...) __pr(LIBPERF_DEBUG3, fmt, ##__VA_ARGS__) #endif /* __LIBPERF_INTERNAL_H */ diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map index d7b327f224e2..bc3fbb213a3e 100644 --- a/tools/perf/lib/libperf.map +++ b/tools/perf/lib/libperf.map @@ -41,6 +41,7 @@ LIBPERF_0.0.1 { perf_evlist__set_maps; perf_evlist__poll; perf_mmap__consume; + perf_mmap__read_init; local: *; }; diff --git a/tools/perf/lib/mmap.c b/tools/perf/lib/mmap.c index 4cada1c89fdb..fdbc6c550dea 100644 --- a/tools/perf/lib/mmap.c +++ b/tools/perf/lib/mmap.c @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-2.0 #include <sys/mman.h> +#include <inttypes.h> +#include <asm/bug.h> +#include <errno.h> #include <linux/ring_buffer.h> #include <linux/perf_event.h> #include <perf/mmap.h> #include <internal/mmap.h> #include <internal/lib.h> #include <linux/kernel.h> +#include "internal.h" void perf_mmap__init(struct perf_mmap *map, bool overwrite, libperf_unmap_cb_t unmap_cb) @@ -91,3 +95,83 @@ void perf_mmap__consume(struct perf_mmap *map) if (refcount_read(&map->refcnt) == 1 && perf_mmap__empty(map)) perf_mmap__put(map); } + +static int overwrite_rb_find_range(void *buf, int mask, u64 *start, u64 *end) +{ + struct perf_event_header *pheader; + u64 evt_head = *start; + int size = mask + 1; + + pr_debug2("%s: buf=%p, start=%"PRIx64"\n", __func__, buf, *start); + pheader = (struct perf_event_header *)(buf + (*start & mask)); + while (true) { + if (evt_head - *start >= (unsigned int)size) { + pr_debug("Finished reading overwrite ring buffer: rewind\n"); + if (evt_head - *start > (unsigned int)size) + evt_head -= pheader->size; + *end = evt_head; + return 0; + } + + pheader = (struct perf_event_header *)(buf + (evt_head & mask)); + + if (pheader->size == 0) { + pr_debug("Finished reading overwrite ring buffer: get start\n"); + *end = evt_head; + return 0; + } + + evt_head += pheader->size; + pr_debug3("move evt_head: %"PRIx64"\n", evt_head); + } + WARN_ONCE(1, "Shouldn't get here\n"); + return -1; +} + +/* + * Report the start and end of the available data in ringbuffer + */ +static int __perf_mmap__read_init(struct perf_mmap *md) +{ + u64 head = perf_mmap__read_head(md); + u64 old = md->prev; + unsigned char *data = md->base + page_size; + unsigned long size; + + md->start = md->overwrite ? head : old; + md->end = md->overwrite ? old : head; + + if ((md->end - md->start) < md->flush) + return -EAGAIN; + + size = md->end - md->start; + if (size > (unsigned long)(md->mask) + 1) { + if (!md->overwrite) { + WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); + + md->prev = head; + perf_mmap__consume(md); + return -EAGAIN; + } + + /* + * Backward ring buffer is full. We still have a chance to read + * most of data from it. + */ + if (overwrite_rb_find_range(data, md->mask, &md->start, &md->end)) + return -EINVAL; + } + + return 0; +} + +int perf_mmap__read_init(struct perf_mmap *map) +{ + /* + * Check if event was unmapped due to a POLLHUP/POLLERR. + */ + if (!refcount_read(&map->refcnt)) + return -ENOENT; + + return __perf_mmap__read_init(map); +} |