* [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events
@ 2022-03-25 4:38 Shunsuke Nakamura
2022-03-25 4:38 ` [RFC PATCH v2 1/7] libperf tests: Fix typo in the error message Shunsuke Nakamura
` (7 more replies)
0 siblings, 8 replies; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4: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 fixes a typo in the error message that I noticed.
Second patch move 'open_flags' from tools/perf to evsel::open_flags.
Third patch adds a interface to perform IOC_REFRESH and IOC_PERIOD.
Fourth patch introduce perf_{evsel, evlist}__open_opt() with extensible
structure opts.
Fifth patch adds a interface to check overflowed events.
Sixth and seventh patch adds tests.
---
Previous version at:
https://lore.kernel.org/linux-perf-users/20220225103114.144239-1-nakamura.shun@fujitsu.com/
Changes in 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 tests: Fix typo in the error message
libperf: Move 'open_flags' from tools/perf to evsel::open_flags
libperf: Add perf_evsel__{refresh, period}() functions
libperf: Introduce perf_{evsel, evlist}__open_opt with extensible
struct opts
libperf: Add perf_evsel__check_overflow() functions
libperf test: Add test_stat_overflow()
libperf test: Add test_stat_overflow_event()
tools/lib/perf/Documentation/libperf.txt | 22 +++
tools/lib/perf/evlist.c | 20 +++
tools/lib/perf/evsel.c | 210 ++++++++++++++++++++++-
tools/lib/perf/include/internal/evsel.h | 2 +
tools/lib/perf/include/perf/evlist.h | 3 +
tools/lib/perf/include/perf/evsel.h | 35 ++++
tools/lib/perf/internal.h | 44 +++++
tools/lib/perf/libperf.map | 8 +
tools/lib/perf/tests/test-evlist.c | 135 ++++++++++++++-
tools/lib/perf/tests/test-evsel.c | 111 ++++++++++++
tools/perf/util/evsel.c | 16 +-
tools/perf/util/evsel.h | 1 -
12 files changed, 588 insertions(+), 19 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 23+ messages in thread
* [RFC PATCH v2 1/7] libperf tests: Fix typo in the error message
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
@ 2022-03-25 4:38 ` Shunsuke Nakamura
2022-03-25 19:52 ` Arnaldo Carvalho de Melo
2022-03-25 4:38 ` [RFC PATCH v2 2/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
` (6 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4:38 UTC (permalink / raw)
To: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa, namhyung
Cc: linux-kernel, linux-perf-users
This patch corrects a typo in the error message.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/tests/test-evlist.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c
index fa854c83b7e7..ed616fc19b4f 100644
--- a/tools/lib/perf/tests/test-evlist.c
+++ b/tools/lib/perf/tests/test-evlist.c
@@ -69,7 +69,7 @@ static int test_stat_cpu(void)
perf_evlist__set_maps(evlist, cpus, NULL);
err = perf_evlist__open(evlist);
- __T("failed to open evsel", err == 0);
+ __T("failed to open evlist", err == 0);
perf_evlist__for_each_evsel(evlist, evsel) {
cpus = perf_evsel__cpus(evsel);
@@ -130,7 +130,7 @@ static int test_stat_thread(void)
perf_evlist__set_maps(evlist, NULL, threads);
err = perf_evlist__open(evlist);
- __T("failed to open evsel", err == 0);
+ __T("failed to open evlist", err == 0);
perf_evlist__for_each_evsel(evlist, evsel) {
perf_evsel__read(evsel, 0, 0, &counts);
@@ -187,7 +187,7 @@ static int test_stat_thread_enable(void)
perf_evlist__set_maps(evlist, NULL, threads);
err = perf_evlist__open(evlist);
- __T("failed to open evsel", err == 0);
+ __T("failed to open evlist", err == 0);
perf_evlist__for_each_evsel(evlist, evsel) {
perf_evsel__read(evsel, 0, 0, &counts);
@@ -507,7 +507,7 @@ static int test_stat_multiplexing(void)
perf_evlist__set_maps(evlist, NULL, threads);
err = perf_evlist__open(evlist);
- __T("failed to open evsel", err == 0);
+ __T("failed to open evlist", err == 0);
perf_evlist__enable(evlist);
--
2.25.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH v2 2/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
2022-03-25 4:38 ` [RFC PATCH v2 1/7] libperf tests: Fix typo in the error message Shunsuke Nakamura
@ 2022-03-25 4:38 ` Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-03-25 4:38 ` [RFC PATCH v2 3/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
` (5 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4: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/evsel.c | 3 ++-
tools/lib/perf/include/internal/evsel.h | 2 ++
tools/perf/util/evsel.c | 16 +++++++++-------
tools/perf/util/evsel.h | 1 -
4 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
index 210ea7c06ce8..6640a333e6d9 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -26,6 +26,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 +159,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;
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 22d3267ce294..52c34552ee76 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] 23+ messages in thread
* [RFC PATCH v2 3/7] libperf: Add perf_evsel__{refresh, period}() functions
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
2022-03-25 4:38 ` [RFC PATCH v2 1/7] libperf tests: Fix typo in the error message Shunsuke Nakamura
2022-03-25 4:38 ` [RFC PATCH v2 2/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
@ 2022-03-25 4:38 ` Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-03-25 4:38 ` [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
` (4 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4: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__refresh_cpu()
perf_evsel__period()
perf_evsel__period_cpu()
to set the over flow limit and period.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/Documentation/libperf.txt | 5 ++
tools/lib/perf/evsel.c | 68 +++++++++++++++++++++---
tools/lib/perf/include/perf/evsel.h | 5 ++
tools/lib/perf/libperf.map | 4 ++
4 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index 32c5051c24eb..ae55e62fc4ce 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -146,6 +146,11 @@ 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);
+ int perf_evsel__refresh(struct perf_evsel *evsel, int refresh);
+ int perf_evsel__refresh_cpu(struct perf_evsel *evsel, int refresh,
+ int cpu_map_idx);
+ int perf_evsel__period(struct perf_evsel *evsel, int period);
+ int perf_evsel__period_cpu(struct perf_evsel *evsel, int period, int cpu_map_idx);
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 6640a333e6d9..b17842581dea 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -330,7 +330,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;
@@ -353,7 +353,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)
@@ -362,13 +362,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)
@@ -377,7 +377,63 @@ 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_cpu(struct perf_evsel *evsel, int refresh, int cpu_map_idx)
+{
+ return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_REFRESH, refresh, cpu_map_idx);
+}
+
+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_cpu(struct perf_evsel *evsel, __u64 period, int cpu_map_idx)
+{
+ struct perf_event_attr *attr;
+ int err = 0;
+
+ attr = perf_evsel__attr(evsel);
+ if (!attr)
+ return -EINVAL;
+
+ err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_PERIOD,
+ (unsigned long)&period, cpu_map_idx);
+ if (err)
+ return err;
+
+ attr->sample_period = period;
+
+ 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;
}
@@ -388,7 +444,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 2a9516b42d15..360ced734add 100644
--- a/tools/lib/perf/include/perf/evsel.h
+++ b/tools/lib/perf/include/perf/evsel.h
@@ -38,6 +38,11 @@ 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__refresh_cpu(struct perf_evsel *evsel, int refresh,
+ int cpu_map_idx);
+LIBPERF_API int perf_evsel__period(struct perf_evsel *evsel, __u64 period);
+LIBPERF_API int perf_evsel__period_cpu(struct perf_evsel *evsel, __u64 period, int cpu_map_idx);
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 6fa0d651576b..ab0f44e9bb57 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -29,6 +29,10 @@ LIBPERF_0.0.1 {
perf_evsel__munmap;
perf_evsel__mmap_base;
perf_evsel__read;
+ perf_evsel__refresh;
+ perf_evsel__refresh_cpu;
+ perf_evsel__period;
+ perf_evsel__period_cpu;
perf_evsel__cpus;
perf_evsel__threads;
perf_evsel__attr;
--
2.25.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (2 preceding siblings ...)
2022-03-25 4:38 ` [RFC PATCH v2 3/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
@ 2022-03-25 4:38 ` Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-03-30 13:50 ` Jiri Olsa
2022-03-25 4:38 ` [RFC PATCH v2 5/7] libperf: Add perf_evsel__check_overflow() functions Shunsuke Nakamura
` (3 subsequent siblings)
7 siblings, 2 replies; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4: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. This allows the user to set the open_flags
specified in perf_event_open and a signal handler to receive overflow
notifications for sampling events.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/Documentation/libperf.txt | 14 +++
tools/lib/perf/evlist.c | 20 +++++
tools/lib/perf/evsel.c | 105 +++++++++++++++++++++++
tools/lib/perf/include/perf/evlist.h | 3 +
tools/lib/perf/include/perf/evsel.h | 26 ++++++
tools/lib/perf/internal.h | 44 ++++++++++
tools/lib/perf/libperf.map | 2 +
7 files changed, 214 insertions(+)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index ae55e62fc4ce..700c1ce15159 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -131,6 +131,20 @@ 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 */
+ int flags; /* fcntl flags */
+ unsigned int signal;
+ int owner_type;
+ struct sigaction *sig;
+ };
+ #define perf_evsel_open_opts__last_field sig
+
+ #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 9a770bfdc804..6f136905d249 100644
--- a/tools/lib/perf/evlist.c
+++ b/tools/lib/perf/evlist.c
@@ -666,3 +666,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 b17842581dea..db9b7274feb5 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -1,4 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
@@ -16,8 +19,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)
@@ -511,3 +518,101 @@ void perf_counts_values__scale(struct perf_counts_values *count,
if (pscaled)
*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)
+{
+ 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);
+ 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/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 360ced734add..ecf30bc6303f 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,27 @@ 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 */
+ int flags; /* fcntl flags */
+ unsigned int signal;
+ int owner_type;
+ struct sigaction *sig;
+};
+#define perf_evsel_open_opts__last_field sig
+
+#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,
@@ -48,5 +70,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..637bf6793c26 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 ab0f44e9bb57..534614fbbb26 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -24,6 +24,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;
@@ -39,6 +40,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] 23+ messages in thread
* [RFC PATCH v2 5/7] libperf: Add perf_evsel__check_overflow() functions
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (3 preceding siblings ...)
2022-03-25 4:38 ` [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
@ 2022-03-25 4:38 ` Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-03-25 4:38 ` [RFC PATCH v2 6/7] libperf test: Add test_stat_overflow() Shunsuke Nakamura
` (2 subsequent siblings)
7 siblings, 1 reply; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4: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__check_overflow
perf_evsel__check_overflow_cpu
to check for perf events with the file descriptor specified in the
argument.
These functions can be used in signal handlers to check overflow.
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
---
tools/lib/perf/Documentation/libperf.txt | 3 +++
tools/lib/perf/evsel.c | 34 ++++++++++++++++++++++++
tools/lib/perf/include/perf/evsel.h | 4 +++
tools/lib/perf/libperf.map | 2 ++
4 files changed, 43 insertions(+)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index 700c1ce15159..4ae8d738b948 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -165,6 +165,9 @@ SYNOPSIS
int cpu_map_idx);
int perf_evsel__period(struct perf_evsel *evsel, int period);
int perf_evsel__period_cpu(struct perf_evsel *evsel, int period, int cpu_map_idx);
+ int perf_evsel__check_overflow(struct perf_evsel *evsel, int sig_fd, bool *overflow);
+ int perf_evsel__check_overflow_cpu(struct perf_evsel *evsel, int cpu_map_idx,
+ int sig_fd, bool *overflow);
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 db9b7274feb5..6ff3cf692df3 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -616,3 +616,37 @@ int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
return err;
}
+
+int perf_evsel__check_overflow_cpu(struct perf_evsel *evsel, int cpu_map_idx,
+ int sig_fd, bool *overflow)
+{
+ int thread;
+ int *fd;
+ int err = 0;
+
+ if (!overflow)
+ return -EINVAL;
+
+ *overflow = false;
+
+ for (thread = 0; thread < xyarray__max_y(evsel->fd) && !err; ++thread) {
+ fd = FD(evsel, cpu_map_idx, thread);
+ if (sig_fd <= 0 || !fd || *fd < 0)
+ err = -EINVAL;
+
+ if (sig_fd == *fd)
+ *overflow = true;
+ }
+
+ return err;
+}
+
+int perf_evsel__check_overflow(struct perf_evsel *evsel, int sig_fd, bool *overflow)
+{
+ int cpu_map_idx;
+ int err = 0;
+
+ for (cpu_map_idx = 0; cpu_map_idx < xyarray__max_x(evsel->fd) && !err; cpu_map_idx++)
+ err = perf_evsel__check_overflow_cpu(evsel, cpu_map_idx, sig_fd, overflow);
+ return err;
+}
diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
index ecf30bc6303f..d686cfbd88a6 100644
--- a/tools/lib/perf/include/perf/evsel.h
+++ b/tools/lib/perf/include/perf/evsel.h
@@ -74,5 +74,9 @@ 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 int perf_evsel__check_overflow(struct perf_evsel *evsel, int sig_fd,
+ bool *overflow);
+LIBPERF_API int perf_evsel__check_overflow_cpu(struct perf_evsel *evsel,
+ int cpu_map_idx, int sig_fd, bool *overflow);
#endif /* __LIBPERF_EVSEL_H */
diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
index 534614fbbb26..981eade34237 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -37,6 +37,8 @@ LIBPERF_0.0.1 {
perf_evsel__cpus;
perf_evsel__threads;
perf_evsel__attr;
+ perf_evsel__check_overflow;
+ perf_evsel__check_overflow_cpu;
perf_evlist__new;
perf_evlist__delete;
perf_evlist__open;
--
2.25.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [RFC PATCH v2 6/7] libperf test: Add test_stat_overflow()
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (4 preceding siblings ...)
2022-03-25 4:38 ` [RFC PATCH v2 5/7] libperf: Add perf_evsel__check_overflow() functions Shunsuke Nakamura
@ 2022-03-25 4:38 ` Shunsuke Nakamura
2022-03-25 4:38 ` [RFC PATCH v2 7/7] libperf test: Add test_stat_overflow_event() Shunsuke Nakamura
2022-03-30 13:50 ` [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Jiri Olsa
7 siblings, 0 replies; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4: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 | 111 ++++++++++++++++++++++++++++++
1 file changed, 111 insertions(+)
diff --git a/tools/lib/perf/tests/test-evsel.c b/tools/lib/perf/tests/test-evsel.c
index 89be89afb24d..8e7cf336fcd7 100644
--- a/tools/lib/perf/tests/test-evsel.c
+++ b/tools/lib/perf/tests/test-evsel.c
@@ -1,6 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#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 +16,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 = {0, 0, 0};
+static struct perf_evsel *s_evsel;
+
static int libperf_print(enum libperf_print_level level,
const char *fmt, va_list ap)
{
@@ -189,6 +206,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 = SIGIO,
+ .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;
+
+ 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_UP = %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);
+
+ sig_count.in = 0;
+ sig_count.hup = 0;
+ sig_count.others = 0;
+ sig_count.overflow = 0;
+ }
+
+ 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 +309,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] 23+ messages in thread
* [RFC PATCH v2 7/7] libperf test: Add test_stat_overflow_event()
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (5 preceding siblings ...)
2022-03-25 4:38 ` [RFC PATCH v2 6/7] libperf test: Add test_stat_overflow() Shunsuke Nakamura
@ 2022-03-25 4:38 ` Shunsuke Nakamura
2022-03-30 13:50 ` [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Jiri Olsa
7 siblings, 0 replies; 23+ messages in thread
From: Shunsuke Nakamura @ 2022-03-25 4: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 | 127 +++++++++++++++++++++++++++++
1 file changed, 127 insertions(+)
diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c
index ed616fc19b4f..ecfe35c64c40 100644
--- a/tools/lib/perf/tests/test-evlist.c
+++ b/tools/lib/perf/tests/test-evlist.c
@@ -6,6 +6,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>
@@ -25,6 +27,13 @@
#define EVENT_NUM 15
#define WAIT_COUNT 100000000UL
+static unsigned int overflow_flag;
+static struct signal_counts {
+ int hup;
+ int others;
+} sig_count = { 0, 0 };
+static struct perf_evlist *s_evlist;
+
static int libperf_print(enum libperf_print_level level,
const char *fmt, va_list ap)
{
@@ -571,6 +580,123 @@ static int test_stat_multiplexing(void)
return 0;
}
+static void sig_handler(int signo, siginfo_t *info, void *uc)
+{
+ struct perf_evsel *evsel;
+ int idx = 0;
+ bool overflow;
+ int err;
+
+ switch (info->si_code) {
+ case POLL_HUP:
+ perf_evlist__for_each_evsel(s_evlist, evsel) {
+ err = perf_evsel__check_overflow(evsel, info->si_fd, &overflow);
+ if (err)
+ fprintf(stderr, "failed to check evsel overflow %d\n", err);
+
+ if (overflow) {
+ overflow_flag = (1U << idx);
+ sig_count.hup++;
+ break;
+ }
+ idx++;
+ }
+ break;
+ default:
+ perf_evlist__for_each_evsel(s_evlist, evsel) {
+ err = perf_evsel__check_overflow(evsel, info->si_fd, &overflow);
+ if (err)
+ fprintf(stderr, "failed to check evsel overflow %d\n", err);
+
+ if (overflow) {
+ overflow_flag = (1U << idx);
+ sig_count.others++;
+ break;
+ }
+ idx++;
+ }
+ }
+}
+
+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 = SIGIO,
+ .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;
+
+ 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_UP = %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);
+
+ overflow_flag = 0;
+ sig_count.hup = 0;
+ 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;
@@ -583,6 +709,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] 23+ messages in thread
* Re: [RFC PATCH v2 1/7] libperf tests: Fix typo in the error message
2022-03-25 4:38 ` [RFC PATCH v2 1/7] libperf tests: Fix typo in the error message Shunsuke Nakamura
@ 2022-03-25 19:52 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 23+ messages in thread
From: Arnaldo Carvalho de Melo @ 2022-03-25 19:52 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: peterz, mingo, mark.rutland, alexander.shishkin, jolsa, namhyung,
linux-kernel, linux-perf-users
Em Fri, Mar 25, 2022 at 01:38:23PM +0900, Shunsuke Nakamura escreveu:
> This patch corrects a typo in the error message.
Thanks, applied. Will wait for review for the other patches in this
series.
- Arnaldo
> Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> ---
> tools/lib/perf/tests/test-evlist.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/tools/lib/perf/tests/test-evlist.c b/tools/lib/perf/tests/test-evlist.c
> index fa854c83b7e7..ed616fc19b4f 100644
> --- a/tools/lib/perf/tests/test-evlist.c
> +++ b/tools/lib/perf/tests/test-evlist.c
> @@ -69,7 +69,7 @@ static int test_stat_cpu(void)
> perf_evlist__set_maps(evlist, cpus, NULL);
>
> err = perf_evlist__open(evlist);
> - __T("failed to open evsel", err == 0);
> + __T("failed to open evlist", err == 0);
>
> perf_evlist__for_each_evsel(evlist, evsel) {
> cpus = perf_evsel__cpus(evsel);
> @@ -130,7 +130,7 @@ static int test_stat_thread(void)
> perf_evlist__set_maps(evlist, NULL, threads);
>
> err = perf_evlist__open(evlist);
> - __T("failed to open evsel", err == 0);
> + __T("failed to open evlist", err == 0);
>
> perf_evlist__for_each_evsel(evlist, evsel) {
> perf_evsel__read(evsel, 0, 0, &counts);
> @@ -187,7 +187,7 @@ static int test_stat_thread_enable(void)
> perf_evlist__set_maps(evlist, NULL, threads);
>
> err = perf_evlist__open(evlist);
> - __T("failed to open evsel", err == 0);
> + __T("failed to open evlist", err == 0);
>
> perf_evlist__for_each_evsel(evlist, evsel) {
> perf_evsel__read(evsel, 0, 0, &counts);
> @@ -507,7 +507,7 @@ static int test_stat_multiplexing(void)
> perf_evlist__set_maps(evlist, NULL, threads);
>
> err = perf_evlist__open(evlist);
> - __T("failed to open evsel", err == 0);
> + __T("failed to open evlist", err == 0);
>
> perf_evlist__enable(evlist);
>
> --
> 2.25.1
--
- Arnaldo
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
` (6 preceding siblings ...)
2022-03-25 4:38 ` [RFC PATCH v2 7/7] libperf test: Add test_stat_overflow_event() Shunsuke Nakamura
@ 2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:23 ` nakamura.shun
7 siblings, 1 reply; 23+ messages in thread
From: Jiri Olsa @ 2022-03-30 13:50 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
On Fri, Mar 25, 2022 at 01:38:22PM +0900, Shunsuke Nakamura wrote:
> This patch series adds interface for overflow check of sampling events
> to libperf.
>
> First patch fixes a typo in the error message that I noticed.
>
> Second patch move 'open_flags' from tools/perf to evsel::open_flags.
>
> Third patch adds a interface to perform IOC_REFRESH and IOC_PERIOD.
>
> Fourth patch introduce perf_{evsel, evlist}__open_opt() with extensible
> structure opts.
>
> Fifth patch adds a interface to check overflowed events.
>
> Sixth and seventh patch adds tests.
>
> ---
> Previous version at:
> https://lore.kernel.org/linux-perf-users/20220225103114.144239-1-nakamura.shun@fujitsu.com/
>
> Changes in 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
looks good.. it got more clear to me, sending some comments
>
>
> Shunsuke Nakamura (7):
> libperf tests: Fix typo in the error message
> libperf: Move 'open_flags' from tools/perf to evsel::open_flags
> libperf: Add perf_evsel__{refresh, period}() functions
> libperf: Introduce perf_{evsel, evlist}__open_opt with extensible
> struct opts
> libperf: Add perf_evsel__check_overflow() functions
> libperf test: Add test_stat_overflow()
> libperf test: Add test_stat_overflow_event()
I'm getting:
[root@krava perf]# make tests
running static:
- running tests/test-cpumap.c...OK
- running tests/test-threadmap.c...OK
- running tests/test-evlist.c...OK
- running tests/test-evsel.c...FAILED tests/test-evsel.c:286 failed to overflow count
FAILED tests/test-evsel.c:286 failed to overflow count
FAILED (2)
FAILED tests/main.c:13 test evsel
make: *** [Makefile:162: tests] Error 255
thanks,
jirka
>
> tools/lib/perf/Documentation/libperf.txt | 22 +++
> tools/lib/perf/evlist.c | 20 +++
> tools/lib/perf/evsel.c | 210 ++++++++++++++++++++++-
> tools/lib/perf/include/internal/evsel.h | 2 +
> tools/lib/perf/include/perf/evlist.h | 3 +
> tools/lib/perf/include/perf/evsel.h | 35 ++++
> tools/lib/perf/internal.h | 44 +++++
> tools/lib/perf/libperf.map | 8 +
> tools/lib/perf/tests/test-evlist.c | 135 ++++++++++++++-
> tools/lib/perf/tests/test-evsel.c | 111 ++++++++++++
> tools/perf/util/evsel.c | 16 +-
> tools/perf/util/evsel.h | 1 -
> 12 files changed, 588 insertions(+), 19 deletions(-)
>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH v2 2/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags
2022-03-25 4:38 ` [RFC PATCH v2 2/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
@ 2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:27 ` nakamura.shun
0 siblings, 1 reply; 23+ messages in thread
From: Jiri Olsa @ 2022-03-30 13:50 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
On Fri, Mar 25, 2022 at 01:38:24PM +0900, Shunsuke Nakamura wrote:
> 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/evsel.c | 3 ++-
> tools/lib/perf/include/internal/evsel.h | 2 ++
> tools/perf/util/evsel.c | 16 +++++++++-------
> tools/perf/util/evsel.h | 1 -
> 4 files changed, 13 insertions(+), 9 deletions(-)
>
> diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
> index 210ea7c06ce8..6640a333e6d9 100644
> --- a/tools/lib/perf/evsel.c
> +++ b/tools/lib/perf/evsel.c
> @@ -26,6 +26,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 +159,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);
please keep this change just open_flags field move,
this change should go to later patch
jirka
>
> if (fd < 0)
> return -errno;
> 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 22d3267ce294..52c34552ee76 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 [flat|nested] 23+ messages in thread
* Re: [RFC PATCH v2 3/7] libperf: Add perf_evsel__{refresh, period}() functions
2022-03-25 4:38 ` [RFC PATCH v2 3/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
@ 2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:29 ` nakamura.shun
0 siblings, 1 reply; 23+ messages in thread
From: Jiri Olsa @ 2022-03-30 13:50 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
On Fri, Mar 25, 2022 at 01:38:25PM +0900, Shunsuke Nakamura wrote:
SNIP
> +int perf_evsel__refresh_cpu(struct perf_evsel *evsel, int refresh, int cpu_map_idx)
> +{
> + return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_REFRESH, refresh, cpu_map_idx);
> +}
> +
> +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_cpu(struct perf_evsel *evsel, __u64 period, int cpu_map_idx)
> +{
> + struct perf_event_attr *attr;
> + int err = 0;
> +
> + attr = perf_evsel__attr(evsel);
> + if (!attr)
> + return -EINVAL;
> +
> + err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_PERIOD,
> + (unsigned long)&period, cpu_map_idx);
> + if (err)
> + return err;
> +
> + attr->sample_period = period;
what's the point in updating attr? this will be used after
event is created right?
> +
> + 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;
same as above
thanks,
jirka
> +
> return err;
> }
>
SNIP
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts
2022-03-25 4:38 ` [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
@ 2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:31 ` nakamura.shun
2022-03-30 13:50 ` Jiri Olsa
1 sibling, 1 reply; 23+ messages in thread
From: Jiri Olsa @ 2022-03-30 13:50 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
On Fri, Mar 25, 2022 at 01:38:26PM +0900, Shunsuke Nakamura wrote:
> Introduce perf_{evsel, evlist}__open_opt with extensible structure opts.
> The mechanism of the extensible structure opts imitates
> tools/lib/bpf/libbpf.h. This allows the user to set the open_flags
> specified in perf_event_open and a signal handler to receive overflow
> notifications for sampling events.
>
> Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> ---
> tools/lib/perf/Documentation/libperf.txt | 14 +++
> tools/lib/perf/evlist.c | 20 +++++
> tools/lib/perf/evsel.c | 105 +++++++++++++++++++++++
> tools/lib/perf/include/perf/evlist.h | 3 +
> tools/lib/perf/include/perf/evsel.h | 26 ++++++
> tools/lib/perf/internal.h | 44 ++++++++++
> tools/lib/perf/libperf.map | 2 +
> 7 files changed, 214 insertions(+)
>
> diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
> index ae55e62fc4ce..700c1ce15159 100644
> --- a/tools/lib/perf/Documentation/libperf.txt
> +++ b/tools/lib/perf/Documentation/libperf.txt
> @@ -131,6 +131,20 @@ 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 */
> + int flags; /* fcntl flags */
> + unsigned int signal;
> + int owner_type;
> + struct sigaction *sig;
> + };
> + #define perf_evsel_open_opts__last_field sig
> +
> + #define LIBPERF_OPTS(TYPE, NAME, ...)
> +
SNIP
> +
> +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);
> + if (err)
> + return err;
> +
> + err = perf_evsel__set_signal_handler(evsel, opts);
> + if (err)
> + return err;
please move the signal stuff handling into separate patch
together with the related fields in opts struct
thanks,
jirka
> +
> + 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 360ced734add..ecf30bc6303f 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,27 @@ 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 */
> + int flags; /* fcntl flags */
> + unsigned int signal;
> + int owner_type;
> + struct sigaction *sig;
> +};
> +#define perf_evsel_open_opts__last_field sig
> +
> +#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,
> @@ -48,5 +70,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..637bf6793c26 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 ab0f44e9bb57..534614fbbb26 100644
> --- a/tools/lib/perf/libperf.map
> +++ b/tools/lib/perf/libperf.map
> @@ -24,6 +24,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;
> @@ -39,6 +40,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] 23+ messages in thread
* Re: [RFC PATCH v2 5/7] libperf: Add perf_evsel__check_overflow() functions
2022-03-25 4:38 ` [RFC PATCH v2 5/7] libperf: Add perf_evsel__check_overflow() functions Shunsuke Nakamura
@ 2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:35 ` nakamura.shun
0 siblings, 1 reply; 23+ messages in thread
From: Jiri Olsa @ 2022-03-30 13:50 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
On Fri, Mar 25, 2022 at 01:38:27PM +0900, Shunsuke Nakamura wrote:
> Add the following functions:
>
> perf_evsel__check_overflow
> perf_evsel__check_overflow_cpu
>
> to check for perf events with the file descriptor specified in the
> argument.
> These functions can be used in signal handlers to check overflow.
>
> Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> ---
> tools/lib/perf/Documentation/libperf.txt | 3 +++
> tools/lib/perf/evsel.c | 34 ++++++++++++++++++++++++
> tools/lib/perf/include/perf/evsel.h | 4 +++
> tools/lib/perf/libperf.map | 2 ++
> 4 files changed, 43 insertions(+)
>
> diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
> index 700c1ce15159..4ae8d738b948 100644
> --- a/tools/lib/perf/Documentation/libperf.txt
> +++ b/tools/lib/perf/Documentation/libperf.txt
> @@ -165,6 +165,9 @@ SYNOPSIS
> int cpu_map_idx);
> int perf_evsel__period(struct perf_evsel *evsel, int period);
> int perf_evsel__period_cpu(struct perf_evsel *evsel, int period, int cpu_map_idx);
> + int perf_evsel__check_overflow(struct perf_evsel *evsel, int sig_fd, bool *overflow);
> + int perf_evsel__check_overflow_cpu(struct perf_evsel *evsel, int cpu_map_idx,
> + int sig_fd, bool *overflow);
should this be more like:
perf_evsel__has_fd(struct perf_evsel *evsel, int fd)
also why do we need to export *_cpu version for this?
I don't see it used in the test
> 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 db9b7274feb5..6ff3cf692df3 100644
> --- a/tools/lib/perf/evsel.c
> +++ b/tools/lib/perf/evsel.c
> @@ -616,3 +616,37 @@ int perf_evsel__open_opts(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
>
> return err;
> }
> +
> +int perf_evsel__check_overflow_cpu(struct perf_evsel *evsel, int cpu_map_idx,
> + int sig_fd, bool *overflow)
> +{
> + int thread;
> + int *fd;
> + int err = 0;
> +
> + if (!overflow)
> + return -EINVAL;
> +
> + *overflow = false;
> +
> + for (thread = 0; thread < xyarray__max_y(evsel->fd) && !err; ++thread) {
> + fd = FD(evsel, cpu_map_idx, thread);
> + if (sig_fd <= 0 || !fd || *fd < 0)
> + err = -EINVAL;
sig_fd check should be before the loop
jirka
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts
2022-03-25 4:38 ` [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
@ 2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:34 ` nakamura.shun
1 sibling, 1 reply; 23+ messages in thread
From: Jiri Olsa @ 2022-03-30 13:50 UTC (permalink / raw)
To: Shunsuke Nakamura
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
On Fri, Mar 25, 2022 at 01:38:26PM +0900, Shunsuke Nakamura wrote:
SNIP
> diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c
> index b17842581dea..db9b7274feb5 100644
> --- a/tools/lib/perf/evsel.c
> +++ b/tools/lib/perf/evsel.c
> @@ -1,4 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
I think we can make this global set in Makefile, like we do in perf
jirka
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events
2022-03-30 13:50 ` [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Jiri Olsa
@ 2022-04-11 8:23 ` nakamura.shun
2022-04-19 20:15 ` Jiri Olsa
0 siblings, 1 reply; 23+ messages in thread
From: nakamura.shun @ 2022-04-11 8:23 UTC (permalink / raw)
To: 'Jiri Olsa'
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
Hi jirka
Sorry for the late reply.
> >
> > Shunsuke Nakamura (7):
> > libperf tests: Fix typo in the error message
> > libperf: Move 'open_flags' from tools/perf to evsel::open_flags
> > libperf: Add perf_evsel__{refresh, period}() functions
> > libperf: Introduce perf_{evsel, evlist}__open_opt with extensible
> > struct opts
> > libperf: Add perf_evsel__check_overflow() functions
> > libperf test: Add test_stat_overflow()
> > libperf test: Add test_stat_overflow_event()
>
> I'm getting:
>
> [root@krava perf]# make tests
> running static:
> - running tests/test-cpumap.c...OK
> - running tests/test-threadmap.c...OK
> - running tests/test-evlist.c...OK
> - running tests/test-evsel.c...FAILED tests/test-evsel.c:286 failed to overflow
> count FAILED tests/test-evsel.c:286 failed to overflow count
> FAILED (2)
> FAILED tests/main.c:13 test evsel
> make: *** [Makefile:162: tests] Error 255
>
Thanks for telling me.
However, we could not reproduce the test failure in our environment.
Could you please tell me the results of your test with the addition of V=1?
Best Regards
Shunsuke
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [RFC PATCH v2 2/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags
2022-03-30 13:50 ` Jiri Olsa
@ 2022-04-11 8:27 ` nakamura.shun
0 siblings, 0 replies; 23+ messages in thread
From: nakamura.shun @ 2022-04-11 8:27 UTC (permalink / raw)
To: 'Jiri Olsa'
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
Hi jirka
> > struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) @@
> > -158,7 +159,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);
>
> please keep this change just open_flags field move, this change should go to
> later patch
>
I'll fix it.
Best Regards
Shunsuke
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [RFC PATCH v2 3/7] libperf: Add perf_evsel__{refresh, period}() functions
2022-03-30 13:50 ` Jiri Olsa
@ 2022-04-11 8:29 ` nakamura.shun
0 siblings, 0 replies; 23+ messages in thread
From: nakamura.shun @ 2022-04-11 8:29 UTC (permalink / raw)
To: 'Jiri Olsa'
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
Hi jirka
> On Fri, Mar 25, 2022 at 01:38:25PM +0900, Shunsuke Nakamura wrote:
>
> SNIP
>
> > +int perf_evsel__refresh_cpu(struct perf_evsel *evsel, int refresh,
> > +int cpu_map_idx) {
> > + return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_REFRESH,
> refresh,
> > +cpu_map_idx); }
> > +
> > +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_cpu(struct perf_evsel *evsel, __u64 period,
> > +int cpu_map_idx) {
> > + struct perf_event_attr *attr;
> > + int err = 0;
> > +
> > + attr = perf_evsel__attr(evsel);
> > + if (!attr)
> > + return -EINVAL;
> > +
> > + err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_PERIOD,
> > + (unsigned long)&period, cpu_map_idx);
> > + if (err)
> > + return err;
> > +
> > + attr->sample_period = period;
>
> what's the point in updating attr? this will be used after event is created right?
>
This is to maintain consistency between evsel->attr->sample_period and the sample_period of the created event.
Users can reference evsel->attr->sample_period using perf_evsel__attr().
So I thought it was necessary to update the sample_period of the event and the sample_period of evsel to avoid discrepancies.
Best Regards
Shunsuke
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts
2022-03-30 13:50 ` Jiri Olsa
@ 2022-04-11 8:31 ` nakamura.shun
0 siblings, 0 replies; 23+ messages in thread
From: nakamura.shun @ 2022-04-11 8:31 UTC (permalink / raw)
To: 'Jiri Olsa'
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
Hi jirka
> On Fri, Mar 25, 2022 at 01:38:26PM +0900, Shunsuke Nakamura wrote:
> > Introduce perf_{evsel, evlist}__open_opt with extensible structure opts.
> > The mechanism of the extensible structure opts imitates
> > tools/lib/bpf/libbpf.h. This allows the user to set the open_flags
> > specified in perf_event_open and a signal handler to receive overflow
> > notifications for sampling events.
> >
> > Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> > ---
> > tools/lib/perf/Documentation/libperf.txt | 14 +++
> > tools/lib/perf/evlist.c | 20 +++++
> > tools/lib/perf/evsel.c | 105
> +++++++++++++++++++++++
> > tools/lib/perf/include/perf/evlist.h | 3 +
> > tools/lib/perf/include/perf/evsel.h | 26 ++++++
> > tools/lib/perf/internal.h | 44 ++++++++++
> > tools/lib/perf/libperf.map | 2 +
> > 7 files changed, 214 insertions(+)
> >
> > diff --git a/tools/lib/perf/Documentation/libperf.txt
> > b/tools/lib/perf/Documentation/libperf.txt
> > index ae55e62fc4ce..700c1ce15159 100644
> > --- a/tools/lib/perf/Documentation/libperf.txt
> > +++ b/tools/lib/perf/Documentation/libperf.txt
> > @@ -131,6 +131,20 @@ 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 */
> > + int flags; /* fcntl flags */
> > + unsigned int signal;
> > + int owner_type;
> > + struct sigaction *sig;
> > + };
> > + #define perf_evsel_open_opts__last_field sig
> > +
> > + #define LIBPERF_OPTS(TYPE, NAME, ...)
> > +
>
> SNIP
>
> > +
> > +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);
> > + if (err)
> > + return err;
> > +
> > + err = perf_evsel__set_signal_handler(evsel, opts);
> > + if (err)
> > + return err;
>
> please move the signal stuff handling into separate patch together with the
> related fields in opts struct
>
I'll fix it.
Best Regards
Shunsuke
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts
2022-03-30 13:50 ` Jiri Olsa
@ 2022-04-11 8:34 ` nakamura.shun
0 siblings, 0 replies; 23+ messages in thread
From: nakamura.shun @ 2022-04-11 8:34 UTC (permalink / raw)
To: 'Jiri Olsa'
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
Hi jirka
> On Fri, Mar 25, 2022 at 01:38:26PM +0900, Shunsuke Nakamura wrote:
>
> SNIP
>
> > diff --git a/tools/lib/perf/evsel.c b/tools/lib/perf/evsel.c index
> > b17842581dea..db9b7274feb5 100644
> > --- a/tools/lib/perf/evsel.c
> > +++ b/tools/lib/perf/evsel.c
> > @@ -1,4 +1,7 @@
> > // SPDX-License-Identifier: GPL-2.0
> > +#ifndef _GNU_SOURCE
> > +#define _GNU_SOURCE
> > +#endif
>
> I think we can make this global set in Makefile, like we do in perf
>
I'll fix it.
Best Regards
Shunsuke
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [RFC PATCH v2 5/7] libperf: Add perf_evsel__check_overflow() functions
2022-03-30 13:50 ` Jiri Olsa
@ 2022-04-11 8:35 ` nakamura.shun
0 siblings, 0 replies; 23+ messages in thread
From: nakamura.shun @ 2022-04-11 8:35 UTC (permalink / raw)
To: 'Jiri Olsa'
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
Hi jirka
> On Fri, Mar 25, 2022 at 01:38:27PM +0900, Shunsuke Nakamura wrote:
> > Add the following functions:
> >
> > perf_evsel__check_overflow
> > perf_evsel__check_overflow_cpu
> >
> > to check for perf events with the file descriptor specified in the
> > argument.
> > These functions can be used in signal handlers to check overflow.
> >
> > Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
> > ---
> > tools/lib/perf/Documentation/libperf.txt | 3 +++
> > tools/lib/perf/evsel.c | 34
> ++++++++++++++++++++++++
> > tools/lib/perf/include/perf/evsel.h | 4 +++
> > tools/lib/perf/libperf.map | 2 ++
> > 4 files changed, 43 insertions(+)
> >
> > diff --git a/tools/lib/perf/Documentation/libperf.txt
> > b/tools/lib/perf/Documentation/libperf.txt
> > index 700c1ce15159..4ae8d738b948 100644
> > --- a/tools/lib/perf/Documentation/libperf.txt
> > +++ b/tools/lib/perf/Documentation/libperf.txt
> > @@ -165,6 +165,9 @@ SYNOPSIS
> > int cpu_map_idx);
> > int perf_evsel__period(struct perf_evsel *evsel, int period);
> > int perf_evsel__period_cpu(struct perf_evsel *evsel, int period,
> > int cpu_map_idx);
> > + int perf_evsel__check_overflow(struct perf_evsel *evsel, int
> > + sig_fd, bool *overflow); int perf_evsel__check_overflow_cpu(struct
> perf_evsel *evsel, int cpu_map_idx,
> > + int sig_fd, bool *overflow);
>
> should this be more like:
>
> perf_evsel__has_fd(struct perf_evsel *evsel, int fd)
>
I'll fix it.
> also why do we need to export *_cpu version for this?
> I don't see it used in the test
>
Sorry, not necessary.
I'll fix it.
> > 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
> > db9b7274feb5..6ff3cf692df3 100644
> > --- a/tools/lib/perf/evsel.c
> > +++ b/tools/lib/perf/evsel.c
> > @@ -616,3 +616,37 @@ int perf_evsel__open_opts(struct perf_evsel
> > *evsel, struct perf_cpu_map *cpus,
> >
> > return err;
> > }
> > +
> > +int perf_evsel__check_overflow_cpu(struct perf_evsel *evsel, int
> cpu_map_idx,
> > + int sig_fd, bool *overflow)
> > +{
> > + int thread;
> > + int *fd;
> > + int err = 0;
> > +
> > + if (!overflow)
> > + return -EINVAL;
> > +
> > + *overflow = false;
> > +
> > + for (thread = 0; thread < xyarray__max_y(evsel->fd) && !err; ++thread)
> {
> > + fd = FD(evsel, cpu_map_idx, thread);
> > + if (sig_fd <= 0 || !fd || *fd < 0)
> > + err = -EINVAL;
>
> sig_fd check should be before the loop
>
I'll fix it.
Best Regards
Shunsuke
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events
2022-04-11 8:23 ` nakamura.shun
@ 2022-04-19 20:15 ` Jiri Olsa
2022-04-20 8:22 ` nakamura.shun
0 siblings, 1 reply; 23+ messages in thread
From: Jiri Olsa @ 2022-04-19 20:15 UTC (permalink / raw)
To: nakamura.shun
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
On Mon, Apr 11, 2022 at 08:23:54AM +0000, nakamura.shun@fujitsu.com wrote:
> Hi jirka
>
> Sorry for the late reply.
>
> > >
> > > Shunsuke Nakamura (7):
> > > libperf tests: Fix typo in the error message
> > > libperf: Move 'open_flags' from tools/perf to evsel::open_flags
> > > libperf: Add perf_evsel__{refresh, period}() functions
> > > libperf: Introduce perf_{evsel, evlist}__open_opt with extensible
> > > struct opts
> > > libperf: Add perf_evsel__check_overflow() functions
> > > libperf test: Add test_stat_overflow()
> > > libperf test: Add test_stat_overflow_event()
> >
> > I'm getting:
> >
> > [root@krava perf]# make tests
> > running static:
> > - running tests/test-cpumap.c...OK
> > - running tests/test-threadmap.c...OK
> > - running tests/test-evlist.c...OK
> > - running tests/test-evsel.c...FAILED tests/test-evsel.c:286 failed to overflow
> > count FAILED tests/test-evsel.c:286 failed to overflow count
> > FAILED (2)
> > FAILED tests/main.c:13 test evsel
> > make: *** [Makefile:162: tests] Error 255
> >
> Thanks for telling me.
> However, we could not reproduce the test failure in our environment.
> Could you please tell me the results of your test with the addition of V=1?
sorry, forgot to answer this one..
[root@krava perf]# LD_LIBRARY_PATH=. ./tests-shared -v
- running tests/test-cpumap.c...OK
- running tests/test-threadmap.c...OK
- running tests/test-evlist.c...
Event 0 -- Raw count = 231217013, run = 10196083, enable = 22183091
Scaled count = 503046909 (45.96%, 10196083/22183091)
Event 1 -- Raw count = 247219790, run = 10946246, enable = 22182044
Scaled count = 500979080 (49.35%, 10946246/22182044)
Event 2 -- Raw count = 268999685, run = 11943490, enable = 22180868
Scaled count = 499573115 (53.85%, 11943490/22180868)
Event 3 -- Raw count = 291383974, run = 12941069, enable = 22179798
Scaled count = 499405241 (58.35%, 12941069/22179798)
Event 4 -- Raw count = 314293846, run = 13938576, enable = 22178649
Scaled count = 500095052 (62.85%, 13938576/22178649)
Event 5 -- Raw count = 337393782, run = 14935798, enable = 22177192
Scaled count = 500974014 (67.35%, 14935798/22177192)
Event 6 -- Raw count = 360218294, run = 15933314, enable = 22175507
Scaled count = 501340982 (71.85%, 15933314/22175507)
Event 7 -- Raw count = 365516630, run = 16179860, enable = 22173686
Scaled count = 500922194 (72.97%, 16179860/22173686)
Event 8 -- Raw count = 365180177, run = 16178058, enable = 22171705
Scaled count = 500472130 (72.97%, 16178058/22171705)
Event 9 -- Raw count = 341205844, run = 15233252, enable = 22169603
Scaled count = 496571454 (68.71%, 15233252/22169603)
Event 10 -- Raw count = 318204949, run = 14234754, enable = 22167081
Scaled count = 495524887 (64.22%, 14234754/22167081)
Event 11 -- Raw count = 296671131, run = 13236210, enable = 22164791
Scaled count = 496792783 (59.72%, 13236210/22164791)
Event 12 -- Raw count = 276639189, run = 12237128, enable = 22162629
Scaled count = 501020477 (55.22%, 12237128/22162629)
Event 13 -- Raw count = 255437518, run = 11238588, enable = 22160497
Scaled count = 503677361 (50.71%, 11238588/22160497)
Event 14 -- Raw count = 232427791, run = 10239844, enable = 22158353
Scaled count = 502958545 (46.21%, 10239844/22158353)
Expected: 500221918
High: 503677361 Low: 231217013 Average: 500223614
Average Error = 0.00%
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...
loop = 65536, count = 328183
loop = 131072, count = 655863
loop = 262144, count = 1320613
loop = 524288, count = 2621943
loop = 1048576, count = 5243383
loop = 65536, count = 66349
loop = 131072, count = 131789
loop = 262144, count = 264697
loop = 524288, count = 528484
loop = 1048576, count = 1056485
period = 1000000
overflow limit = 3, overflow count = 2, POLL_IN = 2, POLL_UP = 0, other signal event = 0
FAILED tests/test-evsel.c:286 failed to overflow count
period = 1000000
overflow limit = 3, overflow count = 5, POLL_IN = 4, POLL_UP = 1, other signal event = 0
FAILED tests/test-evsel.c:286 failed to overflow count
FAILED (2)
FAILED tests/main.c:13 test evsel
jirka
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events
2022-04-19 20:15 ` Jiri Olsa
@ 2022-04-20 8:22 ` nakamura.shun
0 siblings, 0 replies; 23+ messages in thread
From: nakamura.shun @ 2022-04-20 8:22 UTC (permalink / raw)
To: 'Jiri Olsa'
Cc: peterz, mingo, acme, mark.rutland, alexander.shishkin, jolsa,
namhyung, linux-kernel, linux-perf-users
Hi jirka
> On Mon, Apr 11, 2022 at 08:23:54AM +0000, nakamura.shun@fujitsu.com wrote:
> > Hi jirka
> >
> > Sorry for the late reply.
> >
> > > >
> > > > Shunsuke Nakamura (7):
> > > > libperf tests: Fix typo in the error message
> > > > libperf: Move 'open_flags' from tools/perf to evsel::open_flags
> > > > libperf: Add perf_evsel__{refresh, period}() functions
> > > > libperf: Introduce perf_{evsel, evlist}__open_opt with extensible
> > > > struct opts
> > > > libperf: Add perf_evsel__check_overflow() functions
> > > > libperf test: Add test_stat_overflow()
> > > > libperf test: Add test_stat_overflow_event()
> > >
> > > I'm getting:
> > >
> > > [root@krava perf]# make tests
> > > running static:
> > > - running tests/test-cpumap.c...OK
> > > - running tests/test-threadmap.c...OK
> > > - running tests/test-evlist.c...OK
> > > - running tests/test-evsel.c...FAILED tests/test-evsel.c:286 failed
> > > to overflow count FAILED tests/test-evsel.c:286 failed to overflow count
> > > FAILED (2)
> > > FAILED tests/main.c:13 test evsel
> > > make: *** [Makefile:162: tests] Error 255
> > >
> > Thanks for telling me.
> > However, we could not reproduce the test failure in our environment.
> > Could you please tell me the results of your test with the addition of V=1?
>
> sorry, forgot to answer this one..
>
Thanks for the information.
> [root@krava perf]# LD_LIBRARY_PATH=. ./tests-shared -v
> - running tests/test-cpumap.c...OK
> - running tests/test-threadmap.c...OK
> - running tests/test-evlist.c...
> Event 0 -- Raw count = 231217013, run = 10196083, enable = 22183091
> Scaled count = 503046909 (45.96%, 10196083/22183091) Event 1 --
> Raw count = 247219790, run = 10946246, enable = 22182044
> Scaled count = 500979080 (49.35%, 10946246/22182044) Event 2 --
> Raw count = 268999685, run = 11943490, enable = 22180868
> Scaled count = 499573115 (53.85%, 11943490/22180868) Event 3 --
> Raw count = 291383974, run = 12941069, enable = 22179798
> Scaled count = 499405241 (58.35%, 12941069/22179798) Event 4 --
> Raw count = 314293846, run = 13938576, enable = 22178649
> Scaled count = 500095052 (62.85%, 13938576/22178649) Event 5 --
> Raw count = 337393782, run = 14935798, enable = 22177192
> Scaled count = 500974014 (67.35%, 14935798/22177192) Event 6 --
> Raw count = 360218294, run = 15933314, enable = 22175507
> Scaled count = 501340982 (71.85%, 15933314/22175507) Event 7 --
> Raw count = 365516630, run = 16179860, enable = 22173686
> Scaled count = 500922194 (72.97%, 16179860/22173686) Event 8 --
> Raw count = 365180177, run = 16178058, enable = 22171705
> Scaled count = 500472130 (72.97%, 16178058/22171705) Event 9 --
> Raw count = 341205844, run = 15233252, enable = 22169603
> Scaled count = 496571454 (68.71%, 15233252/22169603) Event 10 --
> Raw count = 318204949, run = 14234754, enable = 22167081
> Scaled count = 495524887 (64.22%, 14234754/22167081) Event 11 --
> Raw count = 296671131, run = 13236210, enable = 22164791
> Scaled count = 496792783 (59.72%, 13236210/22164791) Event 12 --
> Raw count = 276639189, run = 12237128, enable = 22162629
> Scaled count = 501020477 (55.22%, 12237128/22162629) Event 13 --
> Raw count = 255437518, run = 11238588, enable = 22160497
> Scaled count = 503677361 (50.71%, 11238588/22160497) Event 14 --
> Raw count = 232427791, run = 10239844, enable = 22158353
> Scaled count = 502958545 (46.21%, 10239844/22158353)
> Expected: 500221918
> High: 503677361 Low: 231217013 Average: 500223614
> Average Error = 0.00%
> 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...
> loop = 65536, count = 328183
> loop = 131072, count = 655863
> loop = 262144, count = 1320613
> loop = 524288, count = 2621943
> loop = 1048576, count = 5243383
> loop = 65536, count = 66349
> loop = 131072, count = 131789
> loop = 262144, count = 264697
> loop = 524288, count = 528484
> loop = 1048576, count = 1056485
> period = 1000000
> overflow limit = 3, overflow count = 2, POLL_IN = 2, POLL_UP = 0, other
> signal event = 0 FAILED tests/test-evsel.c:286 failed to overflow count
This test was using standard signals (SIGIO), but after changing to real-time signals,
I confirmed that the test succeeded.
When using standard signals, it seems that if there is an overlapping timing of standard signals,
the signals generated later will be dropped.
> period = 1000000
> overflow limit = 3, overflow count = 5, POLL_IN = 4, POLL_UP = 1, other
> signal event = 0 FAILED tests/test-evsel.c:286 failed to overflow count
Fixed implementation of overflow counter not clearing on test failure.
> FAILED (2)
> FAILED tests/main.c:13 test evsel
>
I will post a v3 patch with the above fixes.
Best Regards
Shunsuke
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2022-04-20 8:23 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-25 4:38 [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Shunsuke Nakamura
2022-03-25 4:38 ` [RFC PATCH v2 1/7] libperf tests: Fix typo in the error message Shunsuke Nakamura
2022-03-25 19:52 ` Arnaldo Carvalho de Melo
2022-03-25 4:38 ` [RFC PATCH v2 2/7] libperf: Move 'open_flags' from tools/perf to evsel::open_flags Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:27 ` nakamura.shun
2022-03-25 4:38 ` [RFC PATCH v2 3/7] libperf: Add perf_evsel__{refresh, period}() functions Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:29 ` nakamura.shun
2022-03-25 4:38 ` [RFC PATCH v2 4/7] libperf: Introduce perf_{evsel, evlist}__open_opt with extensible struct opts Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:31 ` nakamura.shun
2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:34 ` nakamura.shun
2022-03-25 4:38 ` [RFC PATCH v2 5/7] libperf: Add perf_evsel__check_overflow() functions Shunsuke Nakamura
2022-03-30 13:50 ` Jiri Olsa
2022-04-11 8:35 ` nakamura.shun
2022-03-25 4:38 ` [RFC PATCH v2 6/7] libperf test: Add test_stat_overflow() Shunsuke Nakamura
2022-03-25 4:38 ` [RFC PATCH v2 7/7] libperf test: Add test_stat_overflow_event() Shunsuke Nakamura
2022-03-30 13:50 ` [RFC PATCH v2 0/7] libperf: Add interface for overflow check of sampling events Jiri Olsa
2022-04-11 8:23 ` nakamura.shun
2022-04-19 20:15 ` Jiri Olsa
2022-04-20 8:22 ` nakamura.shun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).