linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 00/10] perf pollfd series
@ 2014-08-22 20:59 Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 01/10] perf evlist: Introduce perf_evlist__filter_pollfd method Arnaldo Carvalho de Melo
                   ` (10 more replies)
  0 siblings, 11 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Borislav Petkov, Corey Ashford, David Ahern, Don Zickus,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Mike Galbraith,
	Namhyung Kim, Paul Mackerras, Peter Zijlstra, Stephane Eranian

Hi,

	This is an alternative series to the one Jiri Olsa posted to use the
fixes he made to the kernel side to allow tooling to notice that a thread had
exited by looking at the pollfd.revents looking for POLLHUP notifications.

	Once all event file descriptors are removed from the evlist pollfd array,
tools can make a decision about exiting or telling the user about what happened,
asking to guidance on what to do next.

	The main difference in this approach is that a new class, which Jiri
called 'poller' and I called 'fdarray', grew up from what was in evlist->pollfd
and associated operations, while Jiri first introduced a new class and then
made tooling use it.

	The details of the implementation should be clear on the changelog
comments, please let me know if you see any problems, and if I can have your
acked-by/tested-by/whatever-else tags to get this moving forward.

	Ah, there is still one missing thing which is to make the hists browser
in live mode be notified that all monitored events are POLLHUP'ed, will get
to that in followup patches.

	The kernel bits were sent together with my latest pull req to Ingo,
this series is on top of that branch and is available at:

 git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git perf/pollfd

- Arnaldo

Arnaldo Carvalho de Melo (10):
  perf evlist: Introduce perf_evlist__filter_pollfd method
  perf tests: Add test for perf_evlist__filter_pollfd()
  perf evlist: Monitor POLLERR and POLLHUP events too
  perf record: Filter out POLLHUP'ed file descriptors
  perf trace: Filter out POLLHUP'ed file descriptors
  perf evlist: Allow growing pollfd on add method
  perf tests: Add pollfd growing test
  perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent
  perf evlist: Introduce poll method for common code idiom
  tools lib api: Adopt fdarray class from perf's evlist

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

* [PATCH 01/10] perf evlist: Introduce perf_evlist__filter_pollfd method
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-25  6:57   ` Adrian Hunter
  2014-08-22 20:59 ` [PATCH 02/10] perf tests: Add test for perf_evlist__filter_pollfd() Arnaldo Carvalho de Melo
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	David Ahern, Don Zickus, Frederic Weisbecker, Ingo Molnar,
	Mike Galbraith, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian

From: Arnaldo Carvalho de Melo <acme@redhat.com>

To remove all entries in evlist->pollfd[] that have revents matching at
least one of the bits in the specified mask.

It'll adjust evlist->nr_fds to the number of unfiltered fds and will
return this value, as a convenience and to avoid requiring direct access
to internal state of perf_evlist objects.

This will be used after polling the evlist fds so that we remove fds
that were closed by the kernel.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ki3oqbfjg84si3f9amhyqvzb@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c | 16 ++++++++++++++++
 tools/perf/util/evlist.h |  2 ++
 2 files changed, 18 insertions(+)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a3e28b49128a..bd7896073d10 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -428,6 +428,22 @@ void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
 	evlist->nr_fds++;
 }
 
+int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
+{
+	int fd = 0, nr_fds = 0;
+
+	while (fd < evlist->nr_fds) {
+		if ((evlist->pollfd[fd].revents & revents_and_mask) == 0)
+			++nr_fds;
+
+		if (++fd != nr_fds)
+			evlist->pollfd[nr_fds] = evlist->pollfd[fd];
+	}
+
+	evlist->nr_fds = nr_fds;
+	return nr_fds;
+}
+
 static void perf_evlist__id_hash(struct perf_evlist *evlist,
 				 struct perf_evsel *evsel,
 				 int cpu, int thread, u64 id)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 106de53a6a74..1082420951f9 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -84,6 +84,8 @@ void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 
 void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
 
+int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
+
 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
 
 struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
-- 
1.9.3


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

* [PATCH 02/10] perf tests: Add test for perf_evlist__filter_pollfd()
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 01/10] perf evlist: Introduce perf_evlist__filter_pollfd method Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 03/10] perf evlist: Monitor POLLERR and POLLHUP events too Arnaldo Carvalho de Melo
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	David Ahern, Don Zickus, Frederic Weisbecker, Ingo Molnar,
	Mike Galbraith, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian

From: Arnaldo Carvalho de Melo <acme@redhat.com>

That will use a synthetic evlist with just what is touched by this new
method to check that it works as expected.

Output in verbose mode:

  $ perf test -v pollfd
  33: Filter fds with revents mask in a pollfd array         :
  --- start ---
  filtering all but pollfd[2]:
  before:   5 [ 5, 4, 3, 2, 1 ]
   after:   1 [ 3 ]
  filtering all but (pollfd[0], pollfd[3]):
  before:   5 [ 5, 4, 3, 2, 1 ]
   after:   2 [ 5, 2 ]
  test child finished with 0
  ---- end ----
  Filter fds with revents mask in a pollfd array: Ok
  $

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-x7c8liszdvc3ocmanf2cet8p@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Makefile.perf        |   1 +
 tools/perf/tests/builtin-test.c |   4 ++
 tools/perf/tests/evlist.c       | 103 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |   1 +
 4 files changed, 109 insertions(+)
 create mode 100644 tools/perf/tests/evlist.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 95e832b1bc3c..9ce194fc00a0 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -399,6 +399,7 @@ LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
 LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
 LIB_OBJS += $(OUTPUT)tests/perf-record.o
 LIB_OBJS += $(OUTPUT)tests/rdpmc.o
+LIB_OBJS += $(OUTPUT)tests/evlist.o
 LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
 LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
 LIB_OBJS += $(OUTPUT)tests/pmu.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6a4145e5ad2c..41e556edbe02 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -158,6 +158,10 @@ static struct test {
 		.func = test__switch_tracking,
 	},
 	{
+		.desc = "Filter fds with revents mask in a pollfd array",
+		.func = test__perf_evlist__filter_pollfd,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/evlist.c b/tools/perf/tests/evlist.c
new file mode 100644
index 000000000000..77579158f4d9
--- /dev/null
+++ b/tools/perf/tests/evlist.c
@@ -0,0 +1,103 @@
+#include "util/evlist.h"
+#include "util/debug.h"
+#include "tests/tests.h"
+
+static void perf_evlist__init_pollfd(struct perf_evlist *evlist,
+				     int nr_fds_alloc, short revents)
+{
+	int fd;
+
+	evlist->nr_fds = nr_fds_alloc;
+
+	for (fd = 0; fd < nr_fds_alloc; ++fd) {
+		evlist->pollfd[fd].fd	   = nr_fds_alloc - fd;
+		evlist->pollfd[fd].revents = revents;
+	}
+}
+
+static int perf_evlist__fprintf_pollfd(struct perf_evlist *evlist,
+				       const char *prefix, FILE *fp)
+{
+	int printed = 0, fd;
+
+	if (!verbose)
+		return 0;
+
+	printed += fprintf(fp, "\n%s: %3d [ ", prefix, evlist->nr_fds);
+	for (fd = 0; fd < evlist->nr_fds; ++fd)
+		printed += fprintf(fp, "%s%d", fd ? ", " : "", evlist->pollfd[fd].fd);
+	printed += fprintf(fp, " ]");
+	return printed;
+}
+
+int test__perf_evlist__filter_pollfd(void)
+{
+	const int nr_fds_alloc = 5;
+	int nr_fds, expected_fd[2], fd;
+	struct pollfd pollfd[nr_fds_alloc];
+	struct perf_evlist evlist_alloc = {
+		.pollfd	= pollfd,
+	}, *evlist = &evlist_alloc;
+
+	perf_evlist__init_pollfd(evlist, nr_fds_alloc, POLLIN);
+	nr_fds = perf_evlist__filter_pollfd(evlist, POLLHUP);
+	if (nr_fds != nr_fds_alloc) {
+		pr_debug("\nperf_evlist__filter_pollfd()=%d != %d shouldn't have filtered anything",
+			 nr_fds, nr_fds_alloc);
+		return TEST_FAIL;
+	}
+
+	perf_evlist__init_pollfd(evlist, nr_fds_alloc, POLLHUP);
+	nr_fds = perf_evlist__filter_pollfd(evlist, POLLHUP);
+	if (nr_fds != 0) {
+		pr_debug("\nperf_evlist__filter_pollfd()=%d != %d, should have filtered all fds",
+			 nr_fds, nr_fds_alloc);
+		return TEST_FAIL;
+	}
+
+	perf_evlist__init_pollfd(evlist, nr_fds_alloc, POLLHUP);
+	pollfd[2].revents = POLLIN;
+	expected_fd[0] = pollfd[2].fd;
+
+	pr_debug("\nfiltering all but pollfd[2]:");
+	perf_evlist__fprintf_pollfd(evlist, "before", stderr);
+	nr_fds = perf_evlist__filter_pollfd(evlist, POLLHUP);
+	perf_evlist__fprintf_pollfd(evlist, " after", stderr);
+	if (nr_fds != 1) {
+		pr_debug("\nperf_evlist__filter_pollfd()=%d != 1, should have left just one event",
+			 nr_fds);
+		return TEST_FAIL;
+	}
+
+	if (pollfd[0].fd != expected_fd[0]) {
+		pr_debug("\npollfd[0].fd=%d != %d\n", pollfd[0].fd, expected_fd[0]);
+		return TEST_FAIL;
+	}
+
+	perf_evlist__init_pollfd(evlist, nr_fds_alloc, POLLHUP);
+	pollfd[0].revents = POLLIN;
+	expected_fd[0] = pollfd[0].fd;
+	pollfd[3].revents = POLLIN;
+	expected_fd[1] = pollfd[3].fd;
+
+	pr_debug("\nfiltering all but (pollfd[0], pollfd[3]):");
+	perf_evlist__fprintf_pollfd(evlist, "before", stderr);
+	nr_fds = perf_evlist__filter_pollfd(evlist, POLLHUP);
+	perf_evlist__fprintf_pollfd(evlist, " after", stderr);
+	if (nr_fds != 2) {
+		pr_debug("\nperf_evlist__filter_pollfd()=%d != 2, should have left just two events",
+			 nr_fds);
+		return TEST_FAIL;
+	}
+
+	for (fd = 0; fd < 2; ++fd) {
+		if (pollfd[fd].fd != expected_fd[fd]) {
+			pr_debug("\npollfd[%d].fd=%d != %d\n", fd, pollfd[fd].fd, expected_fd[fd]);
+			return TEST_FAIL;
+		}
+	}
+
+	pr_debug("\n");
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index be8be10e3957..72c4c039bd80 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -49,6 +49,7 @@ int test__thread_mg_share(void);
 int test__hists_output(void);
 int test__hists_cumulate(void);
 int test__switch_tracking(void);
+int test__perf_evlist__filter_pollfd(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-- 
1.9.3


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

* [PATCH 03/10] perf evlist: Monitor POLLERR and POLLHUP events too
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 01/10] perf evlist: Introduce perf_evlist__filter_pollfd method Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 02/10] perf tests: Add test for perf_evlist__filter_pollfd() Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 04/10] perf record: Filter out POLLHUP'ed file descriptors Arnaldo Carvalho de Melo
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	David Ahern, Don Zickus, Frederic Weisbecker, Ingo Molnar,
	Mike Galbraith, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian

From: Arnaldo Carvalho de Melo <acme@redhat.com>

We want to know when the fd went away, like when a monitored thread
exits.

If we do not monitor such events, then the tools will wait forever on
events from a vanished thread, like when running:

 $ sleep 5s &
 $ perf record -p `pidof sleep`

This builds upon the kernel patch by Jiri Olsa that actually makes a
poll on those file descriptors to return POLLHUP.

It is also needed to change the tools to use
perf_evlist__filter_pollfd() to check if there are remainings fds to
monitor or if all are gone, in which case they will exit the
poll/mmap/read loop.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-a4fslwspov0bs69nj825hqpq@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index bd7896073d10..cddc700d718f 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -424,7 +424,7 @@ void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
 {
 	fcntl(fd, F_SETFL, O_NONBLOCK);
 	evlist->pollfd[evlist->nr_fds].fd = fd;
-	evlist->pollfd[evlist->nr_fds].events = POLLIN;
+	evlist->pollfd[evlist->nr_fds].events = POLLIN | POLLERR | POLLHUP;
 	evlist->nr_fds++;
 }
 
-- 
1.9.3


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

* [PATCH 04/10] perf record: Filter out POLLHUP'ed file descriptors
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (2 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 03/10] perf evlist: Monitor POLLERR and POLLHUP events too Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 05/10] perf trace: " Arnaldo Carvalho de Melo
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	David Ahern, Don Zickus, Frederic Weisbecker, Ingo Molnar,
	Mike Galbraith, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian

From: Arnaldo Carvalho de Melo <acme@redhat.com>

So that we don't continue polling on vanished file descriptors, i.e.
file descriptors for events monitoring threads that exited.

I.e. the following 'perf record' command now exits as expected, instead
of staying in an eternal loop:

  $ sleep 5s &
  $ perf record -p `pidof sleep`

Reported-by: Jiri Olsa <jolsa@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ftg46awsyfjc3axb0xm63oig@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 87e28a4e33ba..b87708ce09c9 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -467,6 +467,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 			if (err > 0 || (err < 0 && errno == EINTR))
 				err = 0;
 			waking++;
+
+			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
+				done = 1;
 		}
 
 		/*
-- 
1.9.3


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

* [PATCH 05/10] perf trace: Filter out POLLHUP'ed file descriptors
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (3 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 04/10] perf record: Filter out POLLHUP'ed file descriptors Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 06/10] perf evlist: Allow growing pollfd on add method Arnaldo Carvalho de Melo
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	David Ahern, Don Zickus, Frederic Weisbecker, Ingo Molnar,
	Mike Galbraith, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
	Stephane Eranian

From: Arnaldo Carvalho de Melo <acme@redhat.com>

So that we don't continue polling on vanished file descriptors, i.e.
file descriptors for events monitoring threads that exited.

I.e. the following 'trace' command now exits as expected, instead
of staying in an eternal loop:

      $ sleep 5s &
      $ trace -p `pidof sleep`

Reported-by: Jiri Olsa <jolsa@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-fhn2pyf8sqhoiwu42hxq9yq2@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-trace.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a9e96ff49c7f..09d4bc44215e 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2171,7 +2171,8 @@ next_event:
 	if (trace->nr_events == before) {
 		int timeout = done ? 100 : -1;
 
-		if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0)
+		if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0 &&
+		    perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) > 0)
 			goto again;
 	} else {
 		goto again;
-- 
1.9.3


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

* [PATCH 06/10] perf evlist: Allow growing pollfd on add method
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (4 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 05/10] perf trace: " Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-25  9:41   ` Jiri Olsa
  2014-08-25  9:47   ` Jiri Olsa
  2014-08-22 20:59 ` [PATCH 07/10] perf tests: Add pollfd growing test Arnaldo Carvalho de Melo
                   ` (4 subsequent siblings)
  10 siblings, 2 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Corey Ashford, David Ahern, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Jiri Olsa, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

From: Arnaldo Carvalho de Melo <acme@redhat.com>

This way we will be able to add more file descriptors to be polled,
like stdin or some timer fd.

At this point we might as well yank the pollfd class from evlist so that
it can be used in other places.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-8udu11ke3ev1yklprevldzyl@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evlist.c | 40 +++++++++++++++++++++++++++++++++++-----
 tools/perf/util/evlist.h |  5 +++--
 2 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index cddc700d718f..9fb00c980312 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -402,7 +402,21 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
 		return perf_evlist__enable_event_thread(evlist, evsel, idx);
 }
 
-static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
+static int perf_evlist__grow_pollfd(struct perf_evlist *evlist, int hint)
+{
+	int nr_fds_alloc = evlist->nr_fds_alloc + hint;
+	size_t size = sizeof(struct pollfd) * nr_fds_alloc;
+	struct pollfd *pollfd = realloc(evlist->pollfd, size);
+
+	if (pollfd == NULL)
+		return -ENOMEM;
+
+	evlist->nr_fds_alloc = nr_fds_alloc;
+	evlist->pollfd	     = pollfd;
+	return 0;
+}
+
+int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
 {
 	int nr_cpus = cpu_map__nr(evlist->cpus);
 	int nr_threads = thread_map__nr(evlist->threads);
@@ -416,16 +430,28 @@ static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
 			nfds += nr_cpus * nr_threads;
 	}
 
-	evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
-	return evlist->pollfd != NULL ? 0 : -ENOMEM;
+	if (evlist->nr_fds_alloc - evlist->nr_fds < nfds &&
+	    perf_evlist__grow_pollfd(evlist, nfds) < 0)
+		return -ENOMEM;
+
+	return 0;
 }
 
-void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
+int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
 {
+	/*
+	 * XXX: 64 is arbitrary, just not to call realloc at each fd.
+	 *	Find a better autogrowing heuristic
+	 */
+	if (evlist->nr_fds == evlist->nr_fds_alloc &&
+	    perf_evlist__grow_pollfd(evlist, 64) < 0)
+		return -ENOMEM;
+
 	fcntl(fd, F_SETFL, O_NONBLOCK);
 	evlist->pollfd[evlist->nr_fds].fd = fd;
 	evlist->pollfd[evlist->nr_fds].events = POLLIN | POLLERR | POLLHUP;
 	evlist->nr_fds++;
+	return 0;
 }
 
 int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
@@ -713,7 +739,11 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
 		return -1;
 	}
 
-	perf_evlist__add_pollfd(evlist, fd);
+	if (perf_evlist__add_pollfd(evlist, fd) < 0) {
+		__perf_evlist__munmap(evlist->mmap[idx].base, idx);
+		return -1;
+	}
+
 	return 0;
 }
 
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 1082420951f9..bbc2fd01b5c5 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -30,6 +30,7 @@ struct perf_evlist {
 	int		 nr_entries;
 	int		 nr_groups;
 	int		 nr_fds;
+	int		 nr_fds_alloc;
 	int		 nr_mmaps;
 	size_t		 mmap_len;
 	int		 id_pos;
@@ -82,8 +83,8 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
 			 int cpu, int thread, u64 id);
 
-void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
-
+int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
+int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
 int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
 
 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
-- 
1.9.3


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

* [PATCH 07/10] perf tests: Add pollfd growing test
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (5 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 06/10] perf evlist: Allow growing pollfd on add method Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 08/10] perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent Arnaldo Carvalho de Melo
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Corey Ashford, David Ahern, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Jiri Olsa, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

From: Arnaldo Carvalho de Melo <acme@redhat.com>

  [acme@ssdandy linux]$ perf test "Add fd"
  34: Add fd to pollfd array, making it autogrow             : Ok
  [acme@ssdandy linux]$ perf test -v "Add fd"
  34: Add fd to pollfd array, making it autogrow             :
  --- start ---
  test child forked, pid 19817

  before growing array:   2 [ 1, 2 ]
  after 3rd add_pollfd:   3 [ 1, 2, 35 ]
  after 4th add_pollfd:   4 [ 1, 2, 35, 88 ]
  test child finished with 0
  ---- end ----
  Add fd to pollfd array, making it autogrow: Ok
  [acme@ssdandy linux]$

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-smflpyta146bzog7z0effjss@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/builtin-test.c |   4 ++
 tools/perf/tests/evlist.c       | 111 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h        |   1 +
 3 files changed, 116 insertions(+)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 41e556edbe02..174c3ffc5713 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -162,6 +162,10 @@ static struct test {
 		.func = test__perf_evlist__filter_pollfd,
 	},
 	{
+		.desc = "Add fd to pollfd array, making it autogrow",
+		.func = test__perf_evlist__add_pollfd,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/evlist.c b/tools/perf/tests/evlist.c
index 77579158f4d9..99d7dfd4e20a 100644
--- a/tools/perf/tests/evlist.c
+++ b/tools/perf/tests/evlist.c
@@ -1,5 +1,7 @@
 #include "util/evlist.h"
 #include "util/debug.h"
+#include "util/thread_map.h"
+#include "util/cpumap.h"
 #include "tests/tests.h"
 
 static void perf_evlist__init_pollfd(struct perf_evlist *evlist,
@@ -101,3 +103,112 @@ int test__perf_evlist__filter_pollfd(void)
 
 	return 0;
 }
+
+int test__perf_evlist__add_pollfd(void)
+{
+	struct perf_evsel evsel = {
+		.system_wide = false,
+	};
+	struct thread_map threads = {
+		.nr = 2,
+	};
+	struct perf_evlist evlist_alloc = {
+		.pollfd	 = NULL,
+		.threads = &threads,
+	}, *evlist = &evlist_alloc;
+
+	INIT_LIST_HEAD(&evlist->entries);
+	list_add(&evsel.node, &evlist->entries);
+
+	if (perf_evlist__alloc_pollfd(evlist) < 0) {
+		pr_debug("\nperf_evlist__alloc_pollfd(evlist) failed!");
+		return TEST_FAIL;
+	}
+
+	if (evlist->nr_fds_alloc != threads.nr) {
+		pr_debug("\n_evlist__alloc_pollfd: nr_fds_alloc=%d != (threads->nr(%d) * cpu_map->nr(%d))=%d",
+			 evlist->nr_fds_alloc, thread_map__nr(evlist->threads), cpu_map__nr(evlist->cpus),
+			 thread_map__nr(evlist->threads) * cpu_map__nr(evlist->cpus));
+		return TEST_FAIL;
+	}
+
+	if (perf_evlist__add_pollfd(evlist, 1) < 0) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 1) failed!");
+		return TEST_FAIL;
+	}
+
+	if (evlist->nr_fds != 1) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 1)=%d != 1", evlist->nr_fds);
+		return TEST_FAIL;
+	}
+
+	if (perf_evlist__add_pollfd(evlist, 2) < 0) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 2) failed!");
+		return TEST_FAIL;
+	}
+
+	if (evlist->nr_fds != 2) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 2)=%d != 2", evlist->nr_fds);
+		return TEST_FAIL;
+	}
+
+	perf_evlist__fprintf_pollfd(evlist, "before growing array", stderr);
+
+	if (perf_evlist__add_pollfd(evlist, 35) < 0) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 35) failed!");
+		return TEST_FAIL;
+	}
+
+	if (evlist->nr_fds != 3) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 35)=%d != 3", evlist->nr_fds);
+		return TEST_FAIL;
+	}
+
+	if (evlist->pollfd == NULL) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 35) should have allocated evlist->pollfd!");
+		return TEST_FAIL;
+	}
+
+	perf_evlist__fprintf_pollfd(evlist, "after 3rd add_pollfd", stderr);
+
+	if (evlist->pollfd[2].fd != 35) {
+		pr_debug("\nevlist->pollfd[2](%d) != 35!", evlist->pollfd[2].fd);
+		return TEST_FAIL;
+	}
+
+	if (perf_evlist__add_pollfd(evlist, 88) < 0) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 88) failed!");
+		return TEST_FAIL;
+	}
+
+	if (evlist->nr_fds != 4) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 88)=%d != 2", evlist->nr_fds);
+		return TEST_FAIL;
+	}
+
+	perf_evlist__fprintf_pollfd(evlist, "after 4th add_pollfd", stderr);
+
+	if (evlist->pollfd[0].fd != 1) {
+		pr_debug("\nevlist->pollfd[0](%d) != 1!", evlist->pollfd[0].fd);
+		return TEST_FAIL;
+	}
+
+	if (evlist->pollfd[1].fd != 2) {
+		pr_debug("\nevlist->pollfd[1](%d) != 2!", evlist->pollfd[1].fd);
+		return TEST_FAIL;
+	}
+
+	if (evlist->pollfd[2].fd != 35) {
+		pr_debug("\nevlist->pollfd[2](%d) != 35!", evlist->pollfd[2].fd);
+		return TEST_FAIL;
+	}
+
+	if (evlist->pollfd[3].fd != 88) {
+		pr_debug("\nevlist->pollfd[3](%d) != 88!", evlist->pollfd[3].fd);
+		return TEST_FAIL;
+	}
+
+	pr_debug("\n");
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 72c4c039bd80..699d4bb61dc7 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -50,6 +50,7 @@ int test__hists_output(void);
 int test__hists_cumulate(void);
 int test__switch_tracking(void);
 int test__perf_evlist__filter_pollfd(void);
+int test__perf_evlist__add_pollfd(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-- 
1.9.3


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

* [PATCH 08/10] perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (6 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 07/10] perf tests: Add pollfd growing test Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-26 14:04   ` David Ahern
  2014-08-22 20:59 ` [PATCH 09/10] perf evlist: Introduce poll method for common code idiom Arnaldo Carvalho de Melo
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Corey Ashford, David Ahern, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Jiri Olsa, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Since we can add file descriptors to the evlist pollfd and it will
autogrow, no need to copy all events to a local pollfd array, just add
the timer and stdin file descriptors.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-2hvp9iromiheh6rl4oaa08x5@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-kvm.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 1a4ef9cd9d5f..b192234096b6 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -921,15 +921,8 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
 	signal(SIGINT, sig_handler);
 	signal(SIGTERM, sig_handler);
 
-	/* copy pollfds -- need to add timerfd and stdin */
+	/* use pollfds -- need to add timerfd and stdin */
 	nr_fds = kvm->evlist->nr_fds;
-	pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
-	if (!pollfds) {
-		err = -ENOMEM;
-		goto out;
-	}
-	memcpy(pollfds, kvm->evlist->pollfd,
-		sizeof(struct pollfd) * kvm->evlist->nr_fds);
 
 	/* add timer fd */
 	if (perf_kvm__timerfd_create(kvm) < 0) {
@@ -937,17 +930,21 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
 		goto out;
 	}
 
-	pollfds[nr_fds].fd = kvm->timerfd;
-	pollfds[nr_fds].events = POLLIN;
+	if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd))
+		goto out;
+
 	nr_fds++;
 
-	pollfds[nr_fds].fd = fileno(stdin);
-	pollfds[nr_fds].events = POLLIN;
+	if (perf_evlist__add_pollfd(kvm->evlist, fileno(stdin)))
+		goto out;
+
 	nr_stdin = nr_fds;
 	nr_fds++;
 	if (fd_set_nonblock(fileno(stdin)) != 0)
 		goto out;
 
+	pollfds	 = kvm->evlist->pollfd;
+
 	/* everything is good - enable the events and process */
 	perf_evlist__enable(kvm->evlist);
 
@@ -981,7 +978,6 @@ out:
 		close(kvm->timerfd);
 
 	tcsetattr(0, TCSAFLUSH, &save);
-	free(pollfds);
 	return err;
 }
 
-- 
1.9.3


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

* [PATCH 09/10] perf evlist: Introduce poll method for common code idiom
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (7 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 08/10] perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-22 20:59 ` [PATCH 10/10] tools lib api: Adopt fdarray class from perf's evlist Arnaldo Carvalho de Melo
  2014-08-25 11:04 ` [RFC 00/10] perf pollfd series Jiri Olsa
  10 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Corey Ashford, David Ahern, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Jiri Olsa, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

From: Arnaldo Carvalho de Melo <acme@redhat.com>

Since we have access two evlist members in all these poll calls, provide
a helper.

This will also help to make the patch introducing the pollfd class more
clear, as the evlist specific uses will be hiden away
perf_evlist__poll().

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-hizx410uqouefj52jujubv2y@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c               | 2 +-
 tools/perf/builtin-top.c                  | 4 ++--
 tools/perf/builtin-trace.c                | 2 +-
 tools/perf/tests/open-syscall-tp-fields.c | 2 +-
 tools/perf/tests/perf-record.c            | 2 +-
 tools/perf/tests/task-exit.c              | 2 +-
 tools/perf/util/evlist.c                  | 5 +++++
 tools/perf/util/evlist.h                  | 2 ++
 tools/perf/util/python.c                  | 2 +-
 9 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b87708ce09c9..aac86600b89e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -459,7 +459,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 		if (hits == rec->samples) {
 			if (done)
 				break;
-			err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1);
+			err = perf_evlist__poll(rec->evlist, -1);
 			/*
 			 * Propagate error, only if there's any. Ignore positive
 			 * number of returned events and interrupt error.
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 9848e270b92c..ef7c808c8ce2 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -964,7 +964,7 @@ static int __cmd_top(struct perf_top *top)
                 perf_evlist__enable(top->evlist);
 
 	/* Wait for a minimal set of events before starting the snapshot */
-	poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
+	perf_evlist__poll(top->evlist, 100);
 
 	perf_top__mmap_read(top);
 
@@ -991,7 +991,7 @@ static int __cmd_top(struct perf_top *top)
 		perf_top__mmap_read(top);
 
 		if (hits == top->samples)
-			ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
+			ret = perf_evlist__poll(top->evlist, 100);
 	}
 
 	ret = 0;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 09d4bc44215e..970aa0297697 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2171,7 +2171,7 @@ next_event:
 	if (trace->nr_events == before) {
 		int timeout = done ? 100 : -1;
 
-		if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0 &&
+		if (perf_evlist__poll(evlist, timeout) > 0 &&
 		    perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) > 0)
 			goto again;
 	} else {
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index 922bdb627950..127dcae0b760 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -105,7 +105,7 @@ int test__syscall_open_tp_fields(void)
 		}
 
 		if (nr_events == before)
-			poll(evlist->pollfd, evlist->nr_fds, 10);
+			perf_evlist__poll(evlist, 10);
 
 		if (++nr_polls > 5) {
 			pr_debug("%s: no events!\n", __func__);
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 2ce753c1db63..7a228a2a070b 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -268,7 +268,7 @@ int test__PERF_RECORD(void)
 		 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
 		 */
 		if (total_events == before && false)
-			poll(evlist->pollfd, evlist->nr_fds, -1);
+			perf_evlist__poll(evlist, -1);
 
 		sleep(1);
 		if (++wakeups > 5) {
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 87522f01c7ad..3a8fedef83bc 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -105,7 +105,7 @@ retry:
 	}
 
 	if (!exited || !nr_exit) {
-		poll(evlist->pollfd, evlist->nr_fds, -1);
+		perf_evlist__poll(evlist, -1);
 		goto retry;
 	}
 
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 9fb00c980312..6c44453049bb 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -470,6 +470,11 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas
 	return nr_fds;
 }
 
+int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
+{
+	return poll(evlist->pollfd, evlist->nr_fds, timeout);
+}
+
 static void perf_evlist__id_hash(struct perf_evlist *evlist,
 				 struct perf_evsel *evsel,
 				 int cpu, int thread, u64 id)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index bbc2fd01b5c5..d7e99b67c94f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -87,6 +87,8 @@ int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
 int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
 int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
 
+int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
+
 struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
 
 struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 12aa9b0d0ba1..4472f8be8e35 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -736,7 +736,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
 		return NULL;
 
-	n = poll(evlist->pollfd, evlist->nr_fds, timeout);
+	n = perf_evlist__poll(evlist, timeout);
 	if (n < 0) {
 		PyErr_SetFromErrno(PyExc_OSError);
 		return NULL;
-- 
1.9.3


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

* [PATCH 10/10] tools lib api: Adopt fdarray class from perf's evlist
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (8 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 09/10] perf evlist: Introduce poll method for common code idiom Arnaldo Carvalho de Melo
@ 2014-08-22 20:59 ` Arnaldo Carvalho de Melo
  2014-08-26  7:46   ` Namhyung Kim
  2014-08-25 11:04 ` [RFC 00/10] perf pollfd series Jiri Olsa
  10 siblings, 1 reply; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-22 20:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Borislav Petkov, Corey Ashford, David Ahern, Frederic Weisbecker,
	Ingo Molnar, Jean Pihet, Jiri Olsa, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

