2019-10-18 15:35:29

by Jiri Olsa

[permalink] [raw]
Subject: [PATCHv3 00/10] libperf: Add sampling interface (leftover)

hi,
sending changes for exporting basic sampling interface
in libperf. It's now possible to use following code in
applications via libperf:

--- (example is without error checks for simplicity)

struct perf_event_attr attr = {
.type = PERF_TYPE_TRACEPOINT,
.sample_period = 1,
.wakeup_watermark = 1,
.disabled = 1,
};
/* ... setup attr */

cpus = perf_cpu_map__new(NULL);

evlist = perf_evlist__new();
evsel = perf_evsel__new(&attr);
perf_evlist__add(evlist, evsel);

perf_evlist__set_maps(evlist, cpus, NULL);

err = perf_evlist__open(evlist);
err = perf_evlist__mmap(evlist, 4);

err = perf_evlist__enable(evlist);

/* ... monitored area, plus all the other cpus */

err = perf_evlist__disable(evlist);

perf_evlist__for_each_mmap(evlist, map) {
if (perf_mmap__read_init(map) < 0)
continue;

while ((event = perf_mmap__read_event(map)) != NULL) {
perf_mmap__consume(map);
}

perf_mmap__read_done(map);
}

perf_evlist__delete(evlist);
perf_cpu_map__put(cpus);

--- (end)

Nothing is carved in stone so far, the interface is exported
as is available in perf now and we can change it as we want.

New tests are added in test-evlist.c to do thread and cpu based
sampling.

All the functionality should not change, however there's considerable
mmap code rewrite.

Now we have perf_evlist__mmap_ops called by both perf and libperf
mmaps functions with specific 'struct perf_evlist_mmap_ops'
callbacks:

- get - to get mmap object, both libperf and perf use different
objects, because perf needs to carry more data for aio,
compression and auxtrace
- mmap - to actually mmap the object, it's simple mmap for libperf,
but more work for perf wrt aio, compression and auxtrace
- idx - callback to get current IDs, used only in perf for auxtrace
setup


It would be great if guys could run your usual workloads to see if all
is fine.. so far so good in my tests ;-)


It's also available in here:
git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/lib

v3 changes:
- changed mmap0 and mmap_ovw0 to mmap_first and mmap_ovw_first
- rebased to latest perf/core
- portion of patches already taken

v2 changes:
- rebased to latest perf/core
- portion of patches already taken
- explained mmap refcnt management in following patch changelog:
libperf: Centralize map refcnt setting

thanks,
jirka


Cc: Kan Liang <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: Ian Rogers <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Song Liu <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
---
Jiri Olsa (10):
libperf: Add perf_evlist__for_each_mmap function
libperf: Move mmap allocation to perf_evlist__mmap_ops::get
libperf: Move mask setup to perf_evlist__mmap_ops function
libperf: Link static tests with libapi.a
libperf: Add _GNU_SOURCE define to compilation
libperf: Add tests_mmap_thread test
libperf: Add tests_mmap_cpus test
libperf: Keep count of failed tests
libperf: Do not export perf_evsel__init/perf_evlist__init
libperf: Add pr_err macro

tools/perf/lib/Makefile | 2 ++
tools/perf/lib/evlist.c | 71 ++++++++++++++++++++++++++++++++++++++---------------
tools/perf/lib/include/internal/evlist.h | 3 +++
tools/perf/lib/include/internal/evsel.h | 1 +
tools/perf/lib/include/internal/mmap.h | 5 ++--
tools/perf/lib/include/internal/tests.h | 20 ++++++++++++---
tools/perf/lib/include/perf/core.h | 1 +
tools/perf/lib/include/perf/evlist.h | 10 +++++++-
tools/perf/lib/include/perf/evsel.h | 2 --
tools/perf/lib/internal.h | 3 +++
tools/perf/lib/libperf.map | 3 +--
tools/perf/lib/mmap.c | 6 +++--
tools/perf/lib/tests/Makefile | 8 +++---
tools/perf/lib/tests/test-cpumap.c | 2 +-
tools/perf/lib/tests/test-evlist.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
tools/perf/lib/tests/test-evsel.c | 2 +-
tools/perf/lib/tests/test-threadmap.c | 2 +-
tools/perf/util/evlist.c | 29 +++++++++-------------
18 files changed, 333 insertions(+), 55 deletions(-)


2019-10-18 15:35:44

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 05/10] libperf: Add _GNU_SOURCE define to compilation

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/Makefile | 1 +
tools/perf/lib/tests/Makefile | 2 ++
2 files changed, 3 insertions(+)

diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile
index 0f233638ef1f..20396f68fcad 100644
--- a/tools/perf/lib/Makefile
+++ b/tools/perf/lib/Makefile
@@ -73,6 +73,7 @@ override CFLAGS += -Werror -Wall
override CFLAGS += -fPIC
override CFLAGS += $(INCLUDES)
override CFLAGS += -fvisibility=hidden
+override CFLAGS += -D_GNU_SOURCE

all:

diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile
index a43cd08c5c03..78c3d8c83c53 100644
--- a/tools/perf/lib/tests/Makefile
+++ b/tools/perf/lib/tests/Makefile
@@ -12,6 +12,8 @@ else
CFLAGS := -g -Wall
endif

+CFLAGS += -D_GNU_SOURCE
+
all:

include $(srctree)/tools/scripts/Makefile.include
--
2.21.0

2019-10-18 15:35:59

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 08/10] libperf: Keep count of failed tests

Keeping the count of failed tests, so we
get better output with failures, like:

# make tests
...
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...FAILED test-evlist.c:53 failed to create evsel2
FAILED test-evlist.c:163 failed to create evsel2
FAILED test-evlist.c:287 failed count
FAILED (3)
- running test-evsel.c...OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...FAILED test-evlist.c:53 failed to create evsel2
FAILED test-evlist.c:163 failed to create evsel2
FAILED test-evlist.c:287 failed count
FAILED (3)
- running test-evsel.c...OK
...

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/include/internal/tests.h | 20 +++++++++++++++++---
tools/perf/lib/tests/test-cpumap.c | 2 +-
tools/perf/lib/tests/test-evlist.c | 2 +-
tools/perf/lib/tests/test-evsel.c | 2 +-
tools/perf/lib/tests/test-threadmap.c | 2 +-
5 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/tools/perf/lib/include/internal/tests.h b/tools/perf/lib/include/internal/tests.h
index b7a20cd24ee1..2093e8868a67 100644
--- a/tools/perf/lib/include/internal/tests.h
+++ b/tools/perf/lib/include/internal/tests.h
@@ -4,14 +4,28 @@

#include <stdio.h>

-#define __T_START fprintf(stdout, "- running %s...", __FILE__)
-#define __T_OK fprintf(stdout, "OK\n")
-#define __T_FAIL fprintf(stdout, "FAIL\n")
+int tests_failed;
+
+#define __T_START \
+do { \
+ fprintf(stdout, "- running %s...", __FILE__); \
+ fflush(NULL); \
+ tests_failed = 0; \
+} while (0)
+
+#define __T_END \
+do { \
+ if (tests_failed) \
+ fprintf(stdout, " FAILED (%d)\n", tests_failed); \
+ else \
+ fprintf(stdout, "OK\n"); \
+} while (0)

#define __T(text, cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
+ tests_failed++; \
return -1; \
} \
} while (0)
diff --git a/tools/perf/lib/tests/test-cpumap.c b/tools/perf/lib/tests/test-cpumap.c
index aa34c20df07e..c8d45091e7c2 100644
--- a/tools/perf/lib/tests/test-cpumap.c
+++ b/tools/perf/lib/tests/test-cpumap.c
@@ -26,6 +26,6 @@ int main(int argc, char **argv)
perf_cpu_map__put(cpus);
perf_cpu_map__put(cpus);

- __T_OK;
+ __T_END;
return 0;
}
diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
index d8c52ebfa53a..9a80c310ac0f 100644
--- a/tools/perf/lib/tests/test-evlist.c
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -407,6 +407,6 @@ int main(int argc, char **argv)
test_mmap_thread();
test_mmap_cpus();

- __T_OK;
+ __T_END;
return 0;
}
diff --git a/tools/perf/lib/tests/test-evsel.c b/tools/perf/lib/tests/test-evsel.c
index 1b6c4285ac2b..135722ac965b 100644
--- a/tools/perf/lib/tests/test-evsel.c
+++ b/tools/perf/lib/tests/test-evsel.c
@@ -130,6 +130,6 @@ int main(int argc, char **argv)
test_stat_thread();
test_stat_thread_enable();

- __T_OK;
+ __T_END;
return 0;
}
diff --git a/tools/perf/lib/tests/test-threadmap.c b/tools/perf/lib/tests/test-threadmap.c
index 8c5f47247d9e..7dc4d6fbedde 100644
--- a/tools/perf/lib/tests/test-threadmap.c
+++ b/tools/perf/lib/tests/test-threadmap.c
@@ -26,6 +26,6 @@ int main(int argc, char **argv)
perf_thread_map__put(threads);
perf_thread_map__put(threads);

- __T_OK;
+ __T_END;
return 0;
}
--
2.21.0

2019-10-18 15:36:00

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 01/10] libperf: Add perf_evlist__for_each_mmap function

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/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
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

2019-10-18 15:36:07

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 09/10] libperf: Do not export perf_evsel__init/perf_evlist__init

There's no point to export perf_evsel__init/perf_evlist__init,
it's called from perf_evsel__new/perf_evlist__new respectively.

It's used only from perf where perf_evsel/perf_evlist is embedded
perf's evsel/evlist.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/include/internal/evlist.h | 1 +
tools/perf/lib/include/internal/evsel.h | 1 +
tools/perf/lib/include/perf/evlist.h | 1 -
tools/perf/lib/include/perf/evsel.h | 2 --
tools/perf/lib/libperf.map | 2 --
5 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h
index 20d90e29fc0e..a2fbccf1922f 100644
--- a/tools/perf/lib/include/internal/evlist.h
+++ b/tools/perf/lib/include/internal/evlist.h
@@ -50,6 +50,7 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
struct perf_evlist_mmap_ops *ops,
struct perf_mmap_param *mp);

+void perf_evlist__init(struct perf_evlist *evlist);
void perf_evlist__exit(struct perf_evlist *evlist);

/**
diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h
index a69b8299c36f..1ffd083b235e 100644
--- a/tools/perf/lib/include/internal/evsel.h
+++ b/tools/perf/lib/include/internal/evsel.h
@@ -50,6 +50,7 @@ struct perf_evsel {
bool system_wide;
};

+void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr);
int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
void perf_evsel__close_fd(struct perf_evsel *evsel);
void perf_evsel__free_fd(struct perf_evsel *evsel);
diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h
index 8c4b3c28535e..0a7479dc13bf 100644
--- a/tools/perf/lib/include/perf/evlist.h
+++ b/tools/perf/lib/include/perf/evlist.h
@@ -10,7 +10,6 @@ struct perf_evsel;
struct perf_cpu_map;
struct perf_thread_map;

-LIBPERF_API void perf_evlist__init(struct perf_evlist *evlist);
LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist,
struct perf_evsel *evsel);
LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist,
diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h
index 4388667f265c..557f5815a9c9 100644
--- a/tools/perf/lib/include/perf/evsel.h
+++ b/tools/perf/lib/include/perf/evsel.h
@@ -21,8 +21,6 @@ struct perf_counts_values {
};
};

-LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel,
- struct perf_event_attr *attr);
LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr);
LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel);
LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map
index 8be02afc324b..7be1af8a546c 100644
--- a/tools/perf/lib/libperf.map
+++ b/tools/perf/lib/libperf.map
@@ -21,7 +21,6 @@ LIBPERF_0.0.1 {
perf_evsel__delete;
perf_evsel__enable;
perf_evsel__disable;
- perf_evsel__init;
perf_evsel__open;
perf_evsel__close;
perf_evsel__read;
@@ -34,7 +33,6 @@ LIBPERF_0.0.1 {
perf_evlist__close;
perf_evlist__enable;
perf_evlist__disable;
- perf_evlist__init;
perf_evlist__add;
perf_evlist__remove;
perf_evlist__next;
--
2.21.0

2019-10-18 15:36:48

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 07/10] libperf: Add tests_mmap_cpus test

Adding mmaping tests that generates prctl call on
every cpu validates it gets all the related events
in ring buffer.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/tests/test-evlist.c | 97 ++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)

diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
index 90a1869ba4b1..d8c52ebfa53a 100644
--- a/tools/perf/lib/tests/test-evlist.c
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
+#include <sched.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
@@ -299,6 +300,101 @@ static int test_mmap_thread(void)
return 0;
}

+static int test_mmap_cpus(void)
+{
+ struct perf_evlist *evlist;
+ struct perf_evsel *evsel;
+ struct perf_mmap *map;
+ struct perf_cpu_map *cpus;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_TRACEPOINT,
+ .sample_period = 1,
+ .wakeup_watermark = 1,
+ .disabled = 1,
+ };
+ cpu_set_t saved_mask;
+ char path[PATH_MAX];
+ int id, err, cpu, tmp;
+ union perf_event *event;
+ int count = 0;
+
+ snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
+ sysfs__mountpoint());
+
+ if (filename__read_int(path, &id)) {
+ fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
+ return -1;
+ }
+
+ attr.config = id;
+
+ cpus = perf_cpu_map__new(NULL);
+ __T("failed to create cpus", cpus);
+
+ evlist = perf_evlist__new();
+ __T("failed to create evlist", evlist);
+
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel1", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ perf_evlist__set_maps(evlist, cpus, NULL);
+
+ err = perf_evlist__open(evlist);
+ __T("failed to open evlist", err == 0);
+
+ err = perf_evlist__mmap(evlist, 4);
+ __T("failed to mmap evlist", err == 0);
+
+ perf_evlist__enable(evlist);
+
+ err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
+ __T("sched_getaffinity failed", err == 0);
+
+ perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+ CPU_SET(cpu, &mask);
+
+ err = sched_setaffinity(0, sizeof(mask), &mask);
+ __T("sched_setaffinity failed", err == 0);
+
+ prctl(0, 0, 0, 0, 0);
+ }
+
+ err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
+ __T("sched_setaffinity failed", err == 0);
+
+ perf_evlist__disable(evlist);
+
+ perf_evlist__for_each_mmap(evlist, map, false) {
+ if (perf_mmap__read_init(map) < 0)
+ continue;
+
+ while ((event = perf_mmap__read_event(map)) != NULL) {
+ count++;
+ perf_mmap__consume(map);
+ }
+
+ perf_mmap__read_done(map);
+ }
+
+ /* calls perf_evlist__munmap/perf_evlist__close */
+ perf_evlist__delete(evlist);
+
+ /*
+ * The generated prctl events should match the
+ * number of cpus or be bigger (we are system-wide).
+ */
+ __T("failed count", count >= perf_cpu_map__nr(cpus));
+
+ perf_cpu_map__put(cpus);
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
__T_START;
@@ -309,6 +405,7 @@ int main(int argc, char **argv)
test_stat_thread();
test_stat_thread_enable();
test_mmap_thread();
+ test_mmap_cpus();

__T_OK;
return 0;
--
2.21.0

2019-10-18 15:37:06

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 02/10] libperf: Move mmap allocation to perf_evlist__mmap_ops::get

Moving allocation of mmap array into perf_evlist__mmap_ops::get,
so we centralize the mmap allocation.

Moving also nr_mmap setup to perf_evlist__mmap_ops so it's
centralized and shared by both perf and libperf mmap code.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/evlist.c | 42 ++++++++++++++++++++++++----------------
tools/perf/util/evlist.c | 24 +++++++++--------------
2 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c
index 854efff1519d..73aac6bb2ac5 100644
--- a/tools/perf/lib/evlist.c
+++ b/tools/perf/lib/evlist.c
@@ -338,10 +338,6 @@ static struct perf_mmap* perf_evlist__alloc_mmap(struct perf_evlist *evlist, boo
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;
@@ -384,18 +380,22 @@ static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
static struct perf_mmap*
perf_evlist__mmap_cb_get(struct perf_evlist *evlist, bool overwrite, int idx)
{
- struct perf_mmap *map = &evlist->mmap[idx];
+ struct perf_mmap *maps;

- 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];
+ maps = overwrite ? evlist->mmap_ovw : evlist->mmap;
+
+ if (!maps) {
+ maps = perf_evlist__alloc_mmap(evlist, overwrite);
+ if (!maps)
+ return NULL;
+
+ if (overwrite)
+ evlist->mmap_ovw = maps;
+ else
+ evlist->mmap = maps;
}

- return map;
+ return &maps[idx];
}

#define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y))
@@ -556,6 +556,17 @@ mmap_per_cpu(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops,
return -1;
}

+static int perf_evlist__nr_mmaps(struct perf_evlist *evlist)
+{
+ int nr_mmaps;
+
+ nr_mmaps = perf_cpu_map__nr(evlist->cpus);
+ if (perf_cpu_map__empty(evlist->cpus))
+ nr_mmaps = perf_thread_map__nr(evlist->threads);
+
+ return nr_mmaps;
+}
+
int perf_evlist__mmap_ops(struct perf_evlist *evlist,
struct perf_evlist_mmap_ops *ops,
struct perf_mmap_param *mp)
@@ -567,10 +578,7 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
if (!ops || !ops->get || !ops->mmap)
return -EINVAL;

- if (!evlist->mmap)
- evlist->mmap = perf_evlist__alloc_mmap(evlist, false);
- if (!evlist->mmap)
- return -ENOMEM;
+ evlist->nr_mmaps = perf_evlist__nr_mmaps(evlist);

