lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220225103114.144239-5-nakamura.shun@fujitsu.com>
Date:   Fri, 25 Feb 2022 19:31:11 +0900
From:   Shunsuke <nakamura.shun@...itsu.com>
To:     peterz@...radead.org, mingo@...hat.com, acme@...nel.org,
        mark.rutland@....com, alexander.shishkin@...ux.intel.com,
        jolsa@...hat.com, namhyung@...nel.org
Cc:     linux-kernel@...r.kernel.org, linux-perf-users@...r.kernel.org,
        Shunsuke Nakamura <nakamura.shun@...itsu.com>
Subject: [RFC PATCH 4/7] libperf: Add perf_evsel__set_signal() functions

From: Shunsuke Nakamura <nakamura.shun@...itsu.com>

Add the following functions:

  perf_evsel__set_signal()
  perf_evsel__set_signal_cpu()

to set the parameters to get the overflow signal.

Signed-off-by: Shunsuke Nakamura <nakamura.shun@...itsu.com>
---
 tools/lib/perf/Documentation/libperf.txt |   4 +
 tools/lib/perf/evsel.c                   | 105 +++++++++++++++++++++++
 tools/lib/perf/include/perf/evsel.h      |   6 ++
 tools/lib/perf/libperf.map               |   2 +
 4 files changed, 117 insertions(+)

diff --git a/tools/lib/perf/Documentation/libperf.txt b/tools/lib/perf/Documentation/libperf.txt
index 8f523293fb9d..d0aa57c6ca97 100644
--- a/tools/lib/perf/Documentation/libperf.txt
+++ b/tools/lib/perf/Documentation/libperf.txt
@@ -151,6 +151,10 @@ 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__set_signal(struct perf_evsel *evsel, int owner_type, unsigned int signal,
+                             struct sigaction *sig);
+  int perf_evsel__set_signal_cpu(struct perf_evsel *evsel, int owner_type, unsigned int signal,
+                                 struct sigaction *sig, 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 8348545874e4..991ab04112b1 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,6 +19,9 @@
 #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>
 
@@ -351,6 +357,28 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
 	return 0;
 }
 
+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;
+}
+
 int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx)
 {
 	return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0, cpu_map_idx);
@@ -437,6 +465,83 @@ int perf_evsel__period(struct perf_evsel *evsel, __u64 period)
 	return err;
 }
 
+int perf_evsel__set_signal_cpu(struct perf_evsel *evsel, int owner_type, unsigned int signal,
+			       struct sigaction *sig, int cpu_map_idx)
+{
+	int err = 0;
+	struct f_owner_ex owner;
+
+	switch (owner_type) {
+	case F_OWNER_PID:
+		owner.pid = getpid();
+		break;
+	case F_OWNER_TID:
+		owner.pid = syscall(SYS_gettid);
+		break;
+	default:
+		return -1;
+	}
+
+	err = perf_evsel__run_fcntl(evsel, F_SETFL, (O_RDWR | O_NONBLOCK | O_ASYNC), 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;
+
+	err = sigaction(signal, sig, NULL);
+	if (err)
+		return err;
+
+	return err;
+}
+
+int perf_evsel__set_signal(struct perf_evsel *evsel, int owner_type, unsigned int signal,
+			   struct sigaction *sig)
+{
+	int i;
+	int err = 0;
+	struct f_owner_ex owner;
+
+	switch (owner_type) {
+	case F_OWNER_PID:
+		owner.pid = getpid();
+		break;
+	case F_OWNER_TID:
+		owner.pid = syscall(SYS_gettid);
+		break;
+	default:
+		return -1;
+	}
+
+	owner.type = owner_type;
+
+	for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++) {
+		err = perf_evsel__run_fcntl(evsel, F_SETFL, (O_RDWR | O_NONBLOCK | O_ASYNC), i);
+		if (err)
+			return err;
+
+		err = perf_evsel__run_fcntl(evsel, F_SETSIG, signal, i);
+		if (err)
+			return err;
+
+		err = perf_evsel__run_fcntl(evsel, F_SETOWN_EX, (unsigned long)&owner, i);
+		if (err)
+			return err;
+	}
+
+	err = sigaction(signal, sig, NULL);
+	if (err)
+		return err;
+
+	return err;
+}
+
 int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
 {
 	int err = 0, i;
diff --git a/tools/lib/perf/include/perf/evsel.h b/tools/lib/perf/include/perf/evsel.h
index 9ec24a5f5f9f..15768fc91910 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;
@@ -43,6 +44,11 @@ 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 int perf_evsel__set_signal(struct perf_evsel *evsel, int owner_type,
+				       unsigned int signal, struct sigaction *sig);
+LIBPERF_API int perf_evsel__set_signal_cpu(struct perf_evsel *evsel, int owner_type,
+					   unsigned int signal, struct sigaction *sig,
+					   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 83ecbce9cfbb..5e04fe2b611c 100644
--- a/tools/lib/perf/libperf.map
+++ b/tools/lib/perf/libperf.map
@@ -32,6 +32,8 @@ LIBPERF_0.0.1 {
 		perf_evsel__refresh_cpu;
 		perf_evsel__period;
 		perf_evsel__period_cpu;
+		perf_evsel__set_signal;
+		perf_evsel__set_signal_cpu;
 		perf_evsel__cpus;
 		perf_evsel__threads;
 		perf_evsel__attr;
-- 
2.31.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