From: Arnaldo Carvalho de Melo <acme@redhat.com>

The extensible file description array that grew in the perf_evlist class
can be useful for other tools, as it is not something that only evlists
need, so move it to tools/lib/api/fd to ease sharing it.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-9fpsmemihi3mzktp0jymcz43@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/api/Makefile    |   7 +++-
 tools/lib/api/fd/poll.c   | 105 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/api/fd/poll.h   |  31 ++++++++++++++
 tools/perf/builtin-kvm.c  |   4 +-
 tools/perf/tests/evlist.c |  67 +++++++++++++++--------------
 tools/perf/util/evlist.c  |  52 ++++-------------------
 tools/perf/util/evlist.h  |   5 +--
 tools/perf/util/python.c  |   4 +-
 8 files changed, 191 insertions(+), 84 deletions(-)
 create mode 100644 tools/lib/api/fd/poll.c
 create mode 100644 tools/lib/api/fd/poll.h

diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index ce00f7ee6455..b76ad9a0bac3 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -10,9 +10,14 @@ LIB_OBJS=
 
 LIB_H += fs/debugfs.h
 LIB_H += fs/fs.h
+# See comment below about piggybacking...
+LIB_H += fd/poll.h
 
 LIB_OBJS += $(OUTPUT)fs/debugfs.o
 LIB_OBJS += $(OUTPUT)fs/fs.o
