* [PATCH v2 1/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT
2024-08-08 0:02 [PATCH v2 0/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
@ 2024-08-08 0:02 ` Charlie Jenkins
2024-08-08 0:02 ` [PATCH v2 2/3] perf: Document PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Charlie Jenkins @ 2024-08-08 0:02 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Atish Patra
Cc: linux-perf-users, linux-kernel, Charlie Jenkins
PERF_EVENT_IOC_REFRESH immediately enables after incrementing
event_limit. Provide a new ioctl flag that allows programs to increment
event_limit without enabling the event. A usecase for this is to set an
event_limit in combination with enable_on_exec.
Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
---
include/linux/perf_event.h | 4 ++--
include/uapi/linux/perf_event.h | 1 +
kernel/events/core.c | 17 +++++++++++------
tools/include/uapi/linux/perf_event.h | 1 +
4 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index a5304ae8c654..40025a5eb98a 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1103,7 +1103,7 @@ extern int perf_event_task_enable(void);
extern void perf_pmu_resched(struct pmu *pmu);
-extern int perf_event_refresh(struct perf_event *event, int refresh);
+extern int perf_event_refresh(struct perf_event *event, int refresh, bool enable);
extern void perf_event_update_userpage(struct perf_event *event);
extern int perf_event_release_kernel(struct perf_event *event);
extern struct perf_event *
@@ -1770,7 +1770,7 @@ static inline int perf_event_read_local(struct perf_event *event, u64 *value,
static inline void perf_event_print_debug(void) { }
static inline int perf_event_task_disable(void) { return -EINVAL; }
static inline int perf_event_task_enable(void) { return -EINVAL; }
-static inline int perf_event_refresh(struct perf_event *event, int refresh)
+static inline int perf_event_refresh(struct perf_event *event, int refresh, bool enable)
{
return -EINVAL;
}
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 3a64499b0f5d..992f51effb27 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -560,6 +560,7 @@ struct perf_event_query_bpf {
#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *)
#define PERF_EVENT_IOC_MODIFY_ATTRIBUTES _IOW('$', 11, struct perf_event_attr *)
+#define PERF_EVENT_IOC_INC_EVENT_LIMIT _IO ('$', 12)
enum perf_event_ioc_flags {
PERF_IOC_FLAG_GROUP = 1U << 0,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8f908f077935..b9d009733ace 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3142,7 +3142,7 @@ void perf_event_addr_filters_sync(struct perf_event *event)
}
EXPORT_SYMBOL_GPL(perf_event_addr_filters_sync);
-static int _perf_event_refresh(struct perf_event *event, int refresh)
+static int _perf_event_refresh(struct perf_event *event, int refresh, bool enable)
{
/*
* not supported on inherited events
@@ -3151,7 +3151,8 @@ static int _perf_event_refresh(struct perf_event *event, int refresh)
return -EINVAL;
atomic_add(refresh, &event->event_limit);
- _perf_event_enable(event);
+ if (enable)
+ _perf_event_enable(event);
return 0;
}
@@ -3159,13 +3160,13 @@ static int _perf_event_refresh(struct perf_event *event, int refresh)
/*
* See perf_event_disable()
*/
-int perf_event_refresh(struct perf_event *event, int refresh)
+int perf_event_refresh(struct perf_event *event, int refresh, bool enable)
{
struct perf_event_context *ctx;
int ret;
ctx = perf_event_ctx_lock(event);
- ret = _perf_event_refresh(event, refresh);
+ ret = _perf_event_refresh(event, refresh, enable);
perf_event_ctx_unlock(event, ctx);
return ret;
@@ -5920,7 +5921,7 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
break;
case PERF_EVENT_IOC_REFRESH:
- return _perf_event_refresh(event, arg);
+ return _perf_event_refresh(event, arg, true);
case PERF_EVENT_IOC_PERIOD:
{
@@ -6006,6 +6007,10 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
return perf_event_modify_attr(event, &new_attr);
}
+
+ case PERF_EVENT_IOC_INC_EVENT_LIMIT:
+ return _perf_event_refresh(event, arg, false);
+
default:
return -ENOTTY;
}
@@ -6721,7 +6726,7 @@ void perf_event_wakeup(struct perf_event *event)
ring_buffer_wakeup(event);
if (event->pending_kill) {
- kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill);
+ kill_fasync(perf_event_fasync(event), SIGTRAP, event->pending_kill);
event->pending_kill = 0;
}
}
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 3a64499b0f5d..992f51effb27 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -560,6 +560,7 @@ struct perf_event_query_bpf {
#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *)
#define PERF_EVENT_IOC_MODIFY_ATTRIBUTES _IOW('$', 11, struct perf_event_attr *)
+#define PERF_EVENT_IOC_INC_EVENT_LIMIT _IO ('$', 12)
enum perf_event_ioc_flags {
PERF_IOC_FLAG_GROUP = 1U << 0,
--
2.45.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v2 2/3] perf: Document PERF_EVENT_IOC_INC_EVENT_LIMIT
2024-08-08 0:02 [PATCH v2 0/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
2024-08-08 0:02 ` [PATCH v2 1/3] " Charlie Jenkins
@ 2024-08-08 0:02 ` Charlie Jenkins
2024-08-08 0:02 ` [PATCH v2 3/3] libperf: Add perf_evsel__refresh() function Charlie Jenkins
2024-08-23 3:40 ` [PATCH v2 0/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
3 siblings, 0 replies; 5+ messages in thread
From: Charlie Jenkins @ 2024-08-08 0:02 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Atish Patra
Cc: linux-perf-users, linux-kernel, Charlie Jenkins
Introduce PERF_EVENT_IOC_INC_EVENT_LIMIT and explain the differences
between it and PERF_EVENT_IOC_REFRESH.
Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
---
tools/perf/design.txt | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/perf/design.txt b/tools/perf/design.txt
index aa8cfeabb743..1626ae83785a 100644
--- a/tools/perf/design.txt
+++ b/tools/perf/design.txt
@@ -439,6 +439,11 @@ Additionally, non-inherited overflow counters can use
to enable a counter for 'nr' events, after which it gets disabled again.
+PERF_EVENT_IOC_REFRESH will increment the event limit by 'nr' and enable the
+event. To increment the event limit without enabling it, use the following:
+
+ ioctl(fd, PERF_EVENT_IOC_INC_EVENT_LIMIT, nr);
+
A process can enable or disable all the counter groups that are
attached to it, using prctl:
--
2.45.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] libperf: Add perf_evsel__refresh() function
2024-08-08 0:02 [PATCH v2 0/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
2024-08-08 0:02 ` [PATCH v2 1/3] " Charlie Jenkins
2024-08-08 0:02 ` [PATCH v2 2/3] perf: Document PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
@ 2024-08-08 0:02 ` Charlie Jenkins
2024-08-23 3:40 ` [PATCH v2 0/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
3 siblings, 0 replies; 5+ messages in thread
From: Charlie Jenkins @ 2024-08-08 0:02 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Atish Patra
Cc: linux-perf-users, linux-kernel, Charlie Jenkins,
Shunsuke Nakamura
Introduce perf_evsel__refresh() to increment the overflow limit. Can
optionally enable the event immediately.
Co-developed-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
Signed-off-by: Shunsuke Nakamura <nakamura.shun@fujitsu.com>
Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
---
tools/lib/perf/Documentation/libperf.txt | 2 ++
tools/lib/perf/evsel.c | 49 ++++++++++++++++++++++++++------
tools/lib/perf/include/perf/evsel.h | 2 ++
tools/lib/perf/libperf.map | 2 ++
4 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index fcfb9499ef9c..a6c3bab5c995 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -147,6 +147,8 @@ 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, bool enable);
+ 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 c07160953224..2b7ca7fa4998 100644
--- a/tools/lib/perf/evsel.c
+++ b/tools/lib/perf/evsel.c
@@ -18,6 +18,7 @@
#include <sys/ioctl.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)
@@ -412,7 +413,7 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread,
return 0;
}
-static int perf_evsel__ioctl(struct perf_evsel *evsel, int ioc, void *arg,
+static int perf_evsel__ioctl(struct perf_evsel *evsel, int ioc, unsigned long arg,
int cpu_map_idx, int thread)
{
int *fd = FD(evsel, cpu_map_idx, thread);
@@ -424,7 +425,7 @@ static int perf_evsel__ioctl(struct perf_evsel *evsel, int ioc, void *arg,
}
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;
@@ -441,7 +442,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_thread(struct perf_evsel *evsel, int thread)
@@ -451,7 +452,7 @@ int perf_evsel__enable_thread(struct perf_evsel *evsel, int thread)
int err;
perf_cpu_map__for_each_cpu(cpu, idx, evsel->cpus) {
- err = perf_evsel__ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, idx, thread);
+ err = perf_evsel__ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0, idx, thread);
if (err)
return err;
}
@@ -465,13 +466,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)
@@ -480,7 +481,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, bool enable)
+{
+ int i, ioc;
+ int err = 0;
+
+ ioc = enable ? PERF_EVENT_IOC_REFRESH : PERF_EVENT_IOC_INC_EVENT_LIMIT;
+
+ for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+ err = perf_evsel__run_ioctl(evsel, ioc, 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);
+
+ 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;
}
@@ -491,7 +524,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 6f92204075c2..e562dd9f39e0 100644
--- a/tools/lib/perf/include/perf/evsel.h
+++ b/tools/lib/perf/include/perf/evsel.h
@@ -40,6 +40,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__enable_thread(struct perf_evsel *evsel, int thread);
LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__refresh(struct perf_evsel *evsel, int refresh, bool enable);
+LIBPERF_API int perf_evsel__period(struct perf_evsel *evsel, __u64 period);
LIBPERF_API int perf_evsel__disable_cpu(struct perf_evsel *evsel, 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);
diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map
index 2aa79b696032..bb7a48befdd5 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -34,6 +34,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.45.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH v2 0/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT
2024-08-08 0:02 [PATCH v2 0/3] perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT Charlie Jenkins
` (2 preceding siblings ...)
2024-08-08 0:02 ` [PATCH v2 3/3] libperf: Add perf_evsel__refresh() function Charlie Jenkins
@ 2024-08-23 3:40 ` Charlie Jenkins
3 siblings, 0 replies; 5+ messages in thread
From: Charlie Jenkins @ 2024-08-23 3:40 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Atish Patra
Cc: linux-perf-users, linux-kernel, Shunsuke Nakamura
On Wed, Aug 07, 2024 at 05:02:39PM -0700, Charlie Jenkins wrote:
> Introduce a new perf ioctl key PERF_EVENT_IOC_INC_EVENT_LIMIT that
> functions the same as PERF_EVENT_IOC_REFRESH, except it does not
> immediately enable counters.
>
> Also create a libperf API perf_evsel__refresh() to allow libperf users
> access to this ioctl key.
>
> Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
> ---
> Changes in v2:
> - Drop discussion about signal race condition
> - Add new patch "libperf: Add perf_evsel__refresh() function"
> - This newly added patch was pulled from a different series with
> modifications to fit the new ioctl key
> -
> https://lore.kernel.org/lkml/20240726-overflow_check_libperf-v2-0-7d154dcf6bea@rivosinc.com/
> will be updated
> - Link to v1: https://lore.kernel.org/r/20240724-perf_set_event_limit-v1-0-e680c93eca55@rivosinc.com
>
> ---
> Charlie Jenkins (3):
> perf: Add PERF_EVENT_IOC_INC_EVENT_LIMIT
> perf: Document PERF_EVENT_IOC_INC_EVENT_LIMIT
> libperf: Add perf_evsel__refresh() function
>
> include/linux/perf_event.h | 4 +--
> include/uapi/linux/perf_event.h | 1 +
> kernel/events/core.c | 17 +++++++----
> tools/include/uapi/linux/perf_event.h | 1 +
> tools/lib/perf/Documentation/libperf.txt | 2 ++
> tools/lib/perf/evsel.c | 49 ++++++++++++++++++++++++++------
> tools/lib/perf/include/perf/evsel.h | 2 ++
> tools/lib/perf/libperf.map | 2 ++
> tools/perf/design.txt | 5 ++++
> 9 files changed, 67 insertions(+), 16 deletions(-)
> ---
> base-commit: 0c3836482481200ead7b416ca80c68a29cfdaabd
> change-id: 20240724-perf_set_event_limit-079f1b996376
> --
> - Charlie
>
I am interested in people's opinion of this. Let me know if there are
any concerns.
- Charlie
^ permalink raw reply [flat|nested] 5+ messages in thread