public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/1] Notifications for perf sideband events
@ 2017-06-06 14:49 Naveen N. Rao
  2017-06-06 15:16 ` [RFC PATCH 1/1] kernel/events: Introduce IOC_COUNT_RECORDS Naveen N. Rao
  0 siblings, 1 reply; 9+ messages in thread
From: Naveen N. Rao @ 2017-06-06 14:49 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: linux-kernel

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. This patch provides for a way to achieve this.

As noted, this is a RFC and I am not too specific about the interface or
the ioctl name. Kindly suggest if you think there is a better way to
achieve this.

- 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"));

	if (ioctl(info->si_fd, PERF_EVENT_IOC_REFRESH, 2) == -1)
	    perror("SIGIO: IOC_REFRESH");
    }

    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;

	fd = perf_event_open(&pe, 0, -1, -1, 0);
	if (fd == -1) {
	    fprintf(stderr, "Error opening leader %lx\n", 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_COUNT_RECORDS, 0) == -1)
	    return -5;

	if (ioctl(fd, PERF_EVENT_IOC_REFRESH, 2) == -1)
	    return -6;

	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_HUP
    Sleep 2
    Caught POLL_HUP
    Sleep 3
    Caught POLL_HUP

    real	0m3.060s
    user	0m0.001s
    sys	0m0.005s


Naveen N. Rao (1):
  kernel/events: Introduce IOC_COUNT_RECORDS

 include/linux/perf_event.h      |  1 +
 include/uapi/linux/perf_event.h |  1 +
 kernel/events/core.c            | 16 +++++++++++++++-
 kernel/events/ring_buffer.c     |  9 +++++++++
 4 files changed, 26 insertions(+), 1 deletion(-)

-- 
2.12.2

^ permalink raw reply	[flat|nested] 9+ messages in thread
* [RFC PATCH 1/1] kernel/events: Introduce IOC_COUNT_RECORDS
@ 2017-06-06 14:51 Naveen N. Rao
  2017-06-06 16:25 ` Peter Zijlstra
  0 siblings, 1 reply; 9+ messages in thread
From: Naveen N. Rao @ 2017-06-06 14:51 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: linux-kernel

Many perf sideband events (context switches, namespaces, ...) are useful
by themselves without the need for subscribing to any overflow events.
However, it is not possible to subscribe for notifications when such
records are logged into the ring buffer. Introduce IOC_COUNT_RECORDS as
a way to request this.

With IOC_COUNT_RECORDS set, IOC_REFRESH takes the number of records
after which to generate a notification, rather than the number of
overflow events.

Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
 include/linux/perf_event.h      |  1 +
 include/uapi/linux/perf_event.h |  1 +
 kernel/events/core.c            | 16 +++++++++++++++-
 kernel/events/ring_buffer.c     |  9 +++++++++
 4 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 24a635887f28..016f2da2bba7 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -683,6 +683,7 @@ struct perf_event {
 	struct irq_work			pending;
 
 	atomic_t			event_limit;
+	bool				count_records;
 
 	/* address range filters */
 	struct perf_addr_filters_head	addr_filters;
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index b1c0b187acfe..fb989ac71ded 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -408,6 +408,7 @@ struct perf_event_attr {
 #define PERF_EVENT_IOC_ID		_IOR('$', 7, __u64 *)
 #define PERF_EVENT_IOC_SET_BPF		_IOW('$', 8, __u32)
 #define PERF_EVENT_IOC_PAUSE_OUTPUT	_IOW('$', 9, __u32)
+#define PERF_EVENT_IOC_COUNT_RECORDS	_IO ('$', 10)
 
 enum perf_event_ioc_flags {
 	PERF_IOC_FLAG_GROUP		= 1U << 0,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6e75a5c9412d..637064880b36 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2674,6 +2674,16 @@ void perf_event_addr_filters_sync(struct perf_event *event)
 }
 EXPORT_SYMBOL_GPL(perf_event_addr_filters_sync);
 
+static int _perf_event_count_records(struct perf_event *event)
+{
+	if (event->attr.inherit || !is_sampling_event(event))
+		return -EINVAL;
+
+	event->count_records = 1;
+
+	return 0;
+}
+
 static int _perf_event_refresh(struct perf_event *event, int refresh)
 {
 	/*
@@ -4699,6 +4709,9 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
 		func = _perf_event_reset;
 		break;
 
+	case PERF_EVENT_IOC_COUNT_RECORDS:
+		return _perf_event_count_records(event);
+
 	case PERF_EVENT_IOC_REFRESH:
 		return _perf_event_refresh(event, arg);
 
@@ -7342,7 +7355,8 @@ static int __perf_event_overflow(struct perf_event *event,
 	 */
 
 	event->pending_kill = POLL_IN;
-	if (events && atomic_dec_and_test(&event->event_limit)) {
+	if (events && !event->count_records &&
+			atomic_dec_and_test(&event->event_limit)) {
 		ret = 1;
 		event->pending_kill = POLL_HUP;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 2831480c63a2..9b9ca0608fed 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -126,6 +126,7 @@ __perf_output_begin(struct perf_output_handle *handle,
 		u64			 id;
 		u64			 lost;
 	} lost_event;
+	int events = atomic_read(&event->event_limit);
 
 	rcu_read_lock();
 	/*
@@ -197,6 +198,14 @@ __perf_output_begin(struct perf_output_handle *handle,
 	if (unlikely(head - local_read(&rb->wakeup) > rb->watermark))
 		local_add(rb->watermark, &rb->wakeup);
 
+	if (events && event->count_records &&
+			atomic_dec_and_test(&event->event_limit)) {
+		event->pending_kill = POLL_HUP;
+		local_inc(&rb->wakeup);
+
+		perf_event_disable_inatomic(event);
+	}
+
 	page_shift = PAGE_SHIFT + page_order(rb);
 
 	handle->page = (offset >> page_shift) & (rb->nr_pages - 1);
-- 
2.12.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-06-06 17:33 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-06 14:49 [RFC PATCH 0/1] Notifications for perf sideband events Naveen N. Rao
2017-06-06 15:16 ` [RFC PATCH 1/1] kernel/events: Introduce IOC_COUNT_RECORDS Naveen N. Rao
2017-06-06 15:51   ` Arnaldo Carvalho de Melo
2017-06-06 16:56     ` Naveen N. Rao
2017-06-06 16:17   ` Peter Zijlstra
2017-06-06 17:12     ` Naveen N. Rao
  -- strict thread matches above, loose matches on Subject: below --
2017-06-06 14:51 Naveen N. Rao
2017-06-06 16:25 ` Peter Zijlstra
2017-06-06 17:32   ` Naveen N. Rao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox