Re: [PATCH RFC 3/4] perf/core: Add support for SIGTRAP on perf events

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Feb 23, 2021 at 3:34 PM Marco Elver <elver@xxxxxxxxxx> wrote:

Adds bit perf_event_attr::sigtrap, which can be set to cause events to
send SIGTRAP (with si_code TRAP_PERF) to the task where the event
occurred. To distinguish perf events and allow user space to decode
si_perf (if set), the event type is set in si_errno.

The primary motivation is to support synchronous signals on perf events
in the task where an event (such as breakpoints) triggered.

Link: https://lore.kernel.org/lkml/YBv3rAT566k+6zjg@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/
Suggested-by: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Signed-off-by: Marco Elver <elver@xxxxxxxxxx>
---
 include/uapi/linux/perf_event.h |  3 ++-
 kernel/events/core.c            | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index ad15e40d7f5d..b9cc6829a40c 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -389,7 +389,8 @@ struct perf_event_attr {
                                cgroup         :  1, /* include cgroup events */
                                text_poke      :  1, /* include text poke events */
                                build_id       :  1, /* use build id in mmap2 events */
-                               __reserved_1   : 29;
+                               sigtrap        :  1, /* send synchronous SIGTRAP on event */
+                               __reserved_1   : 28;

        union {
                __u32           wakeup_events;    /* wakeup every n events */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 37a8297be164..8718763045fd 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6288,6 +6288,17 @@ void perf_event_wakeup(struct perf_event *event)
        }
 }

+static void perf_sigtrap(struct perf_event *event)
+{
+       struct kernel_siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = SIGTRAP;
+       info.si_code = TRAP_PERF;
+       info.si_errno = event->attr.type;
+       force_sig_info(&info);
+}
+
 static void perf_pending_event_disable(struct perf_event *event)
 {
        int cpu = READ_ONCE(event->pending_disable);
@@ -6297,6 +6308,13 @@ static void perf_pending_event_disable(struct perf_event *event)

        if (cpu == smp_processor_id()) {
                WRITE_ONCE(event->pending_disable, -1);
+
+               if (event->attr.sigtrap) {
+                       atomic_inc(&event->event_limit); /* rearm event */

Can/should this be atomic_set(&event->event_limit, 1)? It should only
go between 1 and 0, right?
Otherwise:

Acked-by: Dmitry Vyukov <dvyukov@xxxxxxxxxx>


+                       perf_sigtrap(event);
+                       return;
+               }
+
                perf_event_disable_local(event);
                return;
        }
@@ -11325,6 +11343,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,

        event->state            = PERF_EVENT_STATE_INACTIVE;

+       if (event->attr.sigtrap)
+               atomic_set(&event->event_limit, 1);
+
        if (task) {
                event->attach_state = PERF_ATTACH_TASK;
                /*
--
2.30.0.617.g56c4b15f3c-goog




[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux