* [PATCH 0/7] libperf: Add interface for overflow check of sampling events
@ 2022-04-22 9:38 Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 1/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
` (6 more replies)
0 siblings, 7 replies; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
This patch series adds interface for overflow check of sampling events
to libperf.
First patch move 'open_flags' from tools/perf to evsel::open_flags.
Second patch introduce perf_{evsel, evlist}__open_opt() with extensible
structure opts.
Third patch add support for overflow handling of sampling events.
Fourth patch adds a interface to check overflowed events.
Fifth patch adds a interface to perform IOC_REFRESH and IOC_PERIOD.
Sixth and seventh patch adds tests.
---
Previous version at:
https://lore.kernel.org/linux-perf-users/20220325043829.224045-1-nakamura.shun@fujitsu.com/
Changes in v1:
- Move initialization/reference of evsel->open_flags from the first
patch to the second patch
- Move signal-related handling and related fields of the opts
structure from the second patch to the third patch
- Move _GNU_SOURCE from test-evlist.c to Makefile
- Delete *_cpu() function
- Refactor the fourth patch
- Fix test to use real-time signals instead of standard signals
Changes in RFC v2:
- Delete perf_evsel__set_close_on_exec() function
- Introduce perf_{evsel, evlist}__open_opt() with extensible structure
opts
- Fix perf_evsel__set_signal() to a internal function
- Add bool type argument to perf_evsel__check_{fd, fd_cpu}() to indicate
overflow results
Shunsuke Nakamura (7):
libperf: Move 'open_flags' from tools/perf to evsel::open_flags
libperf: Introduce perf_{evsel, evlist}__open_opt with extensible
struct opts
libperf: Add support for overflow handling of sampling events
libperf: Add perf_evsel__has_fd() functions
libperf: Add perf_evsel__{refresh, period}() functions
libperf test: Add test_stat_overflow()
libperf test: Add test_stat_overflow_event()
tools/lib/perf/Documentation/libperf.txt | 17 +++
tools/lib/perf/Makefile | 1 +
tools/lib/perf/evlist.c | 20 +++
tools/lib/perf/evsel.c | 166 ++++++++++++++++++++++-
tools/lib/perf/include/internal/evsel.h | 2 +
tools/lib/perf/include/perf/evlist.h | 3 +
tools/lib/perf/include/perf/evsel.h | 29 ++++
tools/lib/perf/internal.h | 44 ++++++
tools/lib/perf/libperf.map | 5 +
tools/lib/perf/tests/test-evlist.c | 112 ++++++++++++++-
tools/lib/perf/tests/test-evsel.c | 108 +++++++++++++++
tools/perf/util/evsel.c | 16 ++-
tools/perf/util/evsel.h | 1 -
13 files changed, 508 insertions(+), 16 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
@ 2022-04-22 9:38 ` Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 2/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
` (5 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
Move evsel::open_flags to perf_evsel::open_flags, so we can move
the open_flags interface to libperf.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/include/internal/evsel.h | 2 ++
tools/perf/util/evsel.c | 16 +++++++++-------
tools/perf/util/evsel.h | 1 -
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/tools/lib/perf/include/internal/evsel.h b/tools/lib/perf/include/internal/evsel.h
index cfc9ebd7968e..37a99cf261b3 100644
--- a/tools/lib/perf/include/internal/evsel.h
+++ b/tools/lib/perf/include/internal/evsel.h
@@ -51,6 +51,8 @@ struct perf_evsel {
int nr_members;
bool system_wide;
int idx;
+
+ unsigned long open_flags;
};
void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr,
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2a1729e7aee4..92f7a76ca9d5 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1794,9 +1794,9 @@ static int __evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus,
perf_evsel__alloc_fd(&evsel->core, perf_cpu_map__nr(cpus), nthreads) < 0)
return -ENOMEM;
- evsel->open_flags = PERF_FLAG_FD_CLOEXEC;
+ evsel->core.open_flags = PERF_FLAG_FD_CLOEXEC;
if (evsel->cgrp)
- evsel->open_flags |= PERF_FLAG_PID_CGROUP;
+ evsel->core.open_flags |= PERF_FLAG_PID_CGROUP;
return 0;
}
@@ -1814,7 +1814,7 @@ static void evsel__disable_missing_features(struct evsel *evsel)
evsel->core.attr.clockid = 0;
}
if (perf_missing_features.cloexec)
- evsel->open_flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
+ evsel->core.open_flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
if (perf_missing_features.mmap2)
evsel->core.attr.mmap2 = 0;
if (evsel->pmu && evsel->pmu->missing_features.exclude_guest)
@@ -1902,7 +1902,8 @@ bool evsel__detect_missing_features(struct evsel *evsel)
perf_missing_features.clockid = true;
pr_debug2_peo("switching off use_clockid\n");
return true;
- } else if (!perf_missing_features.cloexec && (evsel->open_flags & PERF_FLAG_FD_CLOEXEC)) {
+ } else if (!perf_missing_features.cloexec &&
+ (evsel->core.open_flags & PERF_FLAG_FD_CLOEXEC)) {
perf_missing_features.cloexec = true;
pr_debug2_peo("switching off cloexec flag\n");
return true;
@@ -2029,11 +2030,12 @@ static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
test_attr__ready();
pr_debug2_peo("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx",
- pid, perf_cpu_map__cpu(cpus, idx).cpu, group_fd, evsel->open_flags);
+ pid, perf_cpu_map__cpu(cpus, idx).cpu, group_fd,
+ evsel->core.open_flags);
fd = sys_perf_event_open(&evsel->core.attr, pid,
perf_cpu_map__cpu(cpus, idx).cpu,
- group_fd, evsel->open_flags);
+ group_fd, evsel->core.open_flags);
FD(evsel, idx, thread) = fd;
@@ -2050,7 +2052,7 @@ static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
if (unlikely(test_attr__enabled)) {
test_attr__open(&evsel->core.attr, pid,
perf_cpu_map__cpu(cpus, idx),
- fd, group_fd, evsel->open_flags);
+ fd, group_fd, evsel->core.open_flags);
}
pr_debug2_peo(" = %d\n", fd);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 041b42d33bf5..8a545954eec7 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -152,7 +152,6 @@ struct evsel {
struct bperf_leader_bpf *leader_skel;
struct bperf_follower_bpf *follower_skel;
};
- unsigned long open_flags;
int precise_ip_original;
/* for missing_features */
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 1/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
@ 2022-04-22 9:38 ` Shunsuke Nakamura
2022-05-20 18:59 ` Namhyung Kim
2022-04-22 9:38 ` [PATCH 3/7] libperf: Add support for overflow handling of sampling events Shunsuke Nakamura
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
Introduce perf_{evsel, evlist}__open_opt with extensible structure opts.
The mechanism of the extensible structure opts imitates
tools/lib/bpf/libbpf.h. Currently, only open_flags is supported for the
opts structure.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/Documentation/libperf.txt | 10 ++++++
tools/lib/perf/evlist.c | 20 +++++++++++
tools/lib/perf/evsel.c | 25 +++++++++++++-
tools/lib/perf/include/perf/evlist.h | 3 ++
tools/lib/perf/include/perf/evsel.h | 22 ++++++++++++
tools/lib/perf/internal.h | 44 ++++++++++++++++++++++++
tools/lib/perf/libperf.map | 2 ++
7 files changed, 125 insertions(+), 1 deletion(-)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index a8f1a237931b..6ca91ca94e01 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -132,6 +132,16 @@ SYNOPSIS
};
};
+ struct perf_evsel_open_opts {
+ /* size of this struct, for forward/backward compatibility */
+ size_t sz;
+
+ unsigned long open_flags; /* perf_event_open flags */
+ };
+ #define perf_evsel_open_opts__last_field open_flags
+
+ #define LIBPERF_OPTS(TYPE, NAME, ...)
+
struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr);
void perf_evsel__delete(struct perf_evsel *evsel);
int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
index a09315538a30..bf9343acb799 100644
--- a/tools/lib/perf/evlist.c
+++ b/tools/lib/perf/evlist.c
@@ -665,3 +665,23 @@ void perf_evlist__set_leader(struct perf_evlist *evlist)
__perf_evlist__set_leader(&evlist->entries, first);
}
}
+
+int perf_evlist__open_opts(struct perf_evlist *evlist,
+ struct perf_evsel_open_opts *opts)
+{
+ struct perf_evsel *evsel;
+ int err;
+
+ perf_evlist__for_each_entry(evlist, evsel) {
+ err = perf_evsel__open_opts(evsel, evsel->cpus,
+ evsel->threads, opts);
+ if (err < 0)
+ goto out_err;
+ }
+
+ return 0;
+
+out_err:
+ perf_evlist__close(evlist);
+ return err;
+}
diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
index 210ea7c06ce8..00c0cea43b52 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -16,8 +16,12 @@
#include <internal/lib.h>
#include <linux/string.h>
#include <sys/ioctl.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
#include <sys/mman.h>
#include <asm/bug.h>
+#include "internal.h"
void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr,
int idx)
@@ -26,6 +30,7 @@ void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr,
evsel->attr = *attr;
evsel->idx = idx;
evsel->leader = evsel;
+ evsel->open_flags = 0;
}
struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
@@ -158,7 +163,7 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
fd = sys_perf_event_open(&evsel->attr,
threads->map[thread].pid,
- cpu, group_fd, 0);
+ cpu, group_fd, evsel->open_flags);
if (fd < 0)
return -errno;
@@ -454,3 +459,21 @@ void perf_counts_values__scale(struct perf_counts_values *count,
if (pscaled)
*pscaled = scaled;
}
+
+int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads,
+ struct perf_evsel_open_opts *opts)
+{
+ int err = 0;
+
+ if (!OPTS_VALID(opts, perf_evsel_open_opts)) {
+ err = -EINVAL;
+ return err;
+ }
+
+ evsel->open_flags = OPTS_GET(opts, open_flags, 0);
+
+ err = perf_evsel__open(evsel, cpus, threads);
+
+ return err;
+}
diff --git a/tools/lib/perf/include/perf/evlist.h b/tools/lib/perf/include/perf/evlist.h
index 9ca399d49bb4..6eff1e9b3481 100644
--- a/tools/lib/perf/include/perf/evlist.h
+++ b/tools/lib/perf/include/perf/evlist.h
@@ -9,6 +9,7 @@ struct perf_evlist;
struct perf_evsel;
struct perf_cpu_map;
struct perf_thread_map;
+struct perf_evsel_open_opts;
LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist,
struct perf_evsel *evsel);
@@ -47,4 +48,6 @@ LIBPERF_API struct perf_mmap *perf_evlist__next_mmap(struct perf_evlist *evlist,
(pos) = perf_evlist__next_mmap((evlist), (pos), overwrite))
LIBPERF_API void perf_evlist__set_leader(struct perf_evlist *evlist);
+LIBPERF_API int perf_evlist__open_opts(struct perf_evlist *evlist,
+ struct perf_evsel_open_opts *opts);
#endif /* __LIBPERF_EVLIST_H */
diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
index 2a9516b42d15..1140df4d2578 100644
--- a/tools/lib/perf/include/perf/evsel.h
+++ b/tools/lib/perf/include/perf/evsel.h
@@ -5,6 +5,7 @@
#include <stdint.h>
#include <perf/core.h>
#include <stdbool.h>
+#include <signal.h>
#include <linux/types.h>
struct perf_evsel;
@@ -23,6 +24,23 @@ struct perf_counts_values {
};
};
+struct perf_evsel_open_opts {
+ /* size of this struct, for forward/backward compatibility */
+ size_t sz;
+
+ unsigned long open_flags; /* perf_event_open flags */
+};
+#define perf_evsel_open_opts__last_field open_flags
+
+#define LIBPERF_OPTS(TYPE, NAME, ...) \
+ struct TYPE NAME = ({ \
+ memset(&NAME, 0, sizeof(struct TYPE)); \
+ (struct TYPE) { \
+ .sz = sizeof(struct TYPE), \
+ __VA_ARGS__ \
+ }; \
+ })
+
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,
@@ -43,5 +61,9 @@ LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel
LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
LIBPERF_API void perf_counts_values__scale(struct perf_counts_values *count,
bool scale, __s8 *pscaled);
+LIBPERF_API int perf_evsel__open_opts(struct perf_evsel *evsel,
+ struct perf_cpu_map *cpus,
+ struct perf_thread_map *threads,
+ struct perf_evsel_open_opts *opts);
#endif /* __LIBPERF_EVSEL_H */
diff --git a/tools/lib/perf/internal.h b/tools/lib/perf/internal.h
index 2c27e158de6b..4b91a087ed62 100644
--- a/tools/lib/perf/internal.h
+++ b/tools/lib/perf/internal.h
@@ -20,4 +20,48 @@ do { \
#define pr_debug2(fmt, ...) __pr(LIBPERF_DEBUG2, fmt, ##__VA_ARGS__)
#define pr_debug3(fmt, ...) __pr(LIBPERF_DEBUG3, fmt, ##__VA_ARGS__)
+static inline bool libperf_is_mem_zeroed(const char *p, ssize_t len)
+{
+ while (len > 0) {
+ if (*p)
+ return false;
+ p++;
+ len--;
+ }
+ return true;
+}
+
+static inline bool libperf_validate_opts(const char *opts,
+ size_t opts_sz, size_t user_sz,
+ const char *type_name)
+{
+ if (user_sz < sizeof(size_t)) {
+ pr_warning("%s size (%zu) is too small\n", type_name, user_sz);
+ return false;
+ }
+ if (!libperf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) {
+ pr_warning("%s has non-zero extra bytes\n", type_name);
+ return false;
+ }
+ return true;
+}
+
+#define offsetofend(TYPE, FIELD) \
+ (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
+
+#define OPTS_VALID(opts, type) \
+ (!(opts) || libperf_validate_opts((const char *)opts, \
+ offsetofend(struct type, \
+ type##__last_field), \
+ (opts)->sz, #type))
+#define OPTS_HAS(opts, field) \
+ ((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
+#define OPTS_GET(opts, field, fallback_value) \
+ (OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
+#define OPTS_SET(opts, field, value) \
+ do { \
+ if (OPTS_HAS(opts, field)) \
+ (opts)->field = value; \
+ } while (0)
+
#endif /* __LIBPERF_INTERNAL_H */
diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
index 190b56ae923a..eeeb3075e092 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -25,6 +25,7 @@ LIBPERF_0.0.1 {
perf_evsel__enable;
perf_evsel__disable;
perf_evsel__open;
+ perf_evsel__open_opts;
perf_evsel__close;
perf_evsel__mmap;
perf_evsel__munmap;
@@ -36,6 +37,7 @@ LIBPERF_0.0.1 {
perf_evlist__new;
perf_evlist__delete;
perf_evlist__open;
+ perf_evlist__open_opts;
perf_evlist__close;
perf_evlist__enable;
perf_evlist__disable;
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/7] libperf: Add support for overflow handling of sampling events
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 1/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 2/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
@ 2022-04-22 9:38 ` Shunsuke Nakamura
2022-05-20 19:28 ` Namhyung Kim
2022-04-22 9:38 ` [PATCH 4/7] libperf: Add perf_evsel__has_fd() functions Shunsuke Nakamura
` (3 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
Extend the fields of the opts structure to set up overflow handling
for sampling events. Also, add processing to set signal handlers in
perf_evsel__open_opts.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/Documentation/libperf.txt | 6 +-
tools/lib/perf/Makefile | 1 +
tools/lib/perf/evsel.c | 79 ++++++++++++++++++++++++
tools/lib/perf/include/perf/evsel.h | 6 +-
tools/lib/perf/tests/test-evlist.c | 1 -
5 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index 6ca91ca94e01..ec93b1c75ebe 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -137,8 +137,12 @@ SYNOPSIS
size_t sz;
unsigned long open_flags; /* perf_event_open flags */
+ int flags; /* fcntl flags */
+ unsigned int signal;
+ int owner_type;
+ struct sigaction *sig;
};
- #define perf_evsel_open_opts__last_field open_flags
+ #define perf_evsel_open_opts__last_field sig
#define LIBPERF_OPTS(TYPE, NAME, ...)
diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile
index 21df023a2103..4c8fae193cf5 100644
--- a/tools/lib/perf/Makefile
+++ b/tools/lib/perf/Makefile
@@ -75,6 +75,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/lib/perf/evsel.c b/tools/lib/perf/evsel.c
index 00c0cea43b52..a289f6c44d7c 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -460,6 +460,79 @@ void perf_counts_values__scale(struct perf_counts_values *count,
*pscaled = scaled;
}
+static int perf_evsel__run_fcntl(struct perf_evsel *evsel,
+ unsigned int cmd, unsigned long arg,
+ int cpu_map_idx)
+{
+ int thread;
+
+ for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
+ int err;
+ int *fd = FD(evsel, cpu_map_idx, thread);
+
+ if (!fd || *fd < 0)
+ return -1;
+
+ err = fcntl(*fd, cmd, arg);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int perf_evsel__set_signal_handler(struct perf_evsel *evsel,
+ struct perf_evsel_open_opts *opts)
+{
+ unsigned int flags;
+ unsigned int signal;
+ struct f_owner_ex owner;
+ struct sigaction *sig;
+ int cpu_map_idx;
+ int err = 0;
+
+ flags = OPTS_GET(opts, flags, (O_RDWR | O_NONBLOCK | O_ASYNC));
+ signal = OPTS_GET(opts, signal, SIGIO);
+ owner.type = OPTS_GET(opts, owner_type, F_OWNER_PID);
+ sig = OPTS_GET(opts, sig, NULL);
+
+ if (flags == 0 && signal == 0 && !owner.type == 0 && sig == 0)
+ return err;
+
+ err = sigaction(signal, sig, NULL);
+ if (err)
+ return err;
+
+ switch (owner.type) {
+ case F_OWNER_PID:
+ owner.pid = getpid();
+ break;
+ case F_OWNER_TID:
+ owner.pid = syscall(SYS_gettid);
+ break;
+ case F_OWNER_PGRP:
+ default:
+ return -1;
+ }
+
+ for (cpu_map_idx = 0; cpu_map_idx < xyarray__max_x(evsel->fd); cpu_map_idx++) {
+ err = perf_evsel__run_fcntl(evsel, F_SETFL, flags, cpu_map_idx);
+ if (err)
+ return err;
+
+ err = perf_evsel__run_fcntl(evsel, F_SETSIG, signal, cpu_map_idx);
+ if (err)
+ return err;
+
+ err = perf_evsel__run_fcntl(evsel, F_SETOWN_EX,
+ (unsigned long)&owner, cpu_map_idx);
+ if (err)
+ return err;
+ }
+
+ return err;
+}
+
int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
struct perf_thread_map *threads,
struct perf_evsel_open_opts *opts)
@@ -474,6 +547,12 @@ int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
evsel->open_flags = OPTS_GET(opts, open_flags, 0);
err = perf_evsel__open(evsel, cpus, threads);
+ if (err)
+ return err;
+
+ err = perf_evsel__set_signal_handler(evsel, opts);
+ if (err)
+ return err;
return err;
}
diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
index 1140df4d2578..50662babfe97 100644
--- a/tools/lib/perf/include/perf/evsel.h
+++ b/tools/lib/perf/include/perf/evsel.h
@@ -29,8 +29,12 @@ struct perf_evsel_open_opts {
size_t sz;
unsigned long open_flags; /* perf_event_open flags */
+ int flags; /* fcntl flags */
+ unsigned int signal;
+ int owner_type;
+ struct sigaction *sig;
};
-#define perf_evsel_open_opts__last_field open_flags
+#define perf_evsel_open_opts__last_field sig
#define LIBPERF_OPTS(TYPE, NAME, ...) \
struct TYPE NAME = ({ \
diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c
index ed616fc19b4f..d8f9493cd4d1 100644
--- a/tools/lib/perf/tests/test-evlist.c
+++ b/tools/lib/perf/tests/test-evlist.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
#include <inttypes.h>
#include <sched.h>
#include <stdio.h>
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/7] libperf: Add perf_evsel__has_fd() functions
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (2 preceding siblings ...)
2022-04-22 9:38 ` [PATCH 3/7] libperf: Add support for overflow handling of sampling events Shunsuke Nakamura
@ 2022-04-22 9:38 ` Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 5/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
Add the following functions:
perf_evsel__has_fd
to check for perf events with the file descriptor specified in the
argument.
This function can be used in signal handlers to check overflow.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/Documentation/libperf.txt | 1 +
tools/lib/perf/evsel.c | 18 ++++++++++++++++++
tools/lib/perf/include/perf/evsel.h | 1 +
tools/lib/perf/libperf.map | 1 +
4 files changed, 21 insertions(+)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index ec93b1c75ebe..bc7881348c76 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -161,6 +161,7 @@ SYNOPSIS
int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
int perf_evsel__disable(struct perf_evsel *evsel);
int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
+ bool perf_evsel__has_fd(struct perf_evsel *evsel, int fd);
struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
index a289f6c44d7c..446934c0e5e5 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -556,3 +556,21 @@ int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
return err;
}
+
+bool perf_evsel__has_fd(struct perf_evsel *evsel, int fd)
+{
+ int cpu_map_idx;
+ int thread;
+ int *evsel_fd;
+
+ for (cpu_map_idx = 0; cpu_map_idx < xyarray__max_x(evsel->fd); ++cpu_map_idx) {
+ for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
+ evsel_fd = FD(evsel, cpu_map_idx, thread);
+
+ if (fd == *evsel_fd)
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
index 50662babfe97..19a7993d9021 100644
--- a/tools/lib/perf/include/perf/evsel.h
+++ b/tools/lib/perf/include/perf/evsel.h
@@ -69,5 +69,6 @@ LIBPERF_API int perf_evsel__open_opts(struct perf_evsel *evsel,
struct perf_cpu_map *cpus,
struct perf_thread_map *threads,
struct perf_evsel_open_opts *opts);
+LIBPERF_API bool perf_evsel__has_fd(struct perf_evsel *evsel, int fd);
#endif /* __LIBPERF_EVSEL_H */
diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
index eeeb3075e092..b2ace16bbc32 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -34,6 +34,7 @@ LIBPERF_0.0.1 {
perf_evsel__cpus;
perf_evsel__threads;
perf_evsel__attr;
+ perf_evsel__has_fd;
perf_evlist__new;
perf_evlist__delete;
perf_evlist__open;
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/7] libperf: Add perf_evsel__{refresh, period}() functions
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (3 preceding siblings ...)
2022-04-22 9:38 ` [PATCH 4/7] libperf: Add perf_evsel__has_fd() functions Shunsuke Nakamura
@ 2022-04-22 9:38 ` Shunsuke Nakamura
2022-05-20 19:38 ` Namhyung Kim
2022-04-22 9:38 ` [PATCH 6/7] libperf test: Add test_stat_overflow() Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 7/7] libperf test: Add test_stat_overflow_event() Shunsuke Nakamura
6 siblings, 1 reply; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
Add the following functions:
perf_evsel__refresh()
perf_evsel__period()
to set the over flow limit and period.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/Documentation/libperf.txt | 2 ++
tools/lib/perf/evsel.c | 44 ++++++++++++++++++++----
tools/lib/perf/include/perf/evsel.h | 2 ++
tools/lib/perf/libperf.map | 2 ++
4 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index bc7881348c76..773224a96bd3 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -162,6 +162,8 @@ SYNOPSIS
int perf_evsel__disable(struct perf_evsel *evsel);
int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
bool perf_evsel__has_fd(struct perf_evsel *evsel, int fd);
+ int perf_evsel__refresh(struct perf_evsel *evsel, int refresh);
+ int perf_evsel__period(struct perf_evsel *evsel, int period);
struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
index 446934c0e5e5..578ae0050036 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -334,7 +334,7 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread,
}
static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
- int ioc, void *arg,
+ int ioc, unsigned long arg,
int cpu_map_idx)
{
int thread;
@@ -357,7 +357,7 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx)
{
- return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, cpu_map_idx);
+ return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0, cpu_map_idx);
}
int perf_evsel__enable(struct perf_evsel *evsel)
@@ -366,13 +366,13 @@ int perf_evsel__enable(struct perf_evsel *evsel)
int err = 0;
for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
- err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, i);
+ err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0, i);
return err;
}
int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx)
{
- return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, cpu_map_idx);
+ return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0, cpu_map_idx);
}
int perf_evsel__disable(struct perf_evsel *evsel)
@@ -381,7 +381,39 @@ int perf_evsel__disable(struct perf_evsel *evsel)
int err = 0;
for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
- err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, i);
+ err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0, i);
+ return err;
+}
+
+int perf_evsel__refresh(struct perf_evsel *evsel, int refresh)
+{
+ int i;
+ int err = 0;
+
+ for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+ err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_REFRESH, refresh, i);
+ return err;
+}
+
+int perf_evsel__period(struct perf_evsel *evsel, __u64 period)
+{
+ struct perf_event_attr *attr;
+ int i;
+ int err = 0;
+
+ attr = perf_evsel__attr(evsel);
+ if (!attr)
+ return -EINVAL;
+
+ for (i = 0; i < xyarray__max_x(evsel->fd); i++) {
+ err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_PERIOD,
+ (unsigned long)&period, i);
+ if (err)
+ return err;
+ }
+
+ attr->sample_period = period;
+
return err;
}
@@ -392,7 +424,7 @@ int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
for (i = 0; i < perf_cpu_map__nr(evsel->cpus) && !err; i++)
err = perf_evsel__run_ioctl(evsel,
PERF_EVENT_IOC_SET_FILTER,
- (void *)filter, i);
+ (unsigned long)filter, i);
return err;
}
diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
index 19a7993d9021..2c5e52c17d28 100644
--- a/tools/lib/perf/include/perf/evsel.h
+++ b/tools/lib/perf/include/perf/evsel.h
@@ -60,6 +60,8 @@ LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel);
LIBPERF_API int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
LIBPERF_API int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
+LIBPERF_API int perf_evsel__refresh(struct perf_evsel *evsel, int refresh);
+LIBPERF_API int perf_evsel__period(struct perf_evsel *evsel, __u64 period);
LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
index b2ace16bbc32..d97e208c5be8 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -31,6 +31,8 @@ LIBPERF_0.0.1 {
perf_evsel__munmap;
perf_evsel__mmap_base;
perf_evsel__read;
+ perf_evsel__refresh;
+ perf_evsel__period;
perf_evsel__cpus;
perf_evsel__threads;
perf_evsel__attr;
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/7] libperf test: Add test_stat_overflow()
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (4 preceding siblings ...)
2022-04-22 9:38 ` [PATCH 5/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
@ 2022-04-22 9:38 ` Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 7/7] libperf test: Add test_stat_overflow_event() Shunsuke Nakamura
6 siblings, 0 replies; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
Added overflow test using refresh and period.
Confirmation
- That the overflow occurs the number of times specified by
perf_evse__refresh()
- That the period can be updated by perf_evsel__period()
Committer testing:
$ sudo make tests -C ./tools/lib/perf V=1
make: Entering directory '/home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/lib/perf'
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=. obj=libperf
make -C /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/lib/api/ O= libapi.a
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=./fd obj=libapi
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=./fs obj=libapi
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=. obj=tests
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=./tests obj=tests
running static:
- running tests/test-cpumap.c...OK
- running tests/test-threadmap.c...OK
- running tests/test-evlist.c...
<SNIP>
OK
- running tests/test-evsel.c...
<SNIP>
period = 1000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
period = 2000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
period = 1000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
period = 2000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
OK
running dynamic:
- running tests/test-cpumap.c...OK
- running tests/test-threadmap.c...OK
- running tests/test-evlist.c...
<SNIP>
OK
- running tests/test-evsel.c...
<SNIP>
period = 1000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
period = 2000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
period = 1000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
period = 2000000
overflow limit = 3, overflow count = 3, POLL_IN = 2, POLL_UP = 1, other signal event = 0
OK
make: Leaving directory '/home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/lib/perf'
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/tests/test-evsel.c | 108 ++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
diff --git a/tools/lib/perf/tests/test-evsel.c b/tools/lib/perf/tests/test-evsel.c
index 89be89afb24d..4de5d5554836 100644
--- a/tools/lib/perf/tests/test-evsel.c
+++ b/tools/lib/perf/tests/test-evsel.c
@@ -1,6 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
+#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
#include <linux/perf_event.h>
#include <perf/cpumap.h>
#include <perf/threadmap.h>
@@ -8,6 +13,15 @@
#include <internal/tests.h>
#include "tests.h"
+#define WAIT_COUNT 10000000UL
+static struct signal_counts {
+ int in;
+ int hup;
+ int others;
+ int overflow;
+} sig_count;
+static struct perf_evsel *s_evsel;
+
static int libperf_print(enum libperf_print_level level,
const char *fmt, va_list ap)
{
@@ -189,6 +203,98 @@ static int test_stat_user_read(int event)
return 0;
}
+static void sig_handler(int signo, siginfo_t *info, void *uc)
+{
+ switch (info->si_code) {
+ case POLL_IN:
+ sig_count.in++;
+ break;
+ case POLL_HUP:
+ sig_count.hup++;
+ break;
+ default:
+ sig_count.others++;
+ }
+
+ sig_count.overflow++;
+}
+
+static int test_stat_overflow(int owner)
+{
+ static struct sigaction sig;
+ u64 period = 1000000;
+ int overflow_limit = 3;
+
+ struct perf_thread_map *threads;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_TASK_CLOCK,
+ .sample_type = PERF_SAMPLE_PERIOD,
+ .sample_period = period,
+ .disabled = 1,
+ };
+ struct perf_event_attr *tmp_attr;
+ int err = 0, i;
+
+ LIBPERF_OPTS(perf_evsel_open_opts, opts,
+ .open_flags = PERF_FLAG_FD_CLOEXEC,
+ .flags = (O_RDWR | O_NONBLOCK | O_ASYNC),
+ .signal = SIGRTMIN + 1,
+ .owner_type = owner,
+ .sig = &sig);
+
+ /* setup signal handler */
+ memset(&sig, 0, sizeof(struct sigaction));
+ sig.sa_sigaction = (void *)sig_handler;
+ sig.sa_flags = SA_SIGINFO;
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ perf_thread_map__set_pid(threads, 0, 0);
+
+ s_evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel", s_evsel);
+
+ err = perf_evsel__open_opts(s_evsel, NULL, threads, &opts);
+ __T("failed to open evsel", err == 0);
+
+ for (i = 0; i < 2; i++) {
+ volatile unsigned int wait_count = WAIT_COUNT;
+
+ sig_count.in = 0;
+ sig_count.hup = 0;
+ sig_count.others = 0;
+ sig_count.overflow = 0;
+
+ period = period << i;
+ err = perf_evsel__period(s_evsel, period);
+ __T("failed to period evsel", err == 0);
+
+ tmp_attr = perf_evsel__attr(s_evsel);
+ __T_VERBOSE("\tperiod = %llu\n", tmp_attr->sample_period);
+
+ err = perf_evsel__refresh(s_evsel, overflow_limit);
+ __T("failed to refresh evsel", err == 0);
+
+ while (wait_count--)
+ ;
+
+ __T_VERBOSE("\toverflow limit = %d, overflow count = %d, ",
+ overflow_limit, sig_count.overflow);
+ __T_VERBOSE("POLL_IN = %d, POLL_HUP = %d, other signal event = %d\n",
+ sig_count.in, sig_count.hup, sig_count.others);
+
+ __T("failed to overflow count", overflow_limit == sig_count.overflow);
+ }
+
+ perf_evsel__close(s_evsel);
+ perf_evsel__delete(s_evsel);
+ perf_thread_map__put(threads);
+
+ return 0;
+}
+
int test_evsel(int argc, char **argv)
{
__T_START;
@@ -200,6 +306,8 @@ int test_evsel(int argc, char **argv)
test_stat_thread_enable();
test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
+ test_stat_overflow(F_OWNER_PID);
+ test_stat_overflow(F_OWNER_TID);
__T_END;
return tests_failed == 0 ? 0 : -1;
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/7] libperf test: Add test_stat_overflow_event()
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (5 preceding siblings ...)
2022-04-22 9:38 ` [PATCH 6/7] libperf test: Add test_stat_overflow() Shunsuke Nakamura
@ 2022-04-22 9:38 ` Shunsuke Nakamura
6 siblings, 0 replies; 11+ messages in thread
From: Shunsuke Nakamura @ 2022-04-22 9:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
Add a test to check overflowed events.
Committer testing:
$ sudo make tests -C ./tools/lib/perf V=1
make: Entering directory '/home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/lib/perf'
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=. obj=libperf
make -C /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/lib/api/ O= libapi.a
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=./fd obj=libapi
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=./fs obj=libapi
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=. obj=tests
make -f /home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/build/Makefile.build dir=./tests obj=tests
running static:
- running tests/test-cpumap.c...OK
- running tests/test-threadmap.c...OK
- running tests/test-evlist.c...
<SNIP>
Event 0 -- overflow flag = 0x1, POLL_UP = 1, other signal event = 0
Event 1 -- overflow flag = 0x2, POLL_UP = 1, other signal event = 0
Event 2 -- overflow flag = 0x4, POLL_UP = 1, other signal event = 0
Event 3 -- overflow flag = 0x8, POLL_UP = 1, other signal event = 0
OK
- running tests/test-evsel.c...
<SNIP>
OK
running dynamic:
- running tests/test-cpumap.c...OK
- running tests/test-threadmap.c...OK
- running tests/test-evlist.c...
<SNIP>
Event 0 -- overflow flag = 0x1, POLL_UP = 1, other signal event = 0
Event 1 -- overflow flag = 0x2, POLL_UP = 1, other signal event = 0
Event 2 -- overflow flag = 0x4, POLL_UP = 1, other signal event = 0
Event 3 -- overflow flag = 0x8, POLL_UP = 1, other signal event = 0
OK
- running tests/test-evsel.c...
<SNIP>
OK
make: Leaving directory '/home/nakamura/build_work/build_kernel/linux-kernel/linux/tools/lib/perf'
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/tests/test-evlist.c | 111 +++++++++++++++++++++++++++++
1 file changed, 111 insertions(+)
diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c
index d8f9493cd4d1..587364851432 100644
--- a/tools/lib/perf/tests/test-evlist.c
+++ b/tools/lib/perf/tests/test-evlist.c
@@ -5,6 +5,8 @@
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
#include <linux/perf_event.h>
#include <linux/limits.h>
#include <sys/types.h>
@@ -24,6 +26,13 @@
#define EVENT_NUM 15
#define WAIT_COUNT 100000000UL
+static unsigned int overflow_flag;
+static struct signal_counts {
+ int hup;
+ int others;
+} sig_count;
+static struct perf_evlist *s_evlist;
+
static int libperf_print(enum libperf_print_level level,
const char *fmt, va_list ap)
{
@@ -570,6 +579,107 @@ static int test_stat_multiplexing(void)
return 0;
}
+static void sig_handler(int signo, siginfo_t *info, void *uc)
+{
+ struct perf_evsel *evsel;
+ int i = 0;
+
+ perf_evlist__for_each_evsel(s_evlist, evsel) {
+ if (perf_evsel__has_fd(evsel, info->si_fd)) {
+ if (info->si_code == POLL_HUP)
+ sig_count.hup++;
+ else
+ sig_count.others++;
+
+ overflow_flag = (1U << i);
+ return;
+ }
+ i++;
+ }
+
+ __T_VERBOSE("Failed to get fd of overflowed event");
+}
+
+static int test_stat_overflow_event(void)
+{
+ static struct sigaction sig;
+
+ struct perf_thread_map *threads;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_SOFTWARE,
+ .config = PERF_COUNT_SW_CPU_CLOCK,
+ .sample_type = PERF_SAMPLE_PERIOD,
+ .sample_period = 100000,
+ .disabled = 1,
+ };
+ int err, i, event_num = 4;
+
+ LIBPERF_OPTS(perf_evsel_open_opts, opts,
+ .open_flags = PERF_FLAG_FD_CLOEXEC,
+ .flags = (O_RDWR | O_NONBLOCK | O_ASYNC),
+ .signal = SIGRTMIN + 1,
+ .owner_type = F_OWNER_PID,
+ .sig = &sig);
+
+ /* setup signal handler */
+ memset(&sig, 0, sizeof(struct sigaction));
+ sig.sa_sigaction = (void *)sig_handler;
+ sig.sa_flags = SA_SIGINFO;
+
+ threads = perf_thread_map__new_dummy();
+ __T("failed to create threads", threads);
+
+ perf_thread_map__set_pid(threads, 0, 0);
+
+ s_evlist = perf_evlist__new();
+ __T("failed to create evlist", s_evlist);
+
+ for (i = 0; i < event_num; i++) {
+ evsel = perf_evsel__new(&attr);
+ __T("failed to create evsel", evsel);
+
+ perf_evlist__add(s_evlist, evsel);
+ }
+
+ perf_evlist__set_maps(s_evlist, NULL, threads);
+
+ err = perf_evlist__open_opts(s_evlist, &opts);
+ __T("failed to open evlist", err == 0);
+
+ i = 0;
+ perf_evlist__for_each_evsel(s_evlist, evsel) {
+ volatile unsigned int wait_count = WAIT_COUNT;
+
+ overflow_flag = 0;
+ sig_count.hup = 0;
+ sig_count.others = 0;
+
+ err = perf_evsel__refresh(evsel, 1);
+ __T("failed to refresh evsel", err == 0);
+
+ while (wait_count--)
+ ;
+
+ __T_VERBOSE("Event %2d -- overflow flag = %#x, ",
+ i, overflow_flag);
+ __T_VERBOSE("POLL_HUP = %d, other signal event = %d\n",
+ sig_count.hup, sig_count.others);
+
+ __T("unexpected event overflow detected", overflow_flag && (1U << i));
+ __T("unexpected signal event detected",
+ sig_count.hup == 1 && sig_count.others == 0);
+
+ i++;
+ }
+
+ perf_evlist__close(s_evlist);
+ perf_evlist__delete(s_evlist);
+ perf_thread_map__put(threads);
+
+ return 0;
+}
+
int test_evlist(int argc, char **argv)
{
__T_START;
@@ -582,6 +692,7 @@ int test_evlist(int argc, char **argv)
test_mmap_thread();
test_mmap_cpus();
test_stat_multiplexing();
+ test_stat_overflow_event();
__T_END;
return tests_failed == 0 ? 0 : -1;
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts
2022-04-22 9:38 ` [PATCH 2/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
@ 2022-05-20 18:59 ` Namhyung Kim
0 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2022-05-20 18:59 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, linux-kernel,
linux-perf-users
Hello,
On Fri, Apr 22, 2022 at 2:44 AM Shunsuke Nakamura
<nakamura.shun@fujitsu.com> wrote:
>
> Introduce perf_{evsel, evlist}__open_opt with extensible structure opts.
> The mechanism of the extensible structure opts imitates
> tools/lib/bpf/libbpf.h. Currently, only open_flags is supported for the
> opts structure.
>
> Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> ---
[SNIP]
> diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
> index 210ea7c06ce8..00c0cea43b52 100644
> --- a/tools/lib/perf/evsel.c
> +++ b/tools/lib/perf/evsel.c
> @@ -16,8 +16,12 @@
> #include <internal/lib.h>
> #include <linux/string.h>
> #include <sys/ioctl.h>
> +#include <signal.h>
> +#include <fcntl.h>
> +#include <sys/types.h>
> #include <sys/mman.h>
> #include <asm/bug.h>
> +#include "internal.h"
>
> void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr,
> int idx)
> @@ -26,6 +30,7 @@ void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr,
> evsel->attr = *attr;
> evsel->idx = idx;
> evsel->leader = evsel;
> + evsel->open_flags = 0;
In general, you don't need to reset it to zero as it's allocated with
zalloc().
> }
>
[SNIP]
> diff --git a/tools/lib/perf/internal.h b/tools/lib/perf/internal.h
> index 2c27e158de6b..4b91a087ed62 100644
> --- a/tools/lib/perf/internal.h
> +++ b/tools/lib/perf/internal.h
> @@ -20,4 +20,48 @@ do { \
> #define pr_debug2(fmt, ...) __pr(LIBPERF_DEBUG2, fmt, ##__VA_ARGS__)
> #define pr_debug3(fmt, ...) __pr(LIBPERF_DEBUG3, fmt, ##__VA_ARGS__)
>
> +static inline bool libperf_is_mem_zeroed(const char *p, ssize_t len)
> +{
> + while (len > 0) {
> + if (*p)
> + return false;
> + p++;
> + len--;
> + }
> + return true;
> +}
> +
> +static inline bool libperf_validate_opts(const char *opts,
> + size_t opts_sz, size_t user_sz,
> + const char *type_name)
> +{
> + if (user_sz < sizeof(size_t)) {
> + pr_warning("%s size (%zu) is too small\n", type_name, user_sz);
> + return false;
> + }
> + if (!libperf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) {
I don't think the cast is necessary since it'll be promoted again
to size_t due to opts_sz. Instead, we can check if user_sz is
greater than opts_sz explicitly and call the function.
> + pr_warning("%s has non-zero extra bytes\n", type_name);
> + return false;
> + }
> + return true;
> +}
> +
> +#define offsetofend(TYPE, FIELD) \
> + (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
> +
> +#define OPTS_VALID(opts, type) \
> + (!(opts) || libperf_validate_opts((const char *)opts, \
> + offsetofend(struct type, \
> + type##__last_field), \
> + (opts)->sz, #type))
> +#define OPTS_HAS(opts, field) \
> + ((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
> +#define OPTS_GET(opts, field, fallback_value) \
> + (OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
It'd be nice if you add a blank line between the macros.
Thanks,
Namhyung
> +#define OPTS_SET(opts, field, value) \
> + do { \
> + if (OPTS_HAS(opts, field)) \
> + (opts)->field = value; \
> + } while (0)
> +
> #endif /* __LIBPERF_INTERNAL_H */
> diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
> index 190b56ae923a..eeeb3075e092 100644
> --- a/tools/lib/perf/libperf.map
> +++ b/tools/lib/perf/libperf.map
> @@ -25,6 +25,7 @@ LIBPERF_0.0.1 {
> perf_evsel__enable;
> perf_evsel__disable;
> perf_evsel__open;
> + perf_evsel__open_opts;
> perf_evsel__close;
> perf_evsel__mmap;
> perf_evsel__munmap;
> @@ -36,6 +37,7 @@ LIBPERF_0.0.1 {
> perf_evlist__new;
> perf_evlist__delete;
> perf_evlist__open;
> + perf_evlist__open_opts;
> perf_evlist__close;
> perf_evlist__enable;
> perf_evlist__disable;
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/7] libperf: Add support for overflow handling of sampling events
2022-04-22 9:38 ` [PATCH 3/7] libperf: Add support for overflow handling of sampling events Shunsuke Nakamura
@ 2022-05-20 19:28 ` Namhyung Kim
0 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2022-05-20 19:28 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, linux-kernel,
linux-perf-users
On Fri, Apr 22, 2022 at 2:44 AM Shunsuke Nakamura
<nakamura.shun@fujitsu.com> wrote:
>
> Extend the fields of the opts structure to set up overflow handling
> for sampling events. Also, add processing to set signal handlers in
> perf_evsel__open_opts.
>
> Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> ---
> tools/lib/perf/Documentation/libperf.txt | 6 +-
> tools/lib/perf/Makefile | 1 +
> tools/lib/perf/evsel.c | 79 ++++++++++++++++++++++++
> tools/lib/perf/include/perf/evsel.h | 6 +-
> tools/lib/perf/tests/test-evlist.c | 1 -
> 5 files changed, 90 insertions(+), 3 deletions(-)
>
> diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
> index 6ca91ca94e01..ec93b1c75ebe 100644
> --- a/tools/lib/perf/Documentation/libperf.txt
> +++ b/tools/lib/perf/Documentation/libperf.txt
> @@ -137,8 +137,12 @@ SYNOPSIS
> size_t sz;
>
> unsigned long open_flags; /* perf_event_open flags */
> + int flags; /* fcntl flags */
What about just rename it to fcntl_flags ?
> + unsigned int signal;
int ?
> + int owner_type;
Please add a comment that it's for F_SETOWN_EX.
> + struct sigaction *sig;
> };
> - #define perf_evsel_open_opts__last_field open_flags
> + #define perf_evsel_open_opts__last_field sig
>
> #define LIBPERF_OPTS(TYPE, NAME, ...)
>
> diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile
> index 21df023a2103..4c8fae193cf5 100644
> --- a/tools/lib/perf/Makefile
> +++ b/tools/lib/perf/Makefile
> @@ -75,6 +75,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/lib/perf/evsel.c b/tools/lib/perf/evsel.c
> index 00c0cea43b52..a289f6c44d7c 100644
> --- a/tools/lib/perf/evsel.c
> +++ b/tools/lib/perf/evsel.c
> @@ -460,6 +460,79 @@ void perf_counts_values__scale(struct perf_counts_values *count,
> *pscaled = scaled;
> }
>
> +static int perf_evsel__run_fcntl(struct perf_evsel *evsel,
> + unsigned int cmd, unsigned long arg,
> + int cpu_map_idx)
I think it'd be better to have _cpu suffix in the function name
as it handles on the specific cpu.
> +{
> + int thread;
> +
> + for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
> + int err;
> + int *fd = FD(evsel, cpu_map_idx, thread);
> +
> + if (!fd || *fd < 0)
> + return -1;
> +
> + err = fcntl(*fd, cmd, arg);
> + if (err)
> + return err;
> + }
> +
> + return 0;
> +}
> +
> +static int perf_evsel__set_signal_handler(struct perf_evsel *evsel,
> + struct perf_evsel_open_opts *opts)
> +{
> + unsigned int flags;
> + unsigned int signal;
> + struct f_owner_ex owner;
> + struct sigaction *sig;
It can be confused with the signal number, how about sigact?
> + int cpu_map_idx;
> + int err = 0;
> +
> + flags = OPTS_GET(opts, flags, (O_RDWR | O_NONBLOCK | O_ASYNC));
> + signal = OPTS_GET(opts, signal, SIGIO);
> + owner.type = OPTS_GET(opts, owner_type, F_OWNER_PID);
> + sig = OPTS_GET(opts, sig, NULL);
> +
> + if (flags == 0 && signal == 0 && !owner.type == 0 && sig == 0)
You man want to check owner.type without "!".
> + return err;
> +
> + err = sigaction(signal, sig, NULL);
> + if (err)
> + return err;
> +
> + switch (owner.type) {
> + case F_OWNER_PID:
> + owner.pid = getpid();
> + break;
> + case F_OWNER_TID:
> + owner.pid = syscall(SYS_gettid);
> + break;
> + case F_OWNER_PGRP:
> + default:
> + return -1;
> + }
> +
> + for (cpu_map_idx = 0; cpu_map_idx < xyarray__max_x(evsel->fd); cpu_map_idx++) {
> + err = perf_evsel__run_fcntl(evsel, F_SETFL, flags, cpu_map_idx);
> + if (err)
> + return err;
> +
> + err = perf_evsel__run_fcntl(evsel, F_SETSIG, signal, cpu_map_idx);
> + if (err)
> + return err;
> +
> + err = perf_evsel__run_fcntl(evsel, F_SETOWN_EX,
> + (unsigned long)&owner, cpu_map_idx);
> + if (err)
> + return err;
> + }
> +
> + return err;
> +}
> +
> int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
> struct perf_thread_map *threads,
> struct perf_evsel_open_opts *opts)
> @@ -474,6 +547,12 @@ int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
> evsel->open_flags = OPTS_GET(opts, open_flags, 0);
>
> err = perf_evsel__open(evsel, cpus, threads);
> + if (err)
> + return err;
> +
> + err = perf_evsel__set_signal_handler(evsel, opts);
> + if (err)
> + return err;
>
> return err;
> }
> diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
> index 1140df4d2578..50662babfe97 100644
> --- a/tools/lib/perf/include/perf/evsel.h
> +++ b/tools/lib/perf/include/perf/evsel.h
> @@ -29,8 +29,12 @@ struct perf_evsel_open_opts {
> size_t sz;
>
> unsigned long open_flags; /* perf_event_open flags */
> + int flags; /* fcntl flags */
> + unsigned int signal;
> + int owner_type;
> + struct sigaction *sig;
> };
> -#define perf_evsel_open_opts__last_field open_flags
> +#define perf_evsel_open_opts__last_field sig
>
> #define LIBPERF_OPTS(TYPE, NAME, ...) \
> struct TYPE NAME = ({ \
> diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c
> index ed616fc19b4f..d8f9493cd4d1 100644
> --- a/tools/lib/perf/tests/test-evlist.c
> +++ b/tools/lib/perf/tests/test-evlist.c
> @@ -1,5 +1,4 @@
> // SPDX-License-Identifier: GPL-2.0
> -#define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET)
Could be in a separate change.
Thanks,
Namhyung
> #include <inttypes.h>
> #include <sched.h>
> #include <stdio.h>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/7] libperf: Add perf_evsel__{refresh, period}() functions
2022-04-22 9:38 ` [PATCH 5/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
@ 2022-05-20 19:38 ` Namhyung Kim
0 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2022-05-20 19:38 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Mark Rutland, Alexander Shishkin, Jiri Olsa, linux-kernel,
linux-perf-users
On Fri, Apr 22, 2022 at 2:45 AM Shunsuke Nakamura
<nakamura.shun@fujitsu.com> wrote:
>
> Add the following functions:
>
> perf_evsel__refresh()
> perf_evsel__period()
>
> to set the over flow limit and period.
>
> Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> ---
> tools/lib/perf/Documentation/libperf.txt | 2 ++
> tools/lib/perf/evsel.c | 44 ++++++++++++++++++++----
> tools/lib/perf/include/perf/evsel.h | 2 ++
> tools/lib/perf/libperf.map | 2 ++
> 4 files changed, 44 insertions(+), 6 deletions(-)
>
> diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
> index bc7881348c76..773224a96bd3 100644
> --- a/tools/lib/perf/Documentation/libperf.txt
> +++ b/tools/lib/perf/Documentation/libperf.txt
> @@ -162,6 +162,8 @@ SYNOPSIS
> int perf_evsel__disable(struct perf_evsel *evsel);
> int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
> bool perf_evsel__has_fd(struct perf_evsel *evsel, int fd);
> + int perf_evsel__refresh(struct perf_evsel *evsel, int refresh);
> + int perf_evsel__period(struct perf_evsel *evsel, int period);
> struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
> struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
> struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
> diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
> index 446934c0e5e5..578ae0050036 100644
> --- a/tools/lib/perf/evsel.c
> +++ b/tools/lib/perf/evsel.c
> @@ -334,7 +334,7 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread,
> }
>
> static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
> - int ioc, void *arg,
> + int ioc, unsigned long arg,
> int cpu_map_idx)
> {
> int thread;
> @@ -357,7 +357,7 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
>
> int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx)
> {
> - return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, cpu_map_idx);
> + return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0, cpu_map_idx);
> }
>
> int perf_evsel__enable(struct perf_evsel *evsel)
> @@ -366,13 +366,13 @@ int perf_evsel__enable(struct perf_evsel *evsel)
> int err = 0;
>
> for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
> - err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, i);
> + err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0, i);
> return err;
> }
>
> int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx)
> {
> - return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, cpu_map_idx);
> + return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0, cpu_map_idx);
> }
>
> int perf_evsel__disable(struct perf_evsel *evsel)
> @@ -381,7 +381,39 @@ int perf_evsel__disable(struct perf_evsel *evsel)
> int err = 0;
>
> for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
> - err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, i);
> + err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0, i);
> + return err;
> +}
> +
> +int perf_evsel__refresh(struct perf_evsel *evsel, int refresh)
> +{
> + int i;
> + int err = 0;
> +
> + for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
> + err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_REFRESH, refresh, i);
> + return err;
> +}
> +
> +int perf_evsel__period(struct perf_evsel *evsel, __u64 period)
> +{
> + struct perf_event_attr *attr;
> + int i;
> + int err = 0;
> +
> + attr = perf_evsel__attr(evsel);
> + if (!attr)
> + return -EINVAL;
I don't think it'd return NULL..
Thanks,
Namhyung
> +
> + for (i = 0; i < xyarray__max_x(evsel->fd); i++) {
> + err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_PERIOD,
> + (unsigned long)&period, i);
> + if (err)
> + return err;
> + }
> +
> + attr->sample_period = period;
> +
> return err;
> }
>
> @@ -392,7 +424,7 @@ int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
> for (i = 0; i < perf_cpu_map__nr(evsel->cpus) && !err; i++)
> err = perf_evsel__run_ioctl(evsel,
> PERF_EVENT_IOC_SET_FILTER,
> - (void *)filter, i);
> + (unsigned long)filter, i);
> return err;
> }
>
> diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
> index 19a7993d9021..2c5e52c17d28 100644
> --- a/tools/lib/perf/include/perf/evsel.h
> +++ b/tools/lib/perf/include/perf/evsel.h
> @@ -60,6 +60,8 @@ LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel);
> LIBPERF_API int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
> LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
> LIBPERF_API int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
> +LIBPERF_API int perf_evsel__refresh(struct perf_evsel *evsel, int refresh);
> +LIBPERF_API int perf_evsel__period(struct perf_evsel *evsel, __u64 period);
> LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
> LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
> LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
> diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
> index b2ace16bbc32..d97e208c5be8 100644
> --- a/tools/lib/perf/libperf.map
> +++ b/tools/lib/perf/libperf.map
> @@ -31,6 +31,8 @@ LIBPERF_0.0.1 {
> perf_evsel__munmap;
> perf_evsel__mmap_base;
> perf_evsel__read;
> + perf_evsel__refresh;
> + perf_evsel__period;
> perf_evsel__cpus;
> perf_evsel__threads;
> perf_evsel__attr;
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2022-05-20 19:39 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-22 9:38 [PATCH 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 1/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 2/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
2022-05-20 18:59 ` Namhyung Kim
2022-04-22 9:38 ` [PATCH 3/7] libperf: Add support for overflow handling of sampling events Shunsuke Nakamura
2022-05-20 19:28 ` Namhyung Kim
2022-04-22 9:38 ` [PATCH 4/7] libperf: Add perf_evsel__has_fd() functions Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 5/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
2022-05-20 19:38 ` Namhyung Kim
2022-04-22 9:38 ` [PATCH 6/7] libperf test: Add test_stat_overflow() Shunsuke Nakamura
2022-04-22 9:38 ` [PATCH 7/7] libperf test: Add test_stat_overflow_event() Shunsuke Nakamura
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.