All of lore.kernel.org
 help / color / mirror / Atom feed
From: "tip-bot2 for Jiri Olsa" <tip-bot2@linutronix.de>
To: linux-tip-commits@vger.kernel.org
Cc: Jiri Olsa <jolsa@kernel.org>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Michael Petlan <mpetlan@redhat.com>,
	Namhyung Kim <namhyung@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Ingo Molnar <mingo@kernel.org>, Borislav Petkov <bp@alien8.de>,
	linux-kernel@vger.kernel.org
Subject: [tip: perf/core] libperf: Adopt perf_evlist__mmap()/munmap() from tools/perf
Date: Tue, 15 Oct 2019 05:31:39 -0000	[thread overview]
Message-ID: <157111749906.12254.2831611483887542840.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20191007125344.14268-14-jolsa@kernel.org>

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     d1a177595b3a824c72dacb0f9d1a4e5906eaef0e
Gitweb:        https://git.kernel.org/tip/d1a177595b3a824c72dacb0f9d1a4e5906eaef0e
Author:        Jiri Olsa <jolsa@kernel.org>
AuthorDate:    Mon, 07 Oct 2019 14:53:21 +02:00
Committer:     Arnaldo Carvalho de Melo <acme@redhat.com>
CommitterDate: Thu, 10 Oct 2019 12:15:58 -03:00

libperf: Adopt perf_evlist__mmap()/munmap() from tools/perf

Add libperf's version of perf_evlist__mmap()/munmap() functions and
exporting them in the perf/evlist.h header.

It's the backbone of what we have in perf code. The following changes
will add needed callbacks and then we'll finally switch the perf code to
use libperf's version.

Add mmap/mmap_ovw 'struct perf_mmap' object arrays to hold maps for
libperf's evlist.

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-14-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/lib/evlist.c                  | 236 ++++++++++++++++++++++-
 tools/perf/lib/include/internal/evlist.h |   2 +-
 tools/perf/lib/include/perf/evlist.h     |   3 +-
 tools/perf/lib/libperf.map               |   2 +-
 4 files changed, 243 insertions(+)

diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c
index d1496fe..250ad57 100644
--- a/tools/perf/lib/evlist.c
+++ b/tools/perf/lib/evlist.c
@@ -8,13 +8,20 @@
 #include <internal/evlist.h>
 #include <internal/evsel.h>
 #include <internal/xyarray.h>
+#include <internal/mmap.h>
+#include <internal/cpumap.h>
+#include <internal/threadmap.h>
+#include <internal/xyarray.h>
+#include <internal/lib.h>
 #include <linux/zalloc.h>
+#include <sys/ioctl.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <poll.h>
+#include <sys/mman.h>
 #include <perf/cpumap.h>
 #include <perf/threadmap.h>
 #include <api/fd/array.h>
@@ -103,6 +110,10 @@ perf_evlist__next(struct perf_evlist *evlist, struct perf_evsel *prev)
 
 void perf_evlist__delete(struct perf_evlist *evlist)
 {
+	if (evlist == NULL)
+		return;
+
+	perf_evlist__munmap(evlist);
 	free(evlist);
 }
 
@@ -281,3 +292,228 @@ int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
 {
 	return fdarray__poll(&evlist->pollfd, timeout);
 }