+# XXX piggybacking here, need to introduce libapikfd, or rename this
+# to plain libapik.a and make it have it all api goodies
+LIB_OBJS += $(OUTPUT)fd/poll.o
 
 LIBFILE = libapikfs.a
 
@@ -29,7 +34,7 @@ $(LIBFILE): $(LIB_OBJS)
 $(LIB_OBJS): $(LIB_H)
 
 libapi_dirs:
-	$(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/
+	$(QUIET_MKDIR)mkdir -p $(OUTPUT){fs,fd}/
 
 $(OUTPUT)%.o: %.c libapi_dirs
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
diff --git a/tools/lib/api/fd/poll.c b/tools/lib/api/fd/poll.c
new file mode 100644
index 000000000000..25535b52bc87
--- /dev/null
+++ b/tools/lib/api/fd/poll.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+#include "poll.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+void fdarray__init(struct fdarray *fda)
+{
+	fda->entries = NULL;
+	fda->nr = fda->nr_alloc = 0;
+}
+
+int fdarray__grow(struct fdarray *fda, int hint)
+{
+	int nr_alloc = fda->nr_alloc + hint;
+	size_t size = sizeof(struct pollfd) * nr_alloc;
+	struct pollfd *entries = realloc(fda->entries, size);
+
+	if (entries == NULL)
+		return -ENOMEM;
+
+	fda->nr_alloc = nr_alloc;
+	fda->entries  = entries;
+	return 0;
+}
+
+struct fdarray *fdarray__new(int nr_alloc)
+{
+	struct fdarray *fda = calloc(1, sizeof(*fda));
+
+	if (fda != NULL) {
+		if (fdarray__grow(fda, nr_alloc)) {
+			free(fda);
+			fda = NULL;
+		}
+	}
+
+	return fda;
+}
+
+void fdarray__exit(struct fdarray *fda)
+{
+	free(fda->entries);
+	fdarray__init(fda);
+}
+
+void fdarray__delete(struct fdarray *fda)
+{
+	fdarray__exit(fda);
+	free(fda);
+}
+
+int fdarray__add(struct fdarray *fda, int fd)
+{
+	/*
+	 * XXX: 64 is arbitrary, just not to call realloc at each fd.
+	 *	Find a better autogrowing heuristic
+	 */
+	if (fda->nr == fda->nr_alloc &&
+	    fdarray__grow(fda, 64) < 0)
+		return -ENOMEM;
+
+	fcntl(fd, F_SETFL, O_NONBLOCK);
+	fda->entries[fda->nr].fd = fd;
+	fda->entries[fda->nr].events = POLLIN | POLLERR | POLLHUP;
+	fda->nr++;
+	return 0;
+}
+
+int fdarray__filter(struct fdarray *fda, short revents_and_mask)
+{
+	int fd = 0, nr = 0;
+
+	while (fd < fda->nr) {
+		if ((fda->entries[fd].revents & revents_and_mask) == 0)
+			++nr;
+
+		if (++fd != nr)
+			fda->entries[nr] = fda->entries[fd];
+	}
+
+	fda->nr = nr;
+	return nr;
+}
+
+int fdarray__poll(struct fdarray *fda, int timeout)
+{
+	return poll(fda->entries, fda->nr, timeout);
+}
+
+int fdarray__fprintf(struct fdarray *fda, FILE *fp)
+{
+	int fd, printed = fprintf(fp, "%d [ ", fda->nr);
+
+	for (fd = 0; fd < fda->nr; ++fd)
+		printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd);
+
+	return printed + fprintf(fp, " ]");
+}
diff --git a/tools/lib/api/fd/poll.h b/tools/lib/api/fd/poll.h
new file mode 100644
index 000000000000..4b9ed25d6f55
--- /dev/null
+++ b/tools/lib/api/fd/poll.h
@@ -0,0 +1,31 @@
+#ifndef __API_FD_POLL__
+#define __API_FD_POLL__
+
+#include <stdio.h>
+
+struct pollfd;
+
+struct fdarray {
+	int	       nr;
+	int	       nr_alloc;
+	struct pollfd *entries;
+};
+
+void fdarray__init(struct fdarray *fda);
+void fdarray__exit(struct fdarray *fda);
+
+struct fdarray *fdarray__new(int nr_alloc);
+void fdarray__delete(struct fdarray *fda);
+
+int fdarray__add(struct fdarray *fda, int fd);
+int fdarray__poll(struct fdarray *fda, int timeout);
+int fdarray__filter(struct fdarray *fda, short revents_and_mask);
+int fdarray__grow(struct fdarray *fda, int extra);
+int fdarray__fprintf(struct fdarray *fda, FILE *fp);
+
+static inline int fdarray__available_entries(struct fdarray *fda)
+{
+	return fda->nr_alloc - fda->nr;
+}
+
+#endif /* __API_FD_POLL__ */
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index b192234096b6..d1d6aad0c29e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -922,7 +922,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
 	signal(SIGTERM, sig_handler);
 
 	/* use pollfds -- need to add timerfd and stdin */
