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 >