perf_evlist__for_each_entry(evlist, evsel) {
if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6cda5a311ba5..5cded4ec5806 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -599,9 +599,6 @@ static struct mmap *evlist__alloc_mmap(struct evlist *evlist,
int i;
struct mmap *map;

- evlist->core.nr_mmaps = perf_cpu_map__nr(evlist->core.cpus);
- if (perf_cpu_map__empty(evlist->core.cpus))
- evlist->core.nr_mmaps = perf_thread_map__nr(evlist->core.threads);
map = zalloc(evlist->core.nr_mmaps * sizeof(struct mmap));
if (!map)
return NULL;
@@ -639,19 +636,21 @@ static struct perf_mmap*
perf_evlist__mmap_cb_get(struct perf_evlist *_evlist, bool overwrite, int idx)
{
struct evlist *evlist = container_of(_evlist, struct evlist, core);
- struct mmap *maps = evlist->mmap;
+ struct mmap *maps;

- if (overwrite) {
- maps = evlist->overwrite_mmap;
+ maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;

- if (!maps) {
- maps = evlist__alloc_mmap(evlist, true);
- if (!maps)
- return NULL;
+ if (!maps) {
+ maps = evlist__alloc_mmap(evlist, overwrite);
+ if (!maps)
+ return NULL;

+ if (overwrite) {
evlist->overwrite_mmap = maps;
if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
+ } else {
+ evlist->mmap = maps;
}
}

@@ -812,11 +811,6 @@ int evlist__mmap_ex(struct evlist *evlist, unsigned int pages,
.mmap = perf_evlist__mmap_cb_mmap,
};

- if (!evlist->mmap)
- evlist->mmap = evlist__alloc_mmap(evlist, false);
- if (!evlist->mmap)
- return -ENOMEM;
-
evlist->core.mmap_len = evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->core.mmap_len);
mp.core.mask = evlist->core.mmap_len - page_size - 1;
--
2.21.0

2019-10-18 15:37:42

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 03/10] libperf: Move mask setup to perf_evlist__mmap_ops function

Moving mask setup to perf_evlist__mmap_ops function,
because it's same on both perf and libperf path.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/evlist.c | 3 ++-
tools/perf/util/evlist.c | 1 -
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c
index 73aac6bb2ac5..205ddbb80bc1 100644
--- a/tools/perf/lib/evlist.c
+++ b/tools/perf/lib/evlist.c
@@ -578,6 +578,8 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
if (!ops || !ops->get || !ops->mmap)
return -EINVAL;

+ mp->mask = evlist->mmap_len - page_size - 1;
+
evlist->nr_mmaps = perf_evlist__nr_mmaps(evlist);

perf_evlist__for_each_entry(evlist, evsel) {
@@ -605,7 +607,6 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages)
};

evlist->mmap_len = (pages + 1) * page_size;
- mp.mask = evlist->mmap_len - page_size - 1;

return perf_evlist__mmap_ops(evlist, &ops, &mp);
}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 5cded4ec5806..fdce590d2278 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -813,7 +813,6 @@ int evlist__mmap_ex(struct evlist *evlist, unsigned int pages,

evlist->core.mmap_len = evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->core.mmap_len);
- mp.core.mask = evlist->core.mmap_len - page_size - 1;

auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->core.mmap_len,
auxtrace_pages, auxtrace_overwrite);
--
2.21.0

2019-10-18 15:37:44

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 04/10] libperf: Link static tests with libapi.a

Both static and dynamic tests needs to link libapi.a,
because it's using its functions. Adding also include
path for libapi includes.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/Makefile | 1 +
tools/perf/lib/tests/Makefile | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile
index 0889c9c3ec19..0f233638ef1f 100644
--- a/tools/perf/lib/Makefile
+++ b/tools/perf/lib/Makefile
@@ -107,6 +107,7 @@ else
endif

LIBAPI = $(API_PATH)libapi.a
+export LIBAPI

$(LIBAPI): FORCE
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile
index 1ee4e9ba848b..a43cd08c5c03 100644
--- a/tools/perf/lib/tests/Makefile
+++ b/tools/perf/lib/tests/Makefile
@@ -16,13 +16,13 @@ all:

include $(srctree)/tools/scripts/Makefile.include

-INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include
+INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include -I$(srctree)/tools/lib

$(TESTS_A): FORCE
- $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a
+ $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a $(LIBAPI)

$(TESTS_SO): FORCE
- $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -L.. -o $@ $(subst -so,.c,$@) -lperf
+ $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -L.. -o $@ $(subst -so,.c,$@) $(LIBAPI) -lperf

all: $(TESTS_A) $(TESTS_SO)

--
2.21.0

2019-10-18 15:38:06

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 10/10] libperf: Add pr_err macro

And missing include for "perf/core.h" header, which provides
LIBPERF_* debug levels and adding missing pr_err support.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/include/perf/core.h | 1 +
tools/perf/lib/internal.h | 3 +++
2 files changed, 4 insertions(+)

diff --git a/tools/perf/lib/include/perf/core.h b/tools/perf/lib/include/perf/core.h
index 2a80e4b6f819..a3f6d68edad7 100644
--- a/tools/perf/lib/include/perf/core.h
+++ b/tools/perf/lib/include/perf/core.h
@@ -9,6 +9,7 @@
#endif

enum libperf_print_level {
+ LIBPERF_ERR,
LIBPERF_WARN,
LIBPERF_INFO,
LIBPERF_DEBUG,
diff --git a/tools/perf/lib/internal.h b/tools/perf/lib/internal.h
index 37db745e1502..2c27e158de6b 100644
--- a/tools/perf/lib/internal.h
+++ b/tools/perf/lib/internal.h
@@ -2,6 +2,8 @@
#ifndef __LIBPERF_INTERNAL_H
#define __LIBPERF_INTERNAL_H

+#include <perf/core.h>
+
void libperf_print(enum libperf_print_level level,
const char *format, ...)
__attribute__((format(printf, 2, 3)));
@@ -11,6 +13,7 @@ do { \
libperf_print(level, "libperf: " fmt, ##__VA_ARGS__); \
} while (0)

+#define pr_err(fmt, ...) __pr(LIBPERF_ERR, fmt, ##__VA_ARGS__)
#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__)
--
2.21.0

2019-10-18 15:38:07

by Jiri Olsa

[permalink] [raw]
Subject: [PATCH 06/10] libperf: Add tests_mmap_thread test

Adding mmaping tests that generates 100 prctl calls
in monitored child process and validates it gets
100 events in ring buffer.

Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Jiri Olsa <[email protected]>
---
tools/perf/lib/tests/test-evlist.c | 119 +++++++++++++++++++++++++++++
1 file changed, 119 insertions(+)

diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
index e6b2ab2e2bde..90a1869ba4b1 100644
--- a/tools/perf/lib/tests/test-evlist.c
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -1,12 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdarg.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <linux/perf_event.h>
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
#include <perf/cpumap.h>
#include <perf/threadmap.h>
#include <perf/evlist.h>
#include <perf/evsel.h>
+#include <perf/mmap.h>
+#include <perf/event.h>
#include <internal/tests.h>
+#include <api/fs/fs.h>

static int libperf_print(enum libperf_print_level level,
const char *fmt, va_list ap)
@@ -181,6 +190,115 @@ static int test_stat_thread_enable(void)
return 0;
}

+static int test_mmap_thread(void)
+{
+ struct perf_evlist *evlist;
+ struct perf_evsel *evsel;
+ struct perf_mmap *map;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_TRACEPOINT,
+ .sample_period = 1,
+ .wakeup_watermark = 1,
+ .disabled = 1,
+ };
+ char path[PATH_MAX];
+ int id, err, pid, go_pipe[2];
+ union perf_event *event;
+ char bf;
+ int count = 0;
+
+ snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
+ sysfs__mountpoint());
+
+ if (filename__read_int(path, &id)) {
+ fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
+ return -1;
+ }
+
+ attr.config = id;
+
+ err = pipe(go_pipe);
+ __T("failed to create pipe", err == 0);
+
+ fflush(NULL);
+
+ pid = fork();
+ if (!pid) {
+ int i;
+
+ read(go_pipe[0], &bf, 1);
+
+ /* Generate 100 prctl calls. */
+ for (i = 0; i < 100; i++)
+ prctl(0, 0, 0, 0, 0);
+
+ exit(0);
+ }
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ cpus = perf_cpu_map__dummy_new();
+ __T("failed to create cpus", cpus);
+
+ perf_thread_map__set_pid(threads, 0, pid);
+
+ evlist = perf_evlist__new();
+ __T("failed to create evlist", evlist);
+
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel1", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ perf_evlist__set_maps(evlist, cpus, threads);
+
+ err = perf_evlist__open(evlist);
+ __T("failed to open evlist", err == 0);
+
+ err = perf_evlist__mmap(evlist, 4);
+ __T("failed to mmap evlist", err == 0);
+
+ perf_evlist__enable(evlist);
+
+ /* kick the child and wait for it to finish */
+ write(go_pipe[1], &bf, 1);
+ waitpid(pid, NULL, 0);
+
+ /*
+ * There's no need to call perf_evlist__disable,
+ * monitored process is dead now.
+ */
+
+ perf_evlist__for_each_mmap(evlist, map, false) {
+ if (perf_mmap__read_init(map) < 0)
+ continue;
+
+ while ((event = perf_mmap__read_event(map)) != NULL) {
+ count++;
+ perf_mmap__consume(map);
+ }
+
+ perf_mmap__read_done(map);
+ }
+
+ /* calls perf_evlist__munmap/perf_evlist__close */
+ perf_evlist__delete(evlist);
+
+ perf_thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+
+ /*
+ * The generated prctl calls should match the
+ * number of events in the buffer.
+ */
+ __T("failed count", count == 100);
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
__T_START;
@@ -190,6 +308,7 @@ int main(int argc, char **argv)
test_stat_cpu();
test_stat_thread();
test_stat_thread_enable();
+ test_mmap_thread();

__T_OK;
return 0;
--
2.21.0

2019-10-19 09:01:07

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 05/10] libperf: Add _GNU_SOURCE define to compilation


Why?


Em Thu, Oct 17, 2019 at 12:59:13PM +0200, Jiri Olsa escreveu:
> Link: http://lkml.kernel.org/n/[email protected]
> Signed-off-by: Jiri Olsa <[email protected]>
> ---
> tools/perf/lib/Makefile | 1 +
> tools/perf/lib/tests/Makefile | 2 ++
> 2 files changed, 3 insertions(+)
>
> diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile
> index 0f233638ef1f..20396f68fcad 100644
> --- a/tools/perf/lib/Makefile
> +++ b/tools/perf/lib/Makefile
> @@ -73,6 +73,7 @@ override CFLAGS += -Werror -Wall
> override CFLAGS += -fPIC
> override CFLAGS += $(INCLUDES)
> override CFLAGS += -fvisibility=hidden
> +override CFLAGS += -D_GNU_SOURCE
>
> all:
>
> diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile
> index a43cd08c5c03..78c3d8c83c53 100644
> --- a/tools/perf/lib/tests/Makefile
> +++ b/tools/perf/lib/tests/Makefile
> @@ -12,6 +12,8 @@ else
> CFLAGS := -g -Wall
> endif
>
> +CFLAGS += -D_GNU_SOURCE
> +
> all:
>
> include $(srctree)/tools/scripts/Makefile.include
> --
> 2.21.0