-	nr_fds = kvm->evlist->nr_fds;
+	nr_fds = kvm->evlist->pollfd.nr;
 
 	/* add timer fd */
 	if (perf_kvm__timerfd_create(kvm) < 0) {
@@ -943,7 +943,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
 	if (fd_set_nonblock(fileno(stdin)) != 0)
 		goto out;
 
-	pollfds	 = kvm->evlist->pollfd;
+	pollfds	 = kvm->evlist->pollfd.entries;
 
 	/* everything is good - enable the events and process */
 	perf_evlist__enable(kvm->evlist);
diff --git a/tools/perf/tests/evlist.c b/tools/perf/tests/evlist.c
index 99d7dfd4e20a..fe3e118b25bd 100644
--- a/tools/perf/tests/evlist.c
+++ b/tools/perf/tests/evlist.c
@@ -8,28 +8,26 @@ static void perf_evlist__init_pollfd(struct perf_evlist *evlist,
 				     int nr_fds_alloc, short revents)
 {
 	int fd;
+	struct fdarray *fda = &evlist->pollfd;
 
-	evlist->nr_fds = nr_fds_alloc;
+	fda->nr = nr_fds_alloc;
 
 	for (fd = 0; fd < nr_fds_alloc; ++fd) {
-		evlist->pollfd[fd].fd	   = nr_fds_alloc - fd;
-		evlist->pollfd[fd].revents = revents;
+		fda->entries[fd].fd	 = nr_fds_alloc - fd;
+		fda->entries[fd].revents = revents;
 	}
 }
 
 static int perf_evlist__fprintf_pollfd(struct perf_evlist *evlist,
 				       const char *prefix, FILE *fp)
 {
-	int printed = 0, fd;
+	int printed = 0;
 
 	if (!verbose)
 		return 0;
 
-	printed += fprintf(fp, "\n%s: %3d [ ", prefix, evlist->nr_fds);
-	for (fd = 0; fd < evlist->nr_fds; ++fd)
-		printed += fprintf(fp, "%s%d", fd ? ", " : "", evlist->pollfd[fd].fd);
-	printed += fprintf(fp, " ]");
-	return printed;
+	printed += fprintf(fp, "\n%s: ", prefix);
+	return fdarray__fprintf(&evlist->pollfd, fp);
 }
 
 int test__perf_evlist__filter_pollfd(void)
@@ -38,7 +36,9 @@ int test__perf_evlist__filter_pollfd(void)
 	int nr_fds, expected_fd[2], fd;
 	struct pollfd pollfd[nr_fds_alloc];
 	struct perf_evlist evlist_alloc = {
-		.pollfd	= pollfd,
+		.pollfd	= {
+			.entries = pollfd,
+		},
 	}, *evlist = &evlist_alloc;
 
 	perf_evlist__init_pollfd(evlist, nr_fds_alloc, POLLIN);
@@ -113,9 +113,12 @@ int test__perf_evlist__add_pollfd(void)
 		.nr = 2,
 	};
 	struct perf_evlist evlist_alloc = {
-		.pollfd	 = NULL,
+		.pollfd	 = {
+			.entries = NULL,
+		},
 		.threads = &threads,
 	}, *evlist = &evlist_alloc;
