[PATCH 06/49] perf tools: Create separate mmap for dummy tracking event

Jiri Olsa
2018-01-09T15:49:17Z

When indexed data file support is enabled, a dummy tracking event will
be used to track metadata (like task, comm and mmap events) for a
session and actual samples will be recorded in separate (intermediate)
files and then merged (with index table).

Provide separate mmap to the dummy tracking event. The size is fixed
to 128KiB (+ 1 page) as the event rate will be lower than samples. I
originally wanted to use a single mmap for this but cross-cpu sharing
is prohibited so it's per-cpu (or per-task) like normal mmaps.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Link: http://lkml.kernel.org/n/tip-8vw9ocqkwqa7rsoolc25ezdt@git.kernel.org
Original-patch-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/perf/builtin-record.c | 9 ++++++++
tools/perf/util/evlist.c | 55 ++++++++++++++++++++++++++++++++++++---------
tools/perf/util/evlist.h | 3 +++
tools/perf/util/mmap.h | 1 +
4 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 57994e16e30f..a792758e9aa3 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -510,6 +510,8 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli

for (i = 0; i < evlist->nr_mmaps; i++) {
struct perf_mmap *map = &maps[i];
+ struct perf_mmap *track_map = evlist->track_mmap ?
+ &evlist->track_mmap[i] : NULL;

if (map->base) {
if (perf_mmap__push(map, overwrite, rec, record__pushfn) != 0) {
@@ -523,6 +525,13 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
rc = -1;
goto out;
}
+
+ if (track_map && track_map->base) {
+ if (perf_mmap__push(track_map, overwrite, rec, record__pushfn) != 0) {
+ rc = -1;
+ goto out;
+ }
+ }
}

/*
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 4e5027e590e2..bb2c74865ba3 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -775,9 +775,15 @@ static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
{
int i;

- if (evlist->mmap)
+ if (evlist->mmap) {
for (i = 0; i < evlist->nr_mmaps; i++)
perf_mmap__munmap(&evlist->mmap[i]);
+ }
+
+ if (evlist->track_mmap) {
+ for (i = 0; i < evlist->nr_mmaps; i++)
+ perf_mmap__munmap(&evlist->track_mmap[i]);
+ }

if (evlist->overwrite_mmap)
for (i = 0; i < evlist->nr_mmaps; i++)
@@ -829,14 +835,20 @@ perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
}

static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
- struct mmap_params *mp, int cpu_idx,
- int thread, int *_output, int *_output_overwrite)
+ struct mmap_params *_mp, int cpu_idx,
+ int thread, int *_output, int *_output_overwrite,
+ int *_output_track)
{
+ struct mmap_params mp_track = {
+ .prot = PROT_READ | PROT_WRITE,
+ .mask = TRACK_MMAP_SIZE - page_size - 1,
+ };
struct perf_evsel *evsel;
int revent;
int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);

evlist__for_each_entry(evlist, evsel) {
+ struct mmap_params *mp = _mp;
struct perf_mmap *maps = evlist->mmap;
int *output = _output;
int fd;
@@ -858,6 +870,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
mp->prot &= ~PROT_WRITE;
}

+ if (mp->track_mmap && perf_evsel__is_dummy_tracking(evsel)) {
+ output = _output_track;
+ maps = evlist->track_mmap;
+ mp = &mp_track;
+ }
+
if (evsel->system_wide && thread)
continue;

@@ -917,13 +935,15 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
for (cpu = 0; cpu < nr_cpus; cpu++) {
int output = -1;
int output_overwrite = -1;
+ int output_track = -1;

auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
true);

for (thread = 0; thread < nr_threads; thread++) {
if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
- thread, &output, &output_overwrite))
+ thread, &output, &output_overwrite,
+ &output_track))
goto out_unmap;
}
}
@@ -945,12 +965,13 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
for (thread = 0; thread < nr_threads; thread++) {
int output = -1;
int output_overwrite = -1;
+ int output_track = -1;

auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
false);

if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
- &output, &output_overwrite))
+ &output, &output_overwrite, &output_track))
goto out_unmap;
}

@@ -1095,12 +1116,26 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
* Its value is decided by evsel's write_backward.
* So &mp should not be passed through const pointer.
*/
- struct mmap_params mp;
+ struct mmap_params mp = {
+ .track_mmap = false,
+ };

- if (!evlist->mmap)
- evlist->mmap = perf_evlist__alloc_mmap(evlist);
- if (!evlist->mmap)
- return -ENOMEM;
+ if (!evlist->mmap) {
+ struct perf_mmap *map;
+
+ map = perf_evlist__alloc_mmap(evlist);
+ if (!map)
+ return -ENOMEM;
+
+ evlist->mmap = map;
+ if (mp.track_mmap) {
+ map = perf_evlist__alloc_mmap(evlist);
+ if (!map)
+ return -ENOMEM;
+
+ evlist->track_mmap = map;
+ }
+ }

if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
return -ENOMEM;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index dff82a5853ad..bbfe523b0509 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -25,6 +25,8 @@ struct record_opts;
#define PERF_EVLIST__HLIST_BITS 8
#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)

+#define TRACK_MMAP_SIZE (((128 * 1024 / page_size) + 1) * page_size)
+
struct perf_evlist {
struct list_head entries;
struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
@@ -45,6 +47,7 @@ struct perf_evlist {
struct fdarray pollfd;
struct perf_mmap *mmap;
struct perf_mmap *overwrite_mmap;
+ struct perf_mmap *track_mmap;
struct thread_map *threads;
struct cpu_map *cpus;
struct perf_evsel *selected;
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 52853eca7ef9..a1e39b131842 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -55,6 +55,7 @@ enum bkw_mmap_state {
struct mmap_params {
int prot, mask;
struct auxtrace_mmap_params auxtrace_mp;
+ bool track_mmap;
};

int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd);
--
2.13.6