--

- Arnaldo

2019-10-19 09:02:37

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 07/10] libperf: Add tests_mmap_cpus test

Em Thu, Oct 17, 2019 at 12:59:15PM +0200, Jiri Olsa escreveu:
> Adding mmaping tests that generates prctl call on
> every cpu validates it gets all the related events
> in ring buffer.

So _here_ we need _GNU_SOURCE, for this specific test:

LINK test-evlist-a
test-evlist.c: In function ‘test_mmap_cpus’:
test-evlist.c:352:8: warning: implicit declaration of function ‘sched_getaffinity’ [-Wimplicit-function-declaration]
352 | err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
| ^~~~~~~~~~~~~~~~~
test-evlist.c:358:3: warning: implicit declaration of function ‘CPU_ZERO’ [-Wimplicit-function-declaration]
358 | CPU_ZERO(&mask);
| ^~~~~~~~
test-evlist.c:359:3: warning: implicit declaration of function ‘CPU_SET’ [-Wimplicit-function-declaration]
359 | CPU_SET(cpu, &mask);
| ^~~~~~~
test-evlist.c:361:9: warning: implicit declaration of function ‘sched_setaffinity’ [-Wimplicit-function-declaration]
361 | err = sched_setaffinity(0, sizeof(mask), &mask);
| ^~~~~~~~~~~~~~~~~
/usr/bin/ld: /tmp/ccOhNrLC.o: in function `test_mmap_cpus':
/home/acme/git/perf/tools/perf/lib/tests/test-evlist.c:358: undefined reference to `CPU_ZERO'
/usr/bin/ld: /home/acme/git/perf/tools/perf/lib/tests/test-evlist.c:359: undefined reference to `CPU_SET'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:22: test-evlist-a] Error 1
make: *** [Makefile:143: tests] Error 2
make: Leaving directory '/home/acme/git/perf/tools/perf/lib'
[root@quaco perf]#

> Link: http://lkml.kernel.org/n/[email protected]
> Signed-off-by: Jiri Olsa <[email protected]>
> ---
> tools/perf/lib/tests/test-evlist.c | 97 ++++++++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
>
> diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
> index 90a1869ba4b1..d8c52ebfa53a 100644
> --- a/tools/perf/lib/tests/test-evlist.c
> +++ b/tools/perf/lib/tests/test-evlist.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> #include <stdio.h>
> +#include <sched.h>
> #include <stdarg.h>
> #include <unistd.h>
> #include <stdlib.h>
> @@ -299,6 +300,101 @@ static int test_mmap_thread(void)
> return 0;
> }
>
> +static int test_mmap_cpus(void)
> +{
> + struct perf_evlist *evlist;
> + struct perf_evsel *evsel;
> + struct perf_mmap *map;
> + struct perf_cpu_map *cpus;
> + struct perf_event_attr attr = {
> + .type = PERF_TYPE_TRACEPOINT,
> + .sample_period = 1,
> + .wakeup_watermark = 1,
> + .disabled = 1,
> + };
> + cpu_set_t saved_mask;
> + char path[PATH_MAX];
> + int id, err, cpu, tmp;
> + union perf_event *event;
> + int count = 0;
> +
> + snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
> + sysfs__mountpoint());
> +
> + if (filename__read_int(path, &id)) {
> + fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
> + return -1;
> + }
> +
> + attr.config = id;
> +
> + cpus = perf_cpu_map__new(NULL);
> + __T("failed to create cpus", cpus);
> +
> + evlist = perf_evlist__new();
> + __T("failed to create evlist", evlist);
> +
> + evsel = perf_evsel__new(&attr);
> + __T("failed to create evsel1", evsel);
> +
> + perf_evlist__add(evlist, evsel);
> +
> + perf_evlist__set_maps(evlist, cpus, NULL);
> +
> + err = perf_evlist__open(evlist);
> + __T("failed to open evlist", err == 0);
> +
> + err = perf_evlist__mmap(evlist, 4);
> + __T("failed to mmap evlist", err == 0);
> +
> + perf_evlist__enable(evlist);
> +
> + err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
> + __T("sched_getaffinity failed", err == 0);
> +
> + perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
> + cpu_set_t mask;
> +
> + CPU_ZERO(&mask);
> + CPU_SET(cpu, &mask);
> +
> + err = sched_setaffinity(0, sizeof(mask), &mask);
> + __T("sched_setaffinity failed", err == 0);
> +
> + prctl(0, 0, 0, 0, 0);
> + }
> +
> + err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
> + __T("sched_setaffinity failed", err == 0);
> +
> + perf_evlist__disable(evlist);
> +
> + perf_evlist__for_each_mmap(evlist, map, false) {
> + if (perf_mmap__read_init(map) < 0)
> + continue;
> +
> + while ((event = perf_mmap__read_event(map)) != NULL) {
> + count++;
> + perf_mmap__consume(map);
> + }
> +
> + perf_mmap__read_done(map);
> + }
> +
> + /* calls perf_evlist__munmap/perf_evlist__close */
> + perf_evlist__delete(evlist);
> +
> + /*
> + * The generated prctl events should match the
> + * number of cpus or be bigger (we are system-wide).
> + */
> + __T("failed count", count >= perf_cpu_map__nr(cpus));
> +
> + perf_cpu_map__put(cpus);
> +
> + return 0;
> +}
> +
> int main(int argc, char **argv)
> {
> __T_START;
> @@ -309,6 +405,7 @@ int main(int argc, char **argv)
> test_stat_thread();
> test_stat_thread_enable();
> test_mmap_thread();
> + test_mmap_cpus();
>
> __T_OK;
> return 0;
> --
> 2.21.0

--

- Arnaldo

2019-10-19 09:04:12

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCHv3 00/10] libperf: Add sampling interface (leftover)

Em Thu, Oct 17, 2019 at 12:59:08PM +0200, Jiri Olsa escreveu:
> hi,
> sending changes for exporting basic sampling interface
> in libperf. It's now possible to use following code in
> applications via libperf:


Thanks, applied.

- Arnaldo
> --- (example is without error checks for simplicity)
>
> struct perf_event_attr attr = {
> .type = PERF_TYPE_TRACEPOINT,
> .sample_period = 1,
> .wakeup_watermark = 1,
> .disabled = 1,
> };
> /* ... setup attr */
>
> cpus = perf_cpu_map__new(NULL);
>
> evlist = perf_evlist__new();
> evsel = perf_evsel__new(&attr);
> perf_evlist__add(evlist, evsel);
>
> perf_evlist__set_maps(evlist, cpus, NULL);
>
> err = perf_evlist__open(evlist);
> err = perf_evlist__mmap(evlist, 4);
>
> err = perf_evlist__enable(evlist);
>
> /* ... monitored area, plus all the other cpus */
>
> err = perf_evlist__disable(evlist);
>
> perf_evlist__for_each_mmap(evlist, map) {
> if (perf_mmap__read_init(map) < 0)
> continue;
>
> while ((event = perf_mmap__read_event(map)) != NULL) {
> perf_mmap__consume(map);
> }
>
> perf_mmap__read_done(map);
> }
>
> perf_evlist__delete(evlist);
> perf_cpu_map__put(cpus);
>
> --- (end)
>
> Nothing is carved in stone so far, the interface is exported
> as is available in perf now and we can change it as we want.
>
> New tests are added in test-evlist.c to do thread and cpu based
> sampling.
>
> All the functionality should not change, however there's considerable
> mmap code rewrite.
>
> Now we have perf_evlist__mmap_ops called by both perf and libperf
> mmaps functions with specific 'struct perf_evlist_mmap_ops'
> callbacks:
>
> - get - to get mmap object, both libperf and perf use different
> objects, because perf needs to carry more data for aio,
> compression and auxtrace
> - mmap - to actually mmap the object, it's simple mmap for libperf,
> but more work for perf wrt aio, compression and auxtrace
> - idx - callback to get current IDs, used only in perf for auxtrace
> setup
>
>
> It would be great if guys could run your usual workloads to see if all
> is fine.. so far so good in my tests ;-)
>
>
> It's also available in here:
> git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
> perf/lib
>
> v3 changes:
> - changed mmap0 and mmap_ovw0 to mmap_first and mmap_ovw_first
> - rebased to latest perf/core
> - portion of patches already taken
>
> v2 changes:
> - rebased to latest perf/core
> - portion of patches already taken
> - explained mmap refcnt management in following patch changelog:
> libperf: Centralize map refcnt setting
>
> thanks,
> jirka
>
>
> Cc: Kan Liang <[email protected]>
> Cc: Steven Rostedt <[email protected]>
> Cc: Adrian Hunter <[email protected]>
> Cc: Ian Rogers <[email protected]>
> Cc: Stephane Eranian <[email protected]>
> Cc: Song Liu <[email protected]>
> Cc: Alexey Budankov <[email protected]>
> Cc: Andi Kleen <[email protected]>
> ---
> Jiri Olsa (10):
> libperf: Add perf_evlist__for_each_mmap function
> libperf: Move mmap allocation to perf_evlist__mmap_ops::get
> libperf: Move mask setup to perf_evlist__mmap_ops function
> libperf: Link static tests with libapi.a
> libperf: Add _GNU_SOURCE define to compilation
> libperf: Add tests_mmap_thread test
> libperf: Add tests_mmap_cpus test
> libperf: Keep count of failed tests
> libperf: Do not export perf_evsel__init/perf_evlist__init
> libperf: Add pr_err macro
>
> tools/perf/lib/Makefile | 2 ++
> tools/perf/lib/evlist.c | 71 ++++++++++++++++++++++++++++++++++++++---------------
> tools/perf/lib/include/internal/evlist.h | 3 +++
> tools/perf/lib/include/internal/evsel.h | 1 +
> tools/perf/lib/include/internal/mmap.h | 5 ++--
> tools/perf/lib/include/internal/tests.h | 20 ++++++++++++---
> tools/perf/lib/include/perf/core.h | 1 +
> tools/perf/lib/include/perf/evlist.h | 10 +++++++-
> tools/perf/lib/include/perf/evsel.h | 2 --
> tools/perf/lib/internal.h | 3 +++
> tools/perf/lib/libperf.map | 3 +--
> tools/perf/lib/mmap.c | 6 +++--
> tools/perf/lib/tests/Makefile | 8 +++---
> tools/perf/lib/tests/test-cpumap.c | 2 +-
> tools/perf/lib/tests/test-evlist.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> tools/perf/lib/tests/test-evsel.c | 2 +-
> tools/perf/lib/tests/test-threadmap.c | 2 +-
> tools/perf/util/evlist.c | 29 +++++++++-------------
> 18 files changed, 333 insertions(+), 55 deletions(-)

--

- Arnaldo

2019-10-19 09:05:20

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 07/10] libperf: Add tests_mmap_cpus test

Em Fri, Oct 18, 2019 at 03:14:29PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Thu, Oct 17, 2019 at 12:59:15PM +0200, Jiri Olsa escreveu:
> > Adding mmaping tests that generates prctl call on
> > every cpu validates it gets all the related events
> > in ring buffer.
>
> So _here_ we need _GNU_SOURCE, for this specific test:

Added, to this test:

[acme@quaco perf]$ git diff
diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
index d8c52ebfa53a..741bc1bb4524 100644
--- a/tools/perf/lib/tests/test-evlist.c
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-#include <stdio.h>
+#define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
#include <sched.h>
+#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
[acme@quaco perf]$

We can go the big hammer way if this is more generally needed, but first
lets try to use it only when needed, ok?

- Arnaldo

> LINK test-evlist-a
> test-evlist.c: In function ‘test_mmap_cpus’:
> test-evlist.c:352:8: warning: implicit declaration of function ‘sched_getaffinity’ [-Wimplicit-function-declaration]
> 352 | err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
> | ^~~~~~~~~~~~~~~~~
> test-evlist.c:358:3: warning: implicit declaration of function ‘CPU_ZERO’ [-Wimplicit-function-declaration]
> 358 | CPU_ZERO(&mask);
> | ^~~~~~~~
> test-evlist.c:359:3: warning: implicit declaration of function ‘CPU_SET’ [-Wimplicit-function-declaration]
> 359 | CPU_SET(cpu, &mask);
> | ^~~~~~~
> test-evlist.c:361:9: warning: implicit declaration of function ‘sched_setaffinity’ [-Wimplicit-function-declaration]
> 361 | err = sched_setaffinity(0, sizeof(mask), &mask);
> | ^~~~~~~~~~~~~~~~~
> /usr/bin/ld: /tmp/ccOhNrLC.o: in function `test_mmap_cpus':
> /home/acme/git/perf/tools/perf/lib/tests/test-evlist.c:358: undefined reference to `CPU_ZERO'
> /usr/bin/ld: /home/acme/git/perf/tools/perf/lib/tests/test-evlist.c:359: undefined reference to `CPU_SET'
> collect2: error: ld returned 1 exit status
> make[1]: *** [Makefile:22: test-evlist-a] Error 1
> make: *** [Makefile:143: tests] Error 2
> make: Leaving directory '/home/acme/git/perf/tools/perf/lib'
> [root@quaco perf]#
>
> > Link: http://lkml.kernel.org/n/[email protected]
> > Signed-off-by: Jiri Olsa <[email protected]>
> > ---
> > tools/perf/lib/tests/test-evlist.c | 97 ++++++++++++++++++++++++++++++
> > 1 file changed, 97 insertions(+)
> >
> > diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
> > index 90a1869ba4b1..d8c52ebfa53a 100644
> > --- a/tools/perf/lib/tests/test-evlist.c
> > +++ b/tools/perf/lib/tests/test-evlist.c
> > @@ -1,5 +1,6 @@
> > // SPDX-License-Identifier: GPL-2.0
> > #include <stdio.h>
> > +#include <sched.h>
> > #include <stdarg.h>
> > #include <unistd.h>
> > #include <stdlib.h>
> > @@ -299,6 +300,101 @@ static int test_mmap_thread(void)
> > return 0;
> > }
> >
> > +static int test_mmap_cpus(void)
> > +{
> > + struct perf_evlist *evlist;
> > + struct perf_evsel *evsel;
> > + struct perf_mmap *map;
> > + struct perf_cpu_map *cpus;
> > + struct perf_event_attr attr = {
> > + .type = PERF_TYPE_TRACEPOINT,
> > + .sample_period = 1,
> > + .wakeup_watermark = 1,
> > + .disabled = 1,
> > + };
> > + cpu_set_t saved_mask;
> > + char path[PATH_MAX];
> > + int id, err, cpu, tmp;
> > + union perf_event *event;
> > + int count = 0;
> > +
> > + snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
> > + sysfs__mountpoint());
> > +
> > + if (filename__read_int(path, &id)) {
> > + fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
> > + return -1;
> > + }
> > +
> > + attr.config = id;
> > +
> > + cpus = perf_cpu_map__new(NULL);
> > + __T("failed to create cpus", cpus);
> > +
> > + evlist = perf_evlist__new();
> > + __T("failed to create evlist", evlist);
> > +
> > + evsel = perf_evsel__new(&attr);
> > + __T("failed to create evsel1", evsel);
> > +
> > + perf_evlist__add(evlist, evsel);
> > +
> > + perf_evlist__set_maps(evlist, cpus, NULL);
> > +
> > + err = perf_evlist__open(evlist);
> > + __T("failed to open evlist", err == 0);
> > +
> > + err = perf_evlist__mmap(evlist, 4);
> > + __T("failed to mmap evlist", err == 0);
> > +
> > + perf_evlist__enable(evlist);
> > +
> > + err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
> > + __T("sched_getaffinity failed", err == 0);
> > +
> > + perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
> > + cpu_set_t mask;
> > +
> > + CPU_ZERO(&mask);
> > + CPU_SET(cpu, &mask);
> > +
> > + err = sched_setaffinity(0, sizeof(mask), &mask);
> > + __T("sched_setaffinity failed", err == 0);
> > +
> > + prctl(0, 0, 0, 0, 0);
> > + }
> > +
> > + err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
> > + __T("sched_setaffinity failed", err == 0);
> > +
> > + perf_evlist__disable(evlist);
> > +
> > + perf_evlist__for_each_mmap(evlist, map, false) {
> > + if (perf_mmap__read_init(map) < 0)
> > + continue;
> > +
> > + while ((event = perf_mmap__read_event(map)) != NULL) {
> > + count++;
> > + perf_mmap__consume(map);
> > + }
> > +
> > + perf_mmap__read_done(map);
> > + }
> > +
> > + /* calls perf_evlist__munmap/perf_evlist__close */
> > + perf_evlist__delete(evlist);
> > +
> > + /*
> > + * The generated prctl events should match the
> > + * number of cpus or be bigger (we are system-wide).
> > + */
> > + __T("failed count", count >= perf_cpu_map__nr(cpus));
> > +
> > + perf_cpu_map__put(cpus);
> > +
> > + return 0;
> > +}
> > +
> > int main(int argc, char **argv)
> > {
> > __T_START;
> > @@ -309,6 +405,7 @@ int main(int argc, char **argv)
> > test_stat_thread();
> > test_stat_thread_enable();
> > test_mmap_thread();
> > + test_mmap_cpus();
> >
> > __T_OK;
> > return 0;
> > --
> > 2.21.0
>
> --
>
> - Arnaldo

--

- Arnaldo

2019-10-19 17:39:30

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 05/10] libperf: Add _GNU_SOURCE define to compilation