+	struct fdarray *fda = &evlist->pollfd;
 
 	INIT_LIST_HEAD(&evlist->entries);
 	list_add(&evsel.node, &evlist->entries);
@@ -125,9 +128,9 @@ int test__perf_evlist__add_pollfd(void)
 		return TEST_FAIL;
 	}
 
-	if (evlist->nr_fds_alloc != threads.nr) {
+	if (fda->nr_alloc != threads.nr) {
 		pr_debug("\n_evlist__alloc_pollfd: nr_fds_alloc=%d != (threads->nr(%d) * cpu_map->nr(%d))=%d",
-			 evlist->nr_fds_alloc, thread_map__nr(evlist->threads), cpu_map__nr(evlist->cpus),
+			 fda->nr_alloc, thread_map__nr(evlist->threads), cpu_map__nr(evlist->cpus),
 			 thread_map__nr(evlist->threads) * cpu_map__nr(evlist->cpus));
 		return TEST_FAIL;
 	}
@@ -137,8 +140,8 @@ int test__perf_evlist__add_pollfd(void)
 		return TEST_FAIL;
 	}
 
-	if (evlist->nr_fds != 1) {
-		pr_debug("\nperf_evlist__add_pollfd(evlist, 1)=%d != 1", evlist->nr_fds);
+	if (fda->nr != 1) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 1)=%d != 1", fda->nr);
 		return TEST_FAIL;
 	}
 
@@ -147,8 +150,8 @@ int test__perf_evlist__add_pollfd(void)
 		return TEST_FAIL;
 	}
 
-	if (evlist->nr_fds != 2) {
-		pr_debug("\nperf_evlist__add_pollfd(evlist, 2)=%d != 2", evlist->nr_fds);
+	if (fda->nr != 2) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 2)=%d != 2", fda->nr);
 		return TEST_FAIL;
 	}
 
@@ -159,20 +162,20 @@ int test__perf_evlist__add_pollfd(void)
 		return TEST_FAIL;
 	}
 
-	if (evlist->nr_fds != 3) {
-		pr_debug("\nperf_evlist__add_pollfd(evlist, 35)=%d != 3", evlist->nr_fds);
+	if (fda->nr != 3) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 35)=%d != 3", fda->nr);
 		return TEST_FAIL;
 	}
 
-	if (evlist->pollfd == NULL) {
+	if (fda->entries == NULL) {
 		pr_debug("\nperf_evlist__add_pollfd(evlist, 35) should have allocated evlist->pollfd!");
 		return TEST_FAIL;
 	}
 
 	perf_evlist__fprintf_pollfd(evlist, "after 3rd add_pollfd", stderr);
 
-	if (evlist->pollfd[2].fd != 35) {
-		pr_debug("\nevlist->pollfd[2](%d) != 35!", evlist->pollfd[2].fd);
+	if (fda->entries[2].fd != 35) {
+		pr_debug("\nfda->entries[2](%d) != 35!", fda->entries[2].fd);
 		return TEST_FAIL;
 	}
 
@@ -181,30 +184,30 @@ int test__perf_evlist__add_pollfd(void)
 		return TEST_FAIL;
 	}
 
-	if (evlist->nr_fds != 4) {
-		pr_debug("\nperf_evlist__add_pollfd(evlist, 88)=%d != 2", evlist->nr_fds);
+	if (fda->nr != 4) {
+		pr_debug("\nperf_evlist__add_pollfd(evlist, 88)=%d != 2", fda->nr);
 		return TEST_FAIL;
 	}
 
 	perf_evlist__fprintf_pollfd(evlist, "after 4th add_pollfd", stderr);
 
-	if (evlist->pollfd[0].fd != 1) {
-		pr_debug("\nevlist->pollfd[0](%d) != 1!", evlist->pollfd[0].fd);
+	if (fda->entries[0].fd != 1) {
+		pr_debug("\nfda->entries[0](%d) != 1!", fda->entries[0].fd);
 		return TEST_FAIL;
 	}
 
-	if (evlist->pollfd[1].fd != 2) {
-		pr_debug("\nevlist->pollfd[1](%d) != 2!", evlist->pollfd[1].fd);
+	if (fda->entries[1].fd != 2) {
+		pr_debug("\nfda->entries[1](%d) != 2!", fda->entries[1].fd);
 		return TEST_FAIL;
 	}
 
-	if (evlist->pollfd[2].fd != 35) {
-		pr_debug("\nevlist->pollfd[2](%d) != 35!", evlist->pollfd[2].fd);
+	if (fda->entries[2].fd != 35) {
+		pr_debug("\nfda->entries[2](%d) != 35!", fda->entries[2].fd);
 		return TEST_FAIL;
 	}
 
-	if (evlist->pollfd[3].fd != 88) {
-		pr_debug("\nevlist->pollfd[3](%d) != 88!", evlist->pollfd[3].fd);
+	if (fda->entries[3].fd != 88) {
+		pr_debug("\nfda->entries[3](%d) != 88!", fda->entries[3].fd);
 		return TEST_FAIL;
 	}
 
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6c44453049bb..4425b4a83c19 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -37,6 +37,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
 		INIT_HLIST_HEAD(&evlist->heads[i]);
 	INIT_LIST_HEAD(&evlist->entries);
 	perf_evlist__set_maps(evlist, cpus, threads);
+	fdarray__init(&evlist->pollfd);
 	evlist->workload.pid = -1;
 }
 
@@ -102,7 +103,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
 	zfree(&evlist->mmap);
-	zfree(&evlist->pollfd);
+	fdarray__exit(&evlist->pollfd);
 }
 
 void perf_evlist__delete(struct perf_evlist *evlist)
@@ -402,20 +403,6 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
 		return perf_evlist__enable_event_thread(evlist, evsel, idx);
 }
 
-static int perf_evlist__grow_pollfd(struct perf_evlist *evlist, int hint)
-{
-	int nr_fds_alloc = evlist->nr_fds_alloc + hint;
-	size_t size = sizeof(struct pollfd) * nr_fds_alloc;
-	struct pollfd *pollfd = realloc(evlist->pollfd, size);
-
-	if (pollfd == NULL)
-		return -ENOMEM;
-
-	evlist->nr_fds_alloc = nr_fds_alloc;
-	evlist->pollfd	     = pollfd;
-	return 0;
-}
-
 int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
 {
 	int nr_cpus = cpu_map__nr(evlist->cpus);
@@ -430,8 +417,8 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
 			nfds += nr_cpus * nr_threads;
 	}
 
-	if (evlist->nr_fds_alloc - evlist->nr_fds < nfds &&
-	    perf_evlist__grow_pollfd(evlist, nfds) < 0)
+	if (fdarray__available_entries(&evlist->pollfd) < nfds &&
+	    fdarray__grow(&evlist->pollfd, nfds) < 0)
 		return -ENOMEM;
 
 	return 0;
@@ -439,40 +426,17 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
 
 int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
 {
-	/*
-	 * XXX: 64 is arbitrary, just not to call realloc at each fd.
-	 *	Find a better autogrowing heuristic
-	 */
-	if (evlist->nr_fds == evlist->nr_fds_alloc &&
-	    perf_evlist__grow_pollfd(evlist, 64) < 0)
-		return -ENOMEM;
-
-	fcntl(fd, F_SETFL, O_NONBLOCK);
-	evlist->pollfd[evlist->nr_fds].fd = fd;
-	evlist->pollfd[evlist->nr_fds].events = POLLIN | POLLERR | POLLHUP;
-	evlist->nr_fds++;
-	return 0;
+	return fdarray__add(&evlist->pollfd, fd);
 }
 
 int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
 {
-	int fd = 0, nr_fds = 0;
-
-	while (fd < evlist->nr_fds) {
-		if ((evlist->pollfd[fd].revents & revents_and_mask) == 0)
-			++nr_fds;
-
-		if (++fd != nr_fds)
-			evlist->pollfd[nr_fds] = evlist->pollfd[fd];
-	}
-
-	evlist->nr_fds = nr_fds;
-	return nr_fds;
+	return fdarray__filter(&evlist->pollfd, revents_and_mask);
 }
 
 int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
 {
-	return poll(evlist->pollfd, evlist->nr_fds, timeout);
+	return fdarray__poll(&evlist->pollfd, timeout);
 }
 
 static void perf_evlist__id_hash(struct perf_evlist *evlist,
@@ -932,7 +896,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 	if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
 		return -ENOMEM;
 
-	if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
+	if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
 		return -ENOMEM;
 
 	evlist->overwrite = overwrite;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index d7e99b67c94f..6d060e9882c3 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,6 +2,7 @@
 #define __PERF_EVLIST_H 1
 
 #include <linux/list.h>
+#include <api/fd/poll.h>
 #include <stdio.h>
 #include "../perf.h"
 #include "event.h"
@@ -29,8 +30,6 @@ struct perf_evlist {
 	struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
 	int		 nr_entries;
 	int		 nr_groups;
-	int		 nr_fds;
-	int		 nr_fds_alloc;
 	int		 nr_mmaps;
 	size_t		 mmap_len;
 	int		 id_pos;
@@ -41,8 +40,8 @@ struct perf_evlist {
 		pid_t	pid;
 	} workload;
 	bool		 overwrite;
+	struct fdarray	 pollfd;
 	struct perf_mmap *mmap;
-	struct pollfd	 *pollfd;
 	struct thread_map *threads;
 	struct cpu_map	  *cpus;
 	struct perf_evsel *selected;
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 4472f8be8e35..3dda85ca50c1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -753,9 +753,9 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
         PyObject *list = PyList_New(0);
 	int i;
 
-	for (i = 0; i < evlist->nr_fds; ++i) {
+	for (i = 0; i < evlist->pollfd.nr; ++i) {
 		PyObject *file;
-		FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
+		FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
 
 		if (fp == NULL)
 			goto free_list;
-- 
1.9.3


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

* Re: [PATCH 01/10] perf evlist: Introduce perf_evlist__filter_pollfd method
  2014-08-22 20:59 ` [PATCH 01/10] perf evlist: Introduce perf_evlist__filter_pollfd method Arnaldo Carvalho de Melo
@ 2014-08-25  6:57   ` Adrian Hunter
  0 siblings, 0 replies; 20+ messages in thread
From: Adrian Hunter @ 2014-08-25  6:57 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Don Zickus, Frederic Weisbecker, Ingo Molnar, Mike Galbraith,
	Namhyung Kim, Paul Mackerras, Peter Zijlstra, Stephane Eranian

On 08/22/2014 11:59 PM, Arnaldo Carvalho de Melo wrote:
> From: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> To remove all entries in evlist->pollfd[] that have revents matching at
> least one of the bits in the specified mask.
> 
> It'll adjust evlist->nr_fds to the number of unfiltered fds and will
> return this value, as a convenience and to avoid requiring direct access
> to internal state of perf_evlist objects.
> 
> This will be used after polling the evlist fds so that we remove fds
> that were closed by the kernel.
> 
> Cc: Adrian Hunter <adrian.hunter@intel.com>
> Cc: David Ahern <dsahern@gmail.com>
> Cc: Don Zickus <dzickus@redhat.com>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Mike Galbraith <efault@gmx.de>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Stephane Eranian <eranian@google.com>
> Link: http://lkml.kernel.org/n/tip-ki3oqbfjg84si3f9amhyqvzb@git.kernel.org
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> ---
>  tools/perf/util/evlist.c | 16 ++++++++++++++++
>  tools/perf/util/evlist.h |  2 ++
>  2 files changed, 18 insertions(+)
> 
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index a3e28b49128a..bd7896073d10 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -428,6 +428,22 @@ void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
>  	evlist->nr_fds++;
>  }
>  
> +int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
> +{
> +	int fd = 0, nr_fds = 0;
> +
> +	while (fd < evlist->nr_fds) {

A for loop is clearer e.g.

	for (fd = 0; fd < evlist->nr_fds; fd++) {


> +		if ((evlist->pollfd[fd].revents & revents_and_mask) == 0)
> +			++nr_fds;
> +
> +		if (++fd != nr_fds)
> +			evlist->pollfd[nr_fds] = evlist->pollfd[fd];

That looks like it will go off the end of the array.  Shouldn't it be:

		if ((evlist->pollfd[fd].revents & revents_and_mask) == 0) {
			if (fd != nr_fds)
				evlist->pollfd[nr_fds] = evlist->pollfd[fd];
			nr_fds += 1;
		}

> +	}
> +
> +	evlist->nr_fds = nr_fds;
> +	return nr_fds;
> +}
> +
>  static void perf_evlist__id_hash(struct perf_evlist *evlist,
>  				 struct perf_evsel *evsel,
>  				 int cpu, int thread, u64 id)
> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
> index 106de53a6a74..1082420951f9 100644
> --- a/tools/perf/util/evlist.h
> +++ b/tools/perf/util/evlist.h
> @@ -84,6 +84,8 @@ void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
>  
>  void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
>  
> +int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
> +
>  struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
>  
>  struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
> 


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

* Re: [PATCH 06/10] perf evlist: Allow growing pollfd on add method
  2014-08-22 20:59 ` [PATCH 06/10] perf evlist: Allow growing pollfd on add method Arnaldo Carvalho de Melo
@ 2014-08-25  9:41   ` Jiri Olsa
  2014-08-25  9:47   ` Jiri Olsa
  1 sibling, 0 replies; 20+ messages in thread
From: Jiri Olsa @ 2014-08-25  9:41 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Corey Ashford, David Ahern, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Jiri Olsa, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

On Fri, Aug 22, 2014 at 05:59:46PM -0300, Arnaldo Carvalho de Melo wrote:

SNIP

> -void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
> +int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
>  {
> +	/*
> +	 * XXX: 64 is arbitrary, just not to call realloc at each fd.
> +	 *	Find a better autogrowing heuristic
> +	 */
> +	if (evlist->nr_fds == evlist->nr_fds_alloc &&
> +	    perf_evlist__grow_pollfd(evlist, 64) < 0)
> +		return -ENOMEM;
> +
>  	fcntl(fd, F_SETFL, O_NONBLOCK);
>  	evlist->pollfd[evlist->nr_fds].fd = fd;
>  	evlist->pollfd[evlist->nr_fds].events = POLLIN | POLLERR | POLLHUP;
>  	evlist->nr_fds++;
> +	return 0;
>  }
>  
>  int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
> @@ -713,7 +739,11 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
>  		return -1;
>  	}
>  
> -	perf_evlist__add_pollfd(evlist, fd);
> +	if (perf_evlist__add_pollfd(evlist, fd) < 0) {
> +		__perf_evlist__munmap(evlist->mmap[idx].base, idx);

unmap does not look necessary here.. should be handeled by out_unmap
in both perf_evlist__mmap_per_thread and perf_evlist__mmap_per_cpu

jirka

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

* Re: [PATCH 06/10] perf evlist: Allow growing pollfd on add method
  2014-08-22 20:59 ` [PATCH 06/10] perf evlist: Allow growing pollfd on add method Arnaldo Carvalho de Melo
  2014-08-25  9:41   ` Jiri Olsa
@ 2014-08-25  9:47   ` Jiri Olsa
  2014-08-25 15:59     ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 20+ messages in thread
From: Jiri Olsa @ 2014-08-25  9:47 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Corey Ashford, David Ahern, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Jiri Olsa, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

On Fri, Aug 22, 2014 at 05:59:46PM -0300, Arnaldo Carvalho de Melo wrote:

SNIP

>  
> -static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
> +static int perf_evlist__grow_pollfd(struct perf_evlist *evlist, int hint)
> +{
> +	int nr_fds_alloc = evlist->nr_fds_alloc + hint;
> +	size_t size = sizeof(struct pollfd) * nr_fds_alloc;
> +	struct pollfd *pollfd = realloc(evlist->pollfd, size);
> +
> +	if (pollfd == NULL)
> +		return -ENOMEM;
> +
> +	evlist->nr_fds_alloc = nr_fds_alloc;
> +	evlist->pollfd	     = pollfd;
> +	return 0;
> +}
> +
> +int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
>  {
>  	int nr_cpus = cpu_map__nr(evlist->cpus);
>  	int nr_threads = thread_map__nr(evlist->threads);
> @@ -416,16 +430,28 @@ static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
>  			nfds += nr_cpus * nr_threads;
>  	}
>  
> -	evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
> -	return evlist->pollfd != NULL ? 0 : -ENOMEM;
> +	if (evlist->nr_fds_alloc - evlist->nr_fds < nfds &&
> +	    perf_evlist__grow_pollfd(evlist, nfds) < 0)
> +		return -ENOMEM;

hum, so do we still need perf_evlist__alloc_pollfd?
we grow any time we need inside perf_evlist__add_pollfd..

jirka

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

* Re: [RFC 00/10] perf pollfd series
  2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
                   ` (9 preceding siblings ...)
  2014-08-22 20:59 ` [PATCH 10/10] tools lib api: Adopt fdarray class from perf's evlist Arnaldo Carvalho de Melo
@ 2014-08-25 11:04 ` Jiri Olsa
  2014-08-25 15:56   ` Arnaldo Carvalho de Melo
  10 siblings, 1 reply; 20+ messages in thread
From: Jiri Olsa @ 2014-08-25 11:04 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, Adrian Hunter, Borislav Petkov, Corey Ashford,
	David Ahern, Don Zickus, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Mike Galbraith, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

On Fri, Aug 22, 2014 at 05:59:40PM -0300, Arnaldo Carvalho de Melo wrote:
> Hi,
> 
> 	This is an alternative series to the one Jiri Olsa posted to use the
> fixes he made to the kernel side to allow tooling to notice that a thread had
> exited by looking at the pollfd.revents looking for POLLHUP notifications.
> 
> 	Once all event file descriptors are removed from the evlist pollfd array,
> tools can make a decision about exiting or telling the user about what happened,
> asking to guidance on what to do next.
> 
> 	The main difference in this approach is that a new class, which Jiri
> called 'poller' and I called 'fdarray', grew up from what was in evlist->pollfd
> and associated operations, while Jiri first introduced a new class and then
> made tooling use it.
> 
> 	The details of the implementation should be clear on the changelog
> comments, please let me know if you see any problems, and if I can have your
> acked-by/tested-by/whatever-else tags to get this moving forward.
> 
> 	Ah, there is still one missing thing which is to make the hists browser
> in live mode be notified that all monitored events are POLLHUP'ed, will get
> to that in followup patches.
> 
> 	The kernel bits were sent together with my latest pull req to Ingo,
> this series is on top of that branch and is available at:
> 
>  git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git perf/pollfd
> 
> - Arnaldo
> 
> Arnaldo Carvalho de Melo (10):
>   perf evlist: Introduce perf_evlist__filter_pollfd method
>   perf tests: Add test for perf_evlist__filter_pollfd()
>   perf evlist: Monitor POLLERR and POLLHUP events too
>   perf record: Filter out POLLHUP'ed file descriptors
>   perf trace: Filter out POLLHUP'ed file descriptors
>   perf evlist: Allow growing pollfd on add method
>   perf tests: Add pollfd growing test
>   perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent
>   perf evlist: Introduce poll method for common code idiom
>   tools lib api: Adopt fdarray class from perf's evlist

fdarray name seems too generic for this object, fdpoll looks
more suitable.. also given that the file name is poll.[ch] ;-)

anyway, except for what I've already commented:

Acked-by: Jiri Olsa <jolsa@kernel.org>

jirka

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

* Re: [RFC 00/10] perf pollfd series
  2014-08-25 11:04 ` [RFC 00/10] perf pollfd series Jiri Olsa
@ 2014-08-25 15:56   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-25 15:56 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Adrian Hunter, Borislav Petkov, Corey Ashford,
	David Ahern, Don Zickus, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Mike Galbraith, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Stephane Eranian

Em Mon, Aug 25, 2014 at 01:04:31PM +0200, Jiri Olsa escreveu:
> fdarray name seems too generic for this object, fdpoll looks
> more suitable.. also given that the file name is poll.[ch] ;-)

I thought about 'struct pollfds', then thought that having 'poll' in the
name of the class and in its main routine, i.e. pollfds__poll, would be
too much.

I thought of it as an extensible array of file descriptors that right
now has just poll related operations, but could have some other
operations, perhaps the associated mmaps in evlist, for instance.

I ended up using poll.[ch] because struct pollfd came from poll.h, but
yeah, that is inconsistent with poll being just one of the operations
for an extensible array of file descriptors, so it should be renamed
accordingly to 'fdarray.[ch]'.

That was my reasoning.

I'm looking at the other comments, would send a fix for what Adrian
commented but thought about an optimization, will do that after lunch,
hopefully food will prevent me from adding more bugs 8-)

> anyway, except for what I've already commented:

> Acked-by: Jiri Olsa <jolsa@kernel.org>

Thanks!

- Arnaldo

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

* Re: [PATCH 06/10] perf evlist: Allow growing pollfd on add method
  2014-08-25  9:47   ` Jiri Olsa
@ 2014-08-25 15:59     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-25 15:59 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Adrian Hunter, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Jiri Olsa,
	Namhyung Kim, Paul Mackerras, Peter Zijlstra

Em Mon, Aug 25, 2014 at 11:47:47AM +0200, Jiri Olsa escreveu:
> On Fri, Aug 22, 2014 at 05:59:46PM -0300, Arnaldo Carvalho de Melo wrote:

> > -static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
> > +static int perf_evlist__grow_pollfd(struct perf_evlist *evlist, int hint)
> > +{
> > +	int nr_fds_alloc = evlist->nr_fds_alloc + hint;
> > +	size_t size = sizeof(struct pollfd) * nr_fds_alloc;
> > +	struct pollfd *pollfd = realloc(evlist->pollfd, size);
> > +
> > +	if (pollfd == NULL)
> > +		return -ENOMEM;
> > +
> > +	evlist->nr_fds_alloc = nr_fds_alloc;
> > +	evlist->pollfd	     = pollfd;
> > +	return 0;
> > +}
> > +
> > +int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
> >  {
> >  	int nr_cpus = cpu_map__nr(evlist->cpus);
> >  	int nr_threads = thread_map__nr(evlist->threads);
> > @@ -416,16 +430,28 @@ static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
> >  			nfds += nr_cpus * nr_threads;
> >  	}
> >  
> > -	evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
> > -	return evlist->pollfd != NULL ? 0 : -ENOMEM;
> > +	if (evlist->nr_fds_alloc - evlist->nr_fds < nfds &&
> > +	    perf_evlist__grow_pollfd(evlist, nfds) < 0)
> > +		return -ENOMEM;
> 
> hum, so do we still need perf_evlist__alloc_pollfd?
> we grow any time we need inside perf_evlist__add_pollfd..

Humm, yeah, it could conceivably be removed and then we would rely
always on add_pollfd() autogrowing it as needed. But then, I thought
that code using this could optimize for the case where it knows in
advance how many entries it will need, just like perf_evlist does.

I.e. the first thing builtin-kvm.c should do would be to grow it by two
more entries, because it knows it wants to add just two more entries, in
advance, etc.

- Arnaldo

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

* Re: [PATCH 10/10] tools lib api: Adopt fdarray class from perf's evlist
  2014-08-22 20:59 ` [PATCH 10/10] tools lib api: Adopt fdarray class from perf's evlist Arnaldo Carvalho de Melo
@ 2014-08-26  7:46   ` Namhyung Kim
  2014-08-26 13:08     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 20+ messages in thread
From: Namhyung Kim @ 2014-08-26  7:46 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Borislav Petkov, Corey Ashford, David Ahern, Frederic Weisbecker,
	Ingo Molnar, Jean Pihet, Jiri Olsa, Paul Mackerras,
	Peter Zijlstra

Hi Arnaldo,

On Fri, 22 Aug 2014 17:59:50 -0300, Arnaldo Carvalho de Melo wrote:
> +int fdarray__add(struct fdarray *fda, int fd)
> +{
> +	/*
> +	 * XXX: 64 is arbitrary, just not to call realloc at each fd.
> +	 *	Find a better autogrowing heuristic
> +	 */
> +	if (fda->nr == fda->nr_alloc &&
> +	    fdarray__grow(fda, 64) < 0)
> +		return -ENOMEM;
> +
> +	fcntl(fd, F_SETFL, O_NONBLOCK);
> +	fda->entries[fda->nr].fd = fd;
> +	fda->entries[fda->nr].events = POLLIN | POLLERR | POLLHUP;
> +	fda->nr++;
> +	return 0;
> +}

To be more generic api, I think it'd be better receiving events from
user rather than hard-coding.  Also it might be useful to let user
sets a grow hint (during init?) as well.

Thanks,
Namhyung

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

* Re: [PATCH 10/10] tools lib api: Adopt fdarray class from perf's evlist
  2014-08-26  7:46   ` Namhyung Kim
@ 2014-08-26 13:08     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-08-26 13:08 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Jiri Olsa, linux-kernel, Adrian Hunter, Borislav Petkov,
	Corey Ashford, David Ahern, Frederic Weisbecker, Ingo Molnar,
	Jean Pihet, Jiri Olsa, Paul Mackerras, Peter Zijlstra

Em Tue, Aug 26, 2014 at 04:46:18PM +0900, Namhyung Kim escreveu:
> Hi Arnaldo,
> 
> On Fri, 22 Aug 2014 17:59:50 -0300, Arnaldo Carvalho de Melo wrote:
> > +int fdarray__add(struct fdarray *fda, int fd)
> > +{
> > +	/*
> > +	 * XXX: 64 is arbitrary, just not to call realloc at each fd.
> > +	 *	Find a better autogrowing heuristic
> > +	 */
> > +	if (fda->nr == fda->nr_alloc &&
> > +	    fdarray__grow(fda, 64) < 0)
> > +		return -ENOMEM;
> > +
> > +	fcntl(fd, F_SETFL, O_NONBLOCK);
> > +	fda->entries[fda->nr].fd = fd;
> > +	fda->entries[fda->nr].events = POLLIN | POLLERR | POLLHUP;
> > +	fda->nr++;
> > +	return 0;
> > +}
> 
> To be more generic api, I think it'd be better receiving events from
> user rather than hard-coding.  Also it might be useful to let user

Agreed, will do.

> sets a grow hint (during init?) as well.

Sure, that can be done as well, and with that, ditch that hard coded
value.

Thanks,

- Arnaldo

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

* Re: [PATCH 08/10] perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent
  2014-08-22 20:59 ` [PATCH 08/10] perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent Arnaldo Carvalho de Melo
@ 2014-08-26 14:04   ` David Ahern
  0 siblings, 0 replies; 20+ messages in thread
From: David Ahern @ 2014-08-26 14:04 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa
  Cc: linux-kernel, Arnaldo Carvalho de Melo, Adrian Hunter,
	Corey Ashford, Frederic Weisbecker, Ingo Molnar, Jean Pihet,
	Jiri Olsa, Namhyung Kim, Paul Mackerras, Peter Zijlstra

On 8/22/14, 2:59 PM, Arnaldo Carvalho de Melo wrote:
> From: Arnaldo Carvalho de Melo <acme@redhat.com>
>
> Since we can add file descriptors to the evlist pollfd and it will
> autogrow, no need to copy all events to a local pollfd array, just add
> the timer and stdin file descriptors.
>
> Cc: Adrian Hunter <adrian.hunter@intel.com>
> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
> Cc: David Ahern <dsahern@gmail.com>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Jean Pihet <jean.pihet@linaro.org>
> Cc: Jiri Olsa <jolsa@kernel.org>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Link: http://lkml.kernel.org/n/tip-2hvp9iromiheh6rl4oaa08x5@git.kernel.org
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> ---
>   tools/perf/builtin-kvm.c | 22 +++++++++-------------
>   1 file changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
> index 1a4ef9cd9d5f..b192234096b6 100644
> --- a/tools/perf/builtin-kvm.c
> +++ b/tools/perf/builtin-kvm.c
> @@ -921,15 +921,8 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
>   	signal(SIGINT, sig_handler);
>   	signal(SIGTERM, sig_handler);
>
> -	/* copy pollfds -- need to add timerfd and stdin */
> +	/* use pollfds -- need to add timerfd and stdin */
>   	nr_fds = kvm->evlist->nr_fds;
> -	pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
> -	if (!pollfds) {
> -		err = -ENOMEM;
> -		goto out;
> -	}
> -	memcpy(pollfds, kvm->evlist->pollfd,
> -		sizeof(struct pollfd) * kvm->evlist->nr_fds);
>
>   	/* add timer fd */
>   	if (perf_kvm__timerfd_create(kvm) < 0) {
> @@ -937,17 +930,21 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
>   		goto out;
>   	}
>
> -	pollfds[nr_fds].fd = kvm->timerfd;
> -	pollfds[nr_fds].events = POLLIN;
> +	if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd))
> +		goto out;
> +
>   	nr_fds++;
>
> -	pollfds[nr_fds].fd = fileno(stdin);
> -	pollfds[nr_fds].events = POLLIN;
> +	if (perf_evlist__add_pollfd(kvm->evlist, fileno(stdin)))
> +		goto out;
> +
>   	nr_stdin = nr_fds;
>   	nr_fds++;
>   	if (fd_set_nonblock(fileno(stdin)) != 0)
>   		goto out;
>
> +	pollfds	 = kvm->evlist->pollfd;
> +
>   	/* everything is good - enable the events and process */
>   	perf_evlist__enable(kvm->evlist);
>
> @@ -981,7 +978,6 @@ out:
>   		close(kvm->timerfd);
>
>   	tcsetattr(0, TCSAFLUSH, &save);
> -	free(pollfds);
>   	return err;
>   }
>
>

Much simpler. Looks ok to me.

Reviewed-by: David Ahern <dsahern@gmail.com>

David

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

end of thread, other threads:[~2014-08-26 14:04 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-22 20:59 [RFC 00/10] perf pollfd series Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 01/10] perf evlist: Introduce perf_evlist__filter_pollfd method Arnaldo Carvalho de Melo
2014-08-25  6:57   ` Adrian Hunter
2014-08-22 20:59 ` [PATCH 02/10] perf tests: Add test for perf_evlist__filter_pollfd() Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 03/10] perf evlist: Monitor POLLERR and POLLHUP events too Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 04/10] perf record: Filter out POLLHUP'ed file descriptors Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 05/10] perf trace: " Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 06/10] perf evlist: Allow growing pollfd on add method Arnaldo Carvalho de Melo
2014-08-25  9:41   ` Jiri Olsa
2014-08-25  9:47   ` Jiri Olsa
2014-08-25 15:59     ` Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 07/10] perf tests: Add pollfd growing test Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 08/10] perf kvm stat live: Use perf_evlist__add_pollfd() instead of local equivalent Arnaldo Carvalho de Melo
2014-08-26 14:04   ` David Ahern
2014-08-22 20:59 ` [PATCH 09/10] perf evlist: Introduce poll method for common code idiom Arnaldo Carvalho de Melo
2014-08-22 20:59 ` [PATCH 10/10] tools lib api: Adopt fdarray class from perf's evlist Arnaldo Carvalho de Melo
2014-08-26  7:46   ` Namhyung Kim
2014-08-26 13:08     ` Arnaldo Carvalho de Melo
2014-08-25 11:04 ` [RFC 00/10] perf pollfd series Jiri Olsa
2014-08-25 15:56   ` Arnaldo Carvalho de Melo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).