Re: [PATCH 0/2] Notifications for perf sideband events

From: Naveen N. Rao
Date: Tue Jun 27 2017 - 05:05:09 EST


On 2017/06/19 08:01PM, Naveen N. Rao wrote:
> Currently, there is no way to ask for signals to be delivered when a
> certain number of sideband events have been logged into the ring buffer.
> This is problematic if we are only interested in, say, context switch
> events. Furthermore, signals are more useful (rather than polling) for
> self-profiling. This series provides for a way to achieve this.
>
> We ride on top of the existing support for ring buffer wakeup to
> generate signals as desired. Counting sideband events still requires
> some changes in the output path, but in normal cases, it ends up being
> just a comparison.
>
> for
> context switch events and how it can control notification through
> signals. The key changes include the below perf_event_attr settings as
> well as use of IOC_ENABLE:
> pe.signal_on_wakeup = 1;
> pe.count_sb_events = 1;
> pe.wakeup_events = 2;
>
> To keep things simple, PERF_EVENT_IOC_REFRESH cannot be used if any of
> the new attributes are set.
>
> RFC v2:
> https://www.mail-archive.com/linux-kernel@xxxxxxxxxxxxxxx/msg1420363.html
> Changes:
> - Send HUP on perf_event_exit_event() (suggested by Jiri)
> - Disable use of IOC_REFRESH if signal_on_wakeup/count_sb_events is
> set.

Peter, Arnaldo, Jiri,
Can you please take a look at this patchset?

Thanks,
Naveen

>
>
> - Naveen
>
> ---
> Here is a sample program demonstrating the same:
>
> #define _GNU_SOURCE
>
> #include <stdlib.h>
> #include <stdio.h>
> #include <unistd.h>
> #include <fcntl.h>
> #include <string.h>
> #include <signal.h>
> #include <sys/ioctl.h>
> #include <sys/mman.h>
> #include <linux/perf_event.h>
> #include <asm/unistd.h>
>
> static long
> perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
> int cpu, int group_fd, unsigned long flags)
> {
> return syscall(__NR_perf_event_open, hw_event, pid, cpu,
> group_fd, flags);
> }
>
> static void sigio_handler(int n, siginfo_t *info, void *uc)
> {
> fprintf (stderr, "Caught %s\n", info->si_code == POLL_HUP ? "POLL_HUP" :
> (info->si_code == POLL_IN ? "POLL_IN" : "other signal"));
> }
>
> int main(int argc, char **argv)
> {
> struct perf_event_attr pe;
> struct sigaction act;
> int fd;
> void *buf;
>
> memset(&act, 0, sizeof(act));
> act.sa_sigaction = sigio_handler;
> act.sa_flags = SA_SIGINFO;
> sigaction(SIGIO, &act, 0);
>
> memset(&pe, 0, sizeof(struct perf_event_attr));
> pe.size = sizeof(struct perf_event_attr);
> pe.type = PERF_TYPE_SOFTWARE;
> pe.config = PERF_COUNT_SW_DUMMY;
> pe.disabled = 1;
> pe.sample_period = 1;
> pe.context_switch = 1;
> pe.signal_on_wakeup = 1;
> pe.count_sb_events = 1;
> pe.wakeup_events = 2;
>
> fd = perf_event_open(&pe, 0, -1, -1, 0);
> if (fd == -1) {
> fprintf(stderr, "Error opening leader %lx\n", (unsigned long)pe.config);
> exit(EXIT_FAILURE);
> }
>
> buf = mmap(NULL, sysconf(_SC_PAGESIZE) * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
> if (buf == MAP_FAILED) {
> fprintf(stderr, "Can't mmap buffer\n");
> return -1;
> }
>
> if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_ASYNC) == -1)
> return -2;
>
> if (fcntl(fd, F_SETSIG, SIGIO) == -1)
> return -3;
>
> if (fcntl(fd, F_SETOWN, getpid()) == -1)
> return -4;
>
> if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) == -1)
> return -5;
>
> fprintf (stderr, "Sleep 1\n");
> sleep(1);
> fprintf (stderr, "Sleep 2\n");
> sleep(1);
> fprintf (stderr, "Sleep 3\n");
> sleep(1);
>
> /* Disable the event counter */
> ioctl(fd, PERF_EVENT_IOC_DISABLE, 1);
>
> close(fd);
>
> return 0;
> }
>
>
> A sample output:
> $ time ./cs
> Sleep 1
> Caught POLL_IN
> Sleep 2
> Caught POLL_IN
> Sleep 3
> Caught POLL_IN
>
> real 0m3.040s
> user 0m0.001s
> sys 0m0.003s
>
>
> Naveen N. Rao (2):
> kernel/events: Add option to notify through signals on wakeup
> kernel/events: Add option to enable counting sideband events in
> wakeup_events
>
> include/uapi/linux/perf_event.h | 4 +++-
> kernel/events/core.c | 20 ++++++++++++--------
> kernel/events/ring_buffer.c | 16 ++++++++++++++++
> 3 files changed, 31 insertions(+), 9 deletions(-)
>
> --
> 2.13.1
>