On Fri, Oct 18, 2019 at 03:07:38PM -0300, Arnaldo Carvalho de Melo wrote:
>
> Why?

it's passed when the library is compiled with perf, but not
when you compile it standalone.. and 2 '-D_GNU_SOURCE' on
command line are ok

jirka

>
>
> Em Thu, Oct 17, 2019 at 12:59:13PM +0200, Jiri Olsa escreveu:
> > Link: http://lkml.kernel.org/n/[email protected]
> > Signed-off-by: Jiri Olsa <[email protected]>
> > ---
> > tools/perf/lib/Makefile | 1 +
> > tools/perf/lib/tests/Makefile | 2 ++
> > 2 files changed, 3 insertions(+)
> >
> > diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile
> > index 0f233638ef1f..20396f68fcad 100644
> > --- a/tools/perf/lib/Makefile
> > +++ b/tools/perf/lib/Makefile
> > @@ -73,6 +73,7 @@ override CFLAGS += -Werror -Wall
> > override CFLAGS += -fPIC
> > override CFLAGS += $(INCLUDES)
> > override CFLAGS += -fvisibility=hidden
> > +override CFLAGS += -D_GNU_SOURCE
> >
> > all:
> >
> > diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile
> > index a43cd08c5c03..78c3d8c83c53 100644
> > --- a/tools/perf/lib/tests/Makefile
> > +++ b/tools/perf/lib/tests/Makefile
> > @@ -12,6 +12,8 @@ else
> > CFLAGS := -g -Wall
> > endif
> >
> > +CFLAGS += -D_GNU_SOURCE
> > +
> > all:
> >
> > include $(srctree)/tools/scripts/Makefile.include
> > --
> > 2.21.0
>
> --
>
> - Arnaldo

2019-10-19 17:47:13

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 07/10] libperf: Add tests_mmap_cpus test

On Fri, Oct 18, 2019 at 03:16:31PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Fri, Oct 18, 2019 at 03:14:29PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Thu, Oct 17, 2019 at 12:59:15PM +0200, Jiri Olsa escreveu:
> > > Adding mmaping tests that generates prctl call on
> > > every cpu validates it gets all the related events
> > > in ring buffer.
> >
> > So _here_ we need _GNU_SOURCE, for this specific test:
>
> Added, to this test:
>
> [acme@quaco perf]$ git diff
> diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
> index d8c52ebfa53a..741bc1bb4524 100644
> --- a/tools/perf/lib/tests/test-evlist.c
> +++ b/tools/perf/lib/tests/test-evlist.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0
> -#include <stdio.h>
> +#define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
> #include <sched.h>
> +#include <stdio.h>
> #include <stdarg.h>
> #include <unistd.h>
> #include <stdlib.h>
> [acme@quaco perf]$
>
> We can go the big hammer way if this is more generally needed, but first
> lets try to use it only when needed, ok?

ok, thanks

FYI so it's quite easy now to separate the lib and move it under
tools/lib/perf.. I'll post it together with docs/tutorial update

jirka

Subject: [tip: perf/core] libperf: Add tests_mmap_cpus test

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

Commit-ID: 37ac1bbdc31a2007f398b7caf0cbe522f1af9c6c
Gitweb: https://git.kernel.org/tip/37ac1bbdc31a2007f398b7caf0cbe522f1af9c6c
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:15 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Add tests_mmap_cpus test

Add mmaping tests that generates prctl call on every cpu validates it
gets all the related events in ring buffer.

Committer testing:

# make -C tools/perf/lib tests
make: Entering directory '/home/acme/git/perf/tools/perf/lib'
LINK test-cpumap-a
LINK test-threadmap-a
LINK test-evlist-a
LINK test-evsel-a
LINK test-cpumap-so
LINK test-threadmap-so
LINK test-evlist-so
LINK test-evsel-so
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...OK
make: Leaving directory '/home/acme/git/perf/tools/perf/lib'
#

Signed-off-by: Jiri Olsa <[email protected]>
Tested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
[ Added _GNU_SOURCE define for sched.h to get sched_[gs]et_affinity
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/tests/test-evlist.c | 98 +++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+)

diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
index 90a1869..741bc1b 100644
--- a/tools/perf/lib/tests/test-evlist.c
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
+#include <sched.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
@@ -299,6 +301,101 @@ static int test_mmap_thread(void)
return 0;
}

+static int test_mmap_cpus(void)
+{
+ struct perf_evlist *evlist;
+ struct perf_evsel *evsel;
+ struct perf_mmap *map;
+ struct perf_cpu_map *cpus;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_TRACEPOINT,
+ .sample_period = 1,
+ .wakeup_watermark = 1,
+ .disabled = 1,
+ };
+ cpu_set_t saved_mask;
+ char path[PATH_MAX];
+ int id, err, cpu, tmp;
+ union perf_event *event;
+ int count = 0;
+
+ snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
+ sysfs__mountpoint());
+
+ if (filename__read_int(path, &id)) {
+ fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
+ return -1;
+ }
+
+ attr.config = id;
+
+ cpus = perf_cpu_map__new(NULL);
+ __T("failed to create cpus", cpus);
+
+ evlist = perf_evlist__new();
+ __T("failed to create evlist", evlist);
+
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel1", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ perf_evlist__set_maps(evlist, cpus, NULL);
+
+ err = perf_evlist__open(evlist);
+ __T("failed to open evlist", err == 0);
+
+ err = perf_evlist__mmap(evlist, 4);
+ __T("failed to mmap evlist", err == 0);
+
+ perf_evlist__enable(evlist);
+
+ err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
+ __T("sched_getaffinity failed", err == 0);
+
+ perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+ CPU_SET(cpu, &mask);
+
+ err = sched_setaffinity(0, sizeof(mask), &mask);
+ __T("sched_setaffinity failed", err == 0);
+
+ prctl(0, 0, 0, 0, 0);
+ }
+
+ err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
+ __T("sched_setaffinity failed", err == 0);
+
+ perf_evlist__disable(evlist);
+
+ perf_evlist__for_each_mmap(evlist, map, false) {
+ if (perf_mmap__read_init(map) < 0)
+ continue;
+
+ while ((event = perf_mmap__read_event(map)) != NULL) {
+ count++;
+ perf_mmap__consume(map);
+ }
+
+ perf_mmap__read_done(map);
+ }
+
+ /* calls perf_evlist__munmap/perf_evlist__close */
+ perf_evlist__delete(evlist);
+
+ /*
+ * The generated prctl events should match the
+ * number of cpus or be bigger (we are system-wide).
+ */
+ __T("failed count", count >= perf_cpu_map__nr(cpus));
+
+ perf_cpu_map__put(cpus);
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
__T_START;
@@ -309,6 +406,7 @@ int main(int argc, char **argv)
test_stat_thread();
test_stat_thread_enable();
test_mmap_thread();
+ test_mmap_cpus();

__T_OK;
return 0;

Subject: [tip: perf/core] libperf: Add pr_err() macro

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

Commit-ID: dcc6854215f115efcbd79368bc07099c41de0b6c
Gitweb: https://git.kernel.org/tip/dcc6854215f115efcbd79368bc07099c41de0b6c
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:18 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Add pr_err() macro

And missing include for "perf/core.h" header, which provides LIBPERF_*
debug levels and add missing pr_err() support.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/include/perf/core.h | 1 +
tools/perf/lib/internal.h | 3 +++
2 files changed, 4 insertions(+)

diff --git a/tools/perf/lib/include/perf/core.h b/tools/perf/lib/include/perf/core.h
index 2a80e4b..a3f6d68 100644
--- a/tools/perf/lib/include/perf/core.h
+++ b/tools/perf/lib/include/perf/core.h
@@ -9,6 +9,7 @@
#endif

enum libperf_print_level {
+ LIBPERF_ERR,
LIBPERF_WARN,
LIBPERF_INFO,
LIBPERF_DEBUG,
diff --git a/tools/perf/lib/internal.h b/tools/perf/lib/internal.h
index 37db745..2c27e15 100644
--- a/tools/perf/lib/internal.h
+++ b/tools/perf/lib/internal.h
@@ -2,6 +2,8 @@
#ifndef __LIBPERF_INTERNAL_H
#define __LIBPERF_INTERNAL_H

+#include <perf/core.h>
+
void libperf_print(enum libperf_print_level level,
const char *format, ...)
__attribute__((format(printf, 2, 3)));
@@ -11,6 +13,7 @@ do { \
libperf_print(level, "libperf: " fmt, ##__VA_ARGS__); \
} while (0)

+#define pr_err(fmt, ...) __pr(LIBPERF_ERR, fmt, ##__VA_ARGS__)
#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__)

Subject: [tip: perf/core] libperf: Move mask setup to perf_evlist__mmap_ops()

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

Commit-ID: b6cd35e4e09c12f9478ed98cb015d4352fa98056
Gitweb: https://git.kernel.org/tip/b6cd35e4e09c12f9478ed98cb015d4352fa98056
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:11 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Move mask setup to perf_evlist__mmap_ops()

Move the mask setup to perf_evlist__mmap_ops(), because it's the same on
both perf and libperf path.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/evlist.c | 3 ++-
tools/perf/util/evlist.c | 1 -
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c
index 73aac6b..205ddbb 100644
--- a/tools/perf/lib/evlist.c
+++ b/tools/perf/lib/evlist.c
@@ -578,6 +578,8 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
if (!ops || !ops->get || !ops->mmap)
return -EINVAL;

+ mp->mask = evlist->mmap_len - page_size - 1;
+
evlist->nr_mmaps = perf_evlist__nr_mmaps(evlist);

perf_evlist__for_each_entry(evlist, evsel) {
@@ -605,7 +607,6 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages)
};

evlist->mmap_len = (pages + 1) * page_size;
- mp.mask = evlist->mmap_len - page_size - 1;

return perf_evlist__mmap_ops(evlist, &ops, &mp);
}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 5cded4e..fdce590 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -813,7 +813,6 @@ int evlist__mmap_ex(struct evlist *evlist, unsigned int pages,

evlist->core.mmap_len = evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->core.mmap_len);
- mp.core.mask = evlist->core.mmap_len - page_size - 1;

auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->core.mmap_len,
auxtrace_pages, auxtrace_overwrite);

Subject: [tip: perf/core] libperf: Keep count of failed tests

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

Commit-ID: 301a89f8cf628316eea6c768787a836b63a83439
Gitweb: https://git.kernel.org/tip/301a89f8cf628316eea6c768787a836b63a83439
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:16 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Keep count of failed tests

Keep the count of failed tests, so we get better output with failures,
like:

# make tests
...
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...FAILED test-evlist.c:53 failed to create evsel2
FAILED test-evlist.c:163 failed to create evsel2
FAILED test-evlist.c:287 failed count
FAILED (3)
- running test-evsel.c...OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...FAILED test-evlist.c:53 failed to create evsel2
FAILED test-evlist.c:163 failed to create evsel2
FAILED test-evlist.c:287 failed count
FAILED (3)
- running test-evsel.c...OK
...

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/include/internal/tests.h | 20 +++++++++++++++++---
tools/perf/lib/tests/test-cpumap.c | 2 +-
tools/perf/lib/tests/test-evlist.c | 2 +-
tools/perf/lib/tests/test-evsel.c | 2 +-
tools/perf/lib/tests/test-threadmap.c | 2 +-
5 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/tools/perf/lib/include/internal/tests.h b/tools/perf/lib/include/internal/tests.h
index b7a20cd..2093e88 100644
--- a/tools/perf/lib/include/internal/tests.h
+++ b/tools/perf/lib/include/internal/tests.h
@@ -4,14 +4,28 @@

#include <stdio.h>

-#define __T_START fprintf(stdout, "- running %s...", __FILE__)
-#define __T_OK fprintf(stdout, "OK\n")
-#define __T_FAIL fprintf(stdout, "FAIL\n")
+int tests_failed;
+
+#define __T_START \
+do { \
+ fprintf(stdout, "- running %s...", __FILE__); \
+ fflush(NULL); \
+ tests_failed = 0; \
+} while (0)
+
+#define __T_END \
+do { \
+ if (tests_failed) \
+ fprintf(stdout, " FAILED (%d)\n", tests_failed); \
+ else \
+ fprintf(stdout, "OK\n"); \
+} while (0)

#define __T(text, cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
+ tests_failed++; \
return -1; \
} \
} while (0)
diff --git a/tools/perf/lib/tests/test-cpumap.c b/tools/perf/lib/tests/test-cpumap.c
index aa34c20..c8d4509 100644
--- a/tools/perf/lib/tests/test-cpumap.c
+++ b/tools/perf/lib/tests/test-cpumap.c
@@ -26,6 +26,6 @@ int main(int argc, char **argv)
perf_cpu_map__put(cpus);
perf_cpu_map__put(cpus);

- __T_OK;
+ __T_END;
return 0;
}
diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
index 741bc1b..6d8ebe0 100644
--- a/tools/perf/lib/tests/test-evlist.c
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -408,6 +408,6 @@ int main(int argc, char **argv)
test_mmap_thread();
test_mmap_cpus();

- __T_OK;
+ __T_END;
return 0;
}
diff --git a/tools/perf/lib/tests/test-evsel.c b/tools/perf/lib/tests/test-evsel.c
index 1b6c428..135722a 100644
--- a/tools/perf/lib/tests/test-evsel.c
+++ b/tools/perf/lib/tests/test-evsel.c
@@ -130,6 +130,6 @@ int main(int argc, char **argv)
test_stat_thread();
test_stat_thread_enable();

- __T_OK;
+ __T_END;
return 0;
}
diff --git a/tools/perf/lib/tests/test-threadmap.c b/tools/perf/lib/tests/test-threadmap.c
index 8c5f472..7dc4d6f 100644
--- a/tools/perf/lib/tests/test-threadmap.c
+++ b/tools/perf/lib/tests/test-threadmap.c
@@ -26,6 +26,6 @@ int main(int argc, char **argv)
perf_thread_map__put(threads);
perf_thread_map__put(threads);

- __T_OK;
+ __T_END;
return 0;
}

Subject: [tip: perf/core] libperf: Do not export perf_evsel__init()/perf_evlist__init()

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

Commit-ID: c27feefea10aed40e82cd5c6b06a154e141dc038
Gitweb: https://git.kernel.org/tip/c27feefea10aed40e82cd5c6b06a154e141dc038
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:17 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Do not export perf_evsel__init()/perf_evlist__init()

There's no point in exporting perf_evsel__init()/perf_evlist__init(),
it's called from perf_evsel__new()/perf_evlist__new() respectively.

It's used only from perf where perf_evsel()/perf_evlist() is embedded
perf's evsel/evlist.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/include/internal/evlist.h | 1 +
tools/perf/lib/include/internal/evsel.h | 1 +
tools/perf/lib/include/perf/evlist.h | 1 -
tools/perf/lib/include/perf/evsel.h | 2 --
tools/perf/lib/libperf.map | 2 --
5 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/tools/perf/lib/include/internal/evlist.h b/tools/perf/lib/include/internal/evlist.h
index 20d90e2..a2fbccf 100644
--- a/tools/perf/lib/include/internal/evlist.h
+++ b/tools/perf/lib/include/internal/evlist.h
@@ -50,6 +50,7 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
struct perf_evlist_mmap_ops *ops,
struct perf_mmap_param *mp);

+void perf_evlist__init(struct perf_evlist *evlist);
void perf_evlist__exit(struct perf_evlist *evlist);

/**
diff --git a/tools/perf/lib/include/internal/evsel.h b/tools/perf/lib/include/internal/evsel.h
index a69b829..1ffd083 100644
--- a/tools/perf/lib/include/internal/evsel.h
+++ b/tools/perf/lib/include/internal/evsel.h
@@ -50,6 +50,7 @@ struct perf_evsel {
bool system_wide;
};

+void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr);
int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
void perf_evsel__close_fd(struct perf_evsel *evsel);
void perf_evsel__free_fd(struct perf_evsel *evsel);
diff --git a/tools/perf/lib/include/perf/evlist.h b/tools/perf/lib/include/perf/evlist.h
index 8c4b3c2..0a7479d 100644
--- a/tools/perf/lib/include/perf/evlist.h
+++ b/tools/perf/lib/include/perf/evlist.h
@@ -10,7 +10,6 @@ struct perf_evsel;
struct perf_cpu_map;
struct perf_thread_map;

-LIBPERF_API void perf_evlist__init(struct perf_evlist *evlist);
LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist,
struct perf_evsel *evsel);
LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist,
diff --git a/tools/perf/lib/include/perf/evsel.h b/tools/perf/lib/include/perf/evsel.h
index 4388667..557f581 100644
--- a/tools/perf/lib/include/perf/evsel.h
+++ b/tools/perf/lib/include/perf/evsel.h
@@ -21,8 +21,6 @@ struct perf_counts_values {
};
};

-LIBPERF_API void perf_evsel__init(struct perf_evsel *evsel,
- struct perf_event_attr *attr);
LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr);
LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel);
LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
diff --git a/tools/perf/lib/libperf.map b/tools/perf/lib/libperf.map
index 8be02af..7be1af8 100644
--- a/tools/perf/lib/libperf.map
+++ b/tools/perf/lib/libperf.map
@@ -21,7 +21,6 @@ LIBPERF_0.0.1 {
perf_evsel__delete;
perf_evsel__enable;
perf_evsel__disable;
- perf_evsel__init;
perf_evsel__open;
perf_evsel__close;
perf_evsel__read;
@@ -34,7 +33,6 @@ LIBPERF_0.0.1 {
perf_evlist__close;
perf_evlist__enable;
perf_evlist__disable;
- perf_evlist__init;
perf_evlist__add;
perf_evlist__remove;
perf_evlist__next;

Subject: [tip: perf/core] libperf: Add tests_mmap_thread test

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

Commit-ID: bd6b7736c1ed109f4d86f725e96a48fb81ce71f6
Gitweb: https://git.kernel.org/tip/bd6b7736c1ed109f4d86f725e96a48fb81ce71f6
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:14 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Add tests_mmap_thread test

Add mmaping tests that generates 100 prctl calls in monitored child
process and validates it gets 100 events in ring buffer.

Committer tests:

# make -C tools/perf/lib tests
make: Entering directory '/home/acme/git/perf/tools/perf/lib'
LINK test-cpumap-a
LINK test-threadmap-a
LINK test-evlist-a
LINK test-evsel-a
LINK test-cpumap-so
LINK test-threadmap-so
LINK test-evlist-so
LINK test-evsel-so
running static:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...OK
running dynamic:
- running test-cpumap.c...OK
- running test-threadmap.c...OK
- running test-evlist.c...OK
- running test-evsel.c...OK
make: Leaving directory '/home/acme/git/perf/tools/perf/lib'
#

Signed-off-by: Jiri Olsa <[email protected]>
Tested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/tests/test-evlist.c | 119 ++++++++++++++++++++++++++++-
1 file changed, 119 insertions(+)

diff --git a/tools/perf/lib/tests/test-evlist.c b/tools/perf/lib/tests/test-evlist.c
index e6b2ab2..90a1869 100644
--- a/tools/perf/lib/tests/test-evlist.c
+++ b/tools/perf/lib/tests/test-evlist.c
@@ -1,12 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdarg.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <linux/perf_event.h>
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
#include <perf/cpumap.h>
#include <perf/threadmap.h>
#include <perf/evlist.h>
#include <perf/evsel.h>
+#include <perf/mmap.h>
+#include <perf/event.h>
#include <internal/tests.h>
+#include <api/fs/fs.h>

static int libperf_print(enum libperf_print_level level,
const char *fmt, va_list ap)
@@ -181,6 +190,115 @@ static int test_stat_thread_enable(void)
return 0;
}

+static int test_mmap_thread(void)
+{
+ struct perf_evlist *evlist;
+ struct perf_evsel *evsel;
+ struct perf_mmap *map;
+ struct perf_cpu_map *cpus;
+ struct perf_thread_map *threads;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_TRACEPOINT,
+ .sample_period = 1,
+ .wakeup_watermark = 1,
+ .disabled = 1,
+ };
+ char path[PATH_MAX];
+ int id, err, pid, go_pipe[2];
+ union perf_event *event;
+ char bf;
+ int count = 0;
+
+ snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
+ sysfs__mountpoint());
+
+ if (filename__read_int(path, &id)) {
+ fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
+ return -1;
+ }
+
+ attr.config = id;
+
+ err = pipe(go_pipe);
+ __T("failed to create pipe", err == 0);
+
+ fflush(NULL);
+
+ pid = fork();
+ if (!pid) {
+ int i;
+
+ read(go_pipe[0], &bf, 1);
+
+ /* Generate 100 prctl calls. */
+ for (i = 0; i < 100; i++)
+ prctl(0, 0, 0, 0, 0);
+
+ exit(0);
+ }
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ cpus = perf_cpu_map__dummy_new();
+ __T("failed to create cpus", cpus);
+
+ perf_thread_map__set_pid(threads, 0, pid);
+
+ evlist = perf_evlist__new();
+ __T("failed to create evlist", evlist);
+
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel1", evsel);
+
+ perf_evlist__add(evlist, evsel);
+
+ perf_evlist__set_maps(evlist, cpus, threads);
+
+ err = perf_evlist__open(evlist);
+ __T("failed to open evlist", err == 0);
+
+ err = perf_evlist__mmap(evlist, 4);
+ __T("failed to mmap evlist", err == 0);
+
+ perf_evlist__enable(evlist);
+
+ /* kick the child and wait for it to finish */
+ write(go_pipe[1], &bf, 1);
+ waitpid(pid, NULL, 0);
+
+ /*
+ * There's no need to call perf_evlist__disable,
+ * monitored process is dead now.
+ */
+
+ perf_evlist__for_each_mmap(evlist, map, false) {
+ if (perf_mmap__read_init(map) < 0)
+ continue;
+
+ while ((event = perf_mmap__read_event(map)) != NULL) {
+ count++;
+ perf_mmap__consume(map);
+ }
+
+ perf_mmap__read_done(map);
+ }
+
+ /* calls perf_evlist__munmap/perf_evlist__close */
+ perf_evlist__delete(evlist);
+
+ perf_thread_map__put(threads);
+ perf_cpu_map__put(cpus);
+
+ /*
+ * The generated prctl calls should match the
+ * number of events in the buffer.
+ */
+ __T("failed count", count == 100);
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
__T_START;
@@ -190,6 +308,7 @@ int main(int argc, char **argv)
test_stat_cpu();
test_stat_thread();
test_stat_thread_enable();
+ test_mmap_thread();

__T_OK;
return 0;

Subject: [tip: perf/core] libperf: Move mmap allocation to perf_evlist__mmap_ops::get

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

Commit-ID: 3805e4f303314c2b53fb217dd8549a5b9eb06b11
Gitweb: https://git.kernel.org/tip/3805e4f303314c2b53fb217dd8549a5b9eb06b11
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:10 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Move mmap allocation to perf_evlist__mmap_ops::get

Move allocation of the mmap array into perf_evlist__mmap_ops::get, to
centralize the mmap allocation.

Also move nr_mmap setup to perf_evlist__mmap_ops so it's centralized and
shared by both perf and libperf mmap code.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/evlist.c | 42 +++++++++++++++++++++++----------------
tools/perf/util/evlist.c | 24 ++++++++--------------
2 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/tools/perf/lib/evlist.c b/tools/perf/lib/evlist.c
index 854efff..73aac6b 100644
--- a/tools/perf/lib/evlist.c
+++ b/tools/perf/lib/evlist.c
@@ -338,10 +338,6 @@ static struct perf_mmap* perf_evlist__alloc_mmap(struct perf_evlist *evlist, boo
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;
@@ -384,18 +380,22 @@ static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
static struct perf_mmap*
perf_evlist__mmap_cb_get(struct perf_evlist *evlist, bool overwrite, int idx)
{
- struct perf_mmap *map = &evlist->mmap[idx];
+ struct perf_mmap *maps;

- 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];
+ maps = overwrite ? evlist->mmap_ovw : evlist->mmap;
+
+ if (!maps) {
+ maps = perf_evlist__alloc_mmap(evlist, overwrite);
+ if (!maps)
+ return NULL;
+
+ if (overwrite)
+ evlist->mmap_ovw = maps;
+ else
+ evlist->mmap = maps;
}

- return map;
+ return &maps[idx];
}

#define FD(e, x, y) (*(int *) xyarray__entry(e->fd, x, y))
@@ -556,6 +556,17 @@ out_unmap:
return -1;
}

+static int perf_evlist__nr_mmaps(struct perf_evlist *evlist)
+{
+ int nr_mmaps;
+
+ nr_mmaps = perf_cpu_map__nr(evlist->cpus);
+ if (perf_cpu_map__empty(evlist->cpus))
+ nr_mmaps = perf_thread_map__nr(evlist->threads);
+
+ return nr_mmaps;
+}
+
int perf_evlist__mmap_ops(struct perf_evlist *evlist,
struct perf_evlist_mmap_ops *ops,
struct perf_mmap_param *mp)
@@ -567,10 +578,7 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist,
if (!ops || !ops->get || !ops->mmap)
return -EINVAL;

- if (!evlist->mmap)
- evlist->mmap = perf_evlist__alloc_mmap(evlist, false);
- if (!evlist->mmap)
- return -ENOMEM;
+ evlist->nr_mmaps = perf_evlist__nr_mmaps(evlist);

perf_evlist__for_each_entry(evlist, evsel) {
if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6cda5a3..5cded4e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -599,9 +599,6 @@ static struct mmap *evlist__alloc_mmap(struct evlist *evlist,
int i;
struct mmap *map;

- evlist->core.nr_mmaps = perf_cpu_map__nr(evlist->core.cpus);
- if (perf_cpu_map__empty(evlist->core.cpus))
- evlist->core.nr_mmaps = perf_thread_map__nr(evlist->core.threads);
map = zalloc(evlist->core.nr_mmaps * sizeof(struct mmap));
if (!map)
return NULL;
@@ -639,19 +636,21 @@ static struct perf_mmap*
perf_evlist__mmap_cb_get(struct perf_evlist *_evlist, bool overwrite, int idx)
{
struct evlist *evlist = container_of(_evlist, struct evlist, core);
- struct mmap *maps = evlist->mmap;
+ struct mmap *maps;

- if (overwrite) {
- maps = evlist->overwrite_mmap;
+ maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;

- if (!maps) {
- maps = evlist__alloc_mmap(evlist, true);
- if (!maps)
- return NULL;
+ if (!maps) {
+ maps = evlist__alloc_mmap(evlist, overwrite);
+ if (!maps)
+ return NULL;

+ if (overwrite) {
evlist->overwrite_mmap = maps;
if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
+ } else {
+ evlist->mmap = maps;
}
}

@@ -812,11 +811,6 @@ int evlist__mmap_ex(struct evlist *evlist, unsigned int pages,
.mmap = perf_evlist__mmap_cb_mmap,
};

- if (!evlist->mmap)
- evlist->mmap = evlist__alloc_mmap(evlist, false);
- if (!evlist->mmap)
- return -ENOMEM;
-
evlist->core.mmap_len = evlist__mmap_size(pages);
pr_debug("mmap size %zuB\n", evlist->core.mmap_len);
mp.core.mask = evlist->core.mmap_len - page_size - 1;

Subject: [tip: perf/core] libperf: Link static tests with libapi.a

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

Commit-ID: 395e62cde10df64122d708c68baee64b1d1622fc
Gitweb: https://git.kernel.org/tip/395e62cde10df64122d708c68baee64b1d1622fc
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:12 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

libperf: Link static tests with libapi.a

Both static and dynamic tests needs to link with libapi.a, because it's
using its functions. Also include path for libapi includes.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/lib/Makefile | 1 +
tools/perf/lib/tests/Makefile | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/perf/lib/Makefile b/tools/perf/lib/Makefile
index 0889c9c..0f23363 100644
--- a/tools/perf/lib/Makefile
+++ b/tools/perf/lib/Makefile
@@ -107,6 +107,7 @@ else
endif

LIBAPI = $(API_PATH)libapi.a
+export LIBAPI

$(LIBAPI): FORCE
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
diff --git a/tools/perf/lib/tests/Makefile b/tools/perf/lib/tests/Makefile
index 1ee4e9b..a43cd08 100644
--- a/tools/perf/lib/tests/Makefile
+++ b/tools/perf/lib/tests/Makefile
@@ -16,13 +16,13 @@ all:

include $(srctree)/tools/scripts/Makefile.include

-INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include
+INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include -I$(srctree)/tools/lib

$(TESTS_A): FORCE
- $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a
+ $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a $(LIBAPI)

$(TESTS_SO): FORCE
- $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -L.. -o $@ $(subst -so,.c,$@) -lperf
+ $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -L.. -o $@ $(subst -so,.c,$@) $(LIBAPI) -lperf

all: $(TESTS_A) $(TESTS_SO)

Subject: [tip: perf/core] libperf: Introduce perf_evlist__for_each_mmap()

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

Commit-ID: 6eb65f7a5cc553f5dffb5cea3a874f1087524d99
Gitweb: https://git.kernel.org/tip/6eb65f7a5cc553f5dffb5cea3a874f1087524d99
Author: Jiri Olsa <[email protected]>
AuthorDate: Thu, 17 Oct 2019 12:59:09 +02:00
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Sat, 19 Oct 2019 15:35:01 -03:00

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 <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Alexey Budankov <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Jin Yao <[email protected]>
Cc: Michael Petlan <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lore.kernel.org/lkml/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
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 6504561..854efff 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 be0b25a..20d90e2 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 ee536c4..be7556e 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 16f526e..8c4b3c2 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 2184aba..8be02af 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 0752c19..79d5ed6 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 0f9cd70..6cda5a3 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;