+
+static struct perf_mmap* perf_evlist__alloc_mmap(struct perf_evlist *evlist, bool overwrite)
+{
+	int i;
+	struct perf_mmap *map;
+
+	evlist->nr_mmaps = perf_cpu_map__nr(evlist->cpus);
+	if (perf_cpu_map__empty(evlist->cpus))
+		evlist->nr_mmaps = perf_thread_map__nr(evlist->threads);
+
+	map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
+	if (!map)
+		return NULL;
+
+	for (i = 0; i < evlist->nr_mmaps; i++) {
+		/*
+		 * When the perf_mmap() call is made we grab one refcount, plus
+		 * one extra to let perf_mmap__consume() get the last
+		 * events after all real references (perf_mmap__get()) are
+		 * dropped.
+		 *
+		 * 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);
+	}
+
+	return map;
+}
+
+static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
+				     struct perf_evsel *evsel, int idx, int cpu,
+				     int thread)
+{
+	struct perf_sample_id *sid = SID(evsel, cpu, thread);
+
+	sid->idx = idx;
+	if (evlist->cpus && cpu >= 0)
+		sid->cpu = evlist->cpus->map[cpu];
+	else
+		sid->cpu = -1;
+	if (!evsel->system_wide && evlist->threads && thread >= 0)
+		sid->tid = perf_thread_map__pid(evlist->threads, thread);
+	else
+		sid->tid = -1;
+}
+
+static struct perf_mmap*
+perf_evlist__map_get(struct perf_evlist *evlist, bool overwrite, int idx)
+{
+	struct perf_mmap *map = &evlist->mmap[idx];
+
+	if (overwrite) {
+		if (!evlist->mmap_ovw) {
+			evlist->mmap_ovw = perf_evlist__alloc_mmap(evlist, true);
+			if (!evlist->mmap_ovw)
+				return NULL;
+		}
+		map = &evlist->mmap_ovw[idx];
+	}
+
+	return map;
+}
+
+#define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y))
+
+static int
+mmap_per_evsel(struct perf_evlist *evlist, int idx,
+	       struct perf_mmap_param *mp, int cpu_idx,
+	       int thread, int *_output, int *_output_overwrite)
+{
+	int evlist_cpu = perf_cpu_map__cpu(evlist->cpus, cpu_idx);
+	struct perf_evsel *evsel;
+	int revent;
+
+	perf_evlist__for_each_entry(evlist, evsel) {
+		bool overwrite = evsel->attr.write_backward;
+		struct perf_mmap *map;
+		int *output, fd, cpu;
+
+		if (evsel->system_wide && thread)
+			continue;
+
+		cpu = perf_cpu_map__idx(evsel->cpus, evlist_cpu);
+		if (cpu == -1)
+			continue;
+
+		map = perf_evlist__map_get(evlist, overwrite, idx);
+		if (map == NULL)
+			return -ENOMEM;
+
+		if (overwrite) {
+			mp->prot = PROT_READ;
+			output   = _output_overwrite;
+		} else {
+			mp->prot = PROT_READ | PROT_WRITE;
+			output   = _output;
+		}
+
+		fd = FD(evsel, cpu, thread);
+
+		if (*output == -1) {
+			*output = fd;
+
+			if (perf_mmap__mmap(map, mp, *output, evlist_cpu) < 0)
+				return -1;
+		} else {
+			if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
+				return -1;
+
+			perf_mmap__get(map);
+		}
+
+		revent = !overwrite ? POLLIN : 0;
+
+		if (!evsel->system_wide &&
+		    perf_evlist__add_pollfd(evlist, fd, map, revent) < 0) {
+			perf_mmap__put(map);
+			return -1;
+		}
+
+		if (evsel->attr.read_format & PERF_FORMAT_ID) {
+			if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
+						   fd) < 0)
+				return -1;
+			perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
+						 thread);
+		}
+	}
+
+	return 0;
+}
+
+static int
+mmap_per_thread(struct perf_evlist *evlist, struct perf_mmap_param *mp)
+{
+	int thread;
+	int nr_threads = perf_thread_map__nr(evlist->threads);
+
+	for (thread = 0; thread < nr_threads; thread++) {
+		int output = -1;
+		int output_overwrite = -1;
+
+		if (mmap_per_evsel(evlist, thread, mp, 0, thread,
+				   &output, &output_overwrite))
+			goto out_unmap;
+	}
+
+	return 0;
+
+out_unmap:
+	perf_evlist__munmap(evlist);
+	return -1;
+}
+
+static int
+mmap_per_cpu(struct perf_evlist *evlist, struct perf_mmap_param *mp)
+{
+	int nr_threads = perf_thread_map__nr(evlist->threads);
+	int nr_cpus    = perf_cpu_map__nr(evlist->cpus);
+	int cpu, thread;
+
+	for (cpu = 0; cpu < nr_cpus; cpu++) {
+		int output = -1;
+		int output_overwrite = -1;
+
+		for (thread = 0; thread < nr_threads; thread++) {
+			if (mmap_per_evsel(evlist, cpu, mp, cpu,
+					   thread, &output, &output_overwrite))
+				goto out_unmap;
+		}
+	}
+
+	return 0;
+
+out_unmap:
+	perf_evlist__munmap(evlist);
+	return -1;
+}
+
+int perf_evlist__mmap(struct perf_evlist *evlist, int pages)
+{
+	struct perf_evsel *evsel;
+	const struct perf_cpu_map *cpus = evlist->cpus;
+	const struct perf_thread_map *threads = evlist->threads;
+	struct perf_mmap_param mp;
+
+	if (!evlist->mmap)
+		evlist->mmap = perf_evlist__alloc_mmap(evlist, false);
+	if (!evlist->mmap)
+		return -ENOMEM;
+
+	perf_evlist__for_each_entry(evlist, evsel) {
+		if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+		    evsel->sample_id == NULL &&
+		    perf_evsel__alloc_id(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0)
+			return -ENOMEM;
+	}
+
+	evlist->mmap_len = (pages + 1) * page_size;
+	mp.mask = evlist->mmap_len - page_size - 1;
+
+	if (perf_cpu_map__empty(cpus))
+		return mmap_per_thread(evlist, &mp);
+
+	return mmap_per_cpu(evlist, &mp);
+}
+
+void perf_evlist__munmap(struct perf_evlist *evlist)
+{
+	int i;
+
+	if (evlist->mmap) {
+		for (i = 0; i < evlist->nr_mmaps; i++)
+			perf_mmap__munmap(&evlist->mmap[i]);
+	}
+
+	if (evlist->mmap_ovw) {
+		for (i = 0; i < evlist->nr_mmaps; i++)
+			perf_mmap__munmap(&evlist->mmap_ovw[i]);
+	}
+
+	zfree(&evlist->mmap);
+	zfree(&evlist->mmap_ovw);
+}
diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h
index 9f440ab..4438a19 100644
--- a/tools/perf/lib/include/internal/evlist.h
+++ b/tools/perf/lib/include/internal/evlist.h
@@ -22,6 +22,8 @@ struct perf_evlist {
 	size_t			 mmap_len;
 	struct fdarray		 pollfd;
 	struct hlist_head	 heads[PERF_EVLIST__HLIST_SIZE];
+	struct perf_mmap	*mmap;
+	struct perf_mmap	*mmap_ovw;
 };
 
 int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h
index 8a2ce07..28b6a12 100644
--- a/tools/perf/lib/include/perf/evlist.h
+++ b/tools/perf/lib/include/perf/evlist.h
@@ -33,4 +33,7 @@ LIBPERF_API void perf_evlist__set_maps(struct perf_evlist *evlist,
 				       struct perf_thread_map *threads);
 LIBPERF_API int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
 
+LIBPERF_API int perf_evlist__mmap(struct perf_evlist *evlist, int pages);
+LIBPERF_API void perf_evlist__munmap(struct perf_evlist *evlist);
+
 #endif /* __LIBPERF_EVLIST_H */
diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map
index 8bb0d73..5a18fd1 100644
--- a/tools/perf/lib/libperf.map
+++ b/tools/perf/lib/libperf.map
@@ -40,6 +40,8 @@ LIBPERF_0.0.1 {
 		perf_evlist__next;
 		perf_evlist__set_maps;
 		perf_evlist__poll;
+		perf_evlist__mmap;
+		perf_evlist__munmap;
 		perf_mmap__consume;
 		perf_mmap__read_init;
 		perf_mmap__read_done;

  reply	other threads:[~2019-10-15  5:36 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-07 12:53 [PATCHv2 00/36] libperf: Add sampling interface Jiri Olsa
2019-10-07 12:53 ` [PATCH 01/36] libperf: Add perf_mmap__init() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 02/36] libperf: Add 'struct perf_mmap_param' Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 03/36] libperf: Add perf_mmap__mmap_len() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__mmap_len() function from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 04/36] libperf: Add perf_mmap__mmap() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__mmap() function from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 05/36] libperf: Add perf_mmap__get() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__get() function from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 06/36] libperf: Add perf_mmap__unmap() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__unmap() function from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 07/36] libperf: Add perf_mmap__put() function Jiri Olsa
2019-10-10 13:11   ` Arnaldo Carvalho de Melo
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__put() function from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 08/36] perf tools: Use perf_mmap way to detect aux mmap Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 09/36] libperf: Add perf_mmap__consume() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__consume() function from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 10/36] libperf: Add perf_mmap__read_init() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__read_init() from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 11/36] libperf: Add perf_mmap__read_done() function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__read_done() from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 12/36] libperf: Add perf_mmap__read_event() function Jiri Olsa
2019-10-10 14:47   ` Arnaldo Carvalho de Melo
2019-10-10 15:32     ` Jiri Olsa
2019-10-10 16:07       ` Arnaldo Carvalho de Melo
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_mmap__read_event() from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 13/36] libperf: Add perf_evlist__mmap()/munmap() functions Jiri Olsa
2019-10-15  5:31   ` tip-bot2 for Jiri Olsa [this message]
2019-10-07 12:53 ` [PATCH 14/36] libperf: Add perf_evlist__mmap_ops function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Introduce perf_evlist__mmap_ops() tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 15/36] libperf: Add perf_evlist_mmap_ops::idx callback Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Introduce " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 16/36] libperf: Add perf_evlist_mmap_ops::get callback Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 17/36] libperf: Add perf_evlist_mmap_ops::mmap callback Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Introduce " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 18/36] perf tools: Add perf_evlist__mmap_cb_idx function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] perf tools: Introduce perf_evlist__mmap_cb_idx() tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 19/36] perf tools: Add perf_evlist__mmap_cb_get function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] perf evlist: Introduce perf_evlist__mmap_cb_get() tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 20/36] perf tools: Add perf_evlist__mmap_cb_mmap function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] perf evlist: Introduce perf_evlist__mmap_cb_mmap() tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 21/36] perf tools: Switch to libperf mmap interface Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] perf evlist: Switch to libperf's " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 22/36] libperf: Centralize map refcnt setting Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 23/36] libperf: Move pollfd allocation to libperf Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Move the pollfd allocation from tools/perf " tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 24/36] libperf: Add perf_evlist__exit function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Introduce perf_evlist__exit() tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 25/36] libperf: Add perf_evlist__purge function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Introduce perf_evlist__purge() tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 26/36] libperf: Add perf_evlist__filter_pollfd function Jiri Olsa
2019-10-15  5:31   ` [tip: perf/core] libperf: Adopt perf_evlist__filter_pollfd() from tools/perf tip-bot2 for Jiri Olsa
2019-10-07 12:53 ` [PATCH 27/36] libperf: Add perf_evlist__for_each_mmap function Jiri Olsa
2019-10-10 16:06   ` Arnaldo Carvalho de Melo
2019-10-10 16:20     ` Jiri Olsa
2019-10-07 12:53 ` [PATCH 28/36] libperf: Move mmap allocation to perf_evlist__mmap_ops::get Jiri Olsa
2019-10-07 12:53 ` [PATCH 29/36] libperf: Move mask setup to perf_evlist__mmap_ops function Jiri Olsa
2019-10-07 12:53 ` [PATCH 30/36] libperf: Link static tests with libapi.a Jiri Olsa
2019-10-07 12:53 ` [PATCH 31/36] libperf: Add _GNU_SOURCE define to compilation Jiri Olsa
2019-10-07 12:53 ` [PATCH 32/36] libperf: Add tests_mmap_thread test Jiri Olsa
2019-10-07 12:53 ` [PATCH 33/36] libperf: Add tests_mmap_cpus test Jiri Olsa
2019-10-07 12:53 ` [PATCH 34/36] libperf: Keep count of failed tests Jiri Olsa
2019-10-07 12:53 ` [PATCH 35/36] libperf: Do not export perf_evsel__init/perf_evlist__init Jiri Olsa
2019-10-07 12:53 ` [PATCH 36/36] libperf: Add pr_err macro Jiri Olsa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=157111749906.12254.2831611483887542840.tip-bot2@tip-bot2 \
    --to=tip-bot2@linutronix.de \
    --cc=acme@redhat.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=mpetlan@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.