diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-09-08 10:24:01 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-09-25 15:46:55 -0400 |
commit | 2171a9256862ec139a042832a9ae737b942ca882 (patch) | |
tree | 6664a28341e22f1aa0f6486b54621033047d05a9 /tools | |
parent | 82396986032915c1572bfb74b224fcc2e4e8ba7c (diff) |
tools lib fd array: Allow associating an integer cookie with each entry
We will use this in perf's evlist class so that it can, at
fdarray__filter() time, to unmap the associated ring buffer.
We may need to have further info associated with each fdarray entry, in
that case we'll make that int array a 'union fdarray_priv' one and put a
pointer there so that users can stash whatever they want there. For now,
an int is enough tho.
v2: Add clarification to the per array entry priv area, as well as make
it a union, which makes usage a bit longer, but if/when we make it
use more space by allowing per entry pointers existing users source
code will not have to be changed, just rebuilt.
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>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/n/tip-0p00bn83quck3fio3kcs9vca@git.kernel.org
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lib/api/fd/array.c | 28 | ||||
-rw-r--r-- | tools/lib/api/fd/array.h | 16 | ||||
-rw-r--r-- | tools/perf/tests/fdarray.c | 8 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 2 |
4 files changed, 44 insertions, 10 deletions
diff --git a/tools/lib/api/fd/array.c b/tools/lib/api/fd/array.c index 4889c7d42961..0e636c4339b8 100644 --- a/tools/lib/api/fd/array.c +++ b/tools/lib/api/fd/array.c | |||
@@ -13,21 +13,31 @@ | |||
13 | void fdarray__init(struct fdarray *fda, int nr_autogrow) | 13 | void fdarray__init(struct fdarray *fda, int nr_autogrow) |
14 | { | 14 | { |
15 | fda->entries = NULL; | 15 | fda->entries = NULL; |
16 | fda->priv = NULL; | ||
16 | fda->nr = fda->nr_alloc = 0; | 17 | fda->nr = fda->nr_alloc = 0; |
17 | fda->nr_autogrow = nr_autogrow; | 18 | fda->nr_autogrow = nr_autogrow; |
18 | } | 19 | } |
19 | 20 | ||
20 | int fdarray__grow(struct fdarray *fda, int nr) | 21 | int fdarray__grow(struct fdarray *fda, int nr) |
21 | { | 22 | { |
23 | void *priv; | ||
22 | int nr_alloc = fda->nr_alloc + nr; | 24 | int nr_alloc = fda->nr_alloc + nr; |
25 | size_t psize = sizeof(fda->priv[0]) * nr_alloc; | ||
23 | size_t size = sizeof(struct pollfd) * nr_alloc; | 26 | size_t size = sizeof(struct pollfd) * nr_alloc; |
24 | struct pollfd *entries = realloc(fda->entries, size); | 27 | struct pollfd *entries = realloc(fda->entries, size); |
25 | 28 | ||
26 | if (entries == NULL) | 29 | if (entries == NULL) |
27 | return -ENOMEM; | 30 | return -ENOMEM; |
28 | 31 | ||
32 | priv = realloc(fda->priv, psize); | ||
33 | if (priv == NULL) { | ||
34 | free(entries); | ||
35 | return -ENOMEM; | ||
36 | } | ||
37 | |||
29 | fda->nr_alloc = nr_alloc; | 38 | fda->nr_alloc = nr_alloc; |
30 | fda->entries = entries; | 39 | fda->entries = entries; |
40 | fda->priv = priv; | ||
31 | return 0; | 41 | return 0; |
32 | } | 42 | } |
33 | 43 | ||
@@ -50,6 +60,7 @@ struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow) | |||
50 | void fdarray__exit(struct fdarray *fda) | 60 | void fdarray__exit(struct fdarray *fda) |
51 | { | 61 | { |
52 | free(fda->entries); | 62 | free(fda->entries); |
63 | free(fda->priv); | ||
53 | fdarray__init(fda, 0); | 64 | fdarray__init(fda, 0); |
54 | } | 65 | } |
55 | 66 | ||
@@ -61,6 +72,8 @@ void fdarray__delete(struct fdarray *fda) | |||
61 | 72 | ||
62 | int fdarray__add(struct fdarray *fda, int fd, short revents) | 73 | int fdarray__add(struct fdarray *fda, int fd, short revents) |
63 | { | 74 | { |
75 | int pos = fda->nr; | ||
76 | |||
64 | if (fda->nr == fda->nr_alloc && | 77 | if (fda->nr == fda->nr_alloc && |
65 | fdarray__grow(fda, fda->nr_autogrow) < 0) | 78 | fdarray__grow(fda, fda->nr_autogrow) < 0) |
66 | return -ENOMEM; | 79 | return -ENOMEM; |
@@ -68,10 +81,11 @@ int fdarray__add(struct fdarray *fda, int fd, short revents) | |||
68 | fda->entries[fda->nr].fd = fd; | 81 | fda->entries[fda->nr].fd = fd; |
69 | fda->entries[fda->nr].events = revents; | 82 | fda->entries[fda->nr].events = revents; |
70 | fda->nr++; | 83 | fda->nr++; |
71 | return 0; | 84 | return pos; |
72 | } | 85 | } |
73 | 86 | ||
74 | int fdarray__filter(struct fdarray *fda, short revents) | 87 | int fdarray__filter(struct fdarray *fda, short revents, |
88 | void (*entry_destructor)(struct fdarray *fda, int fd)) | ||
75 | { | 89 | { |
76 | int fd, nr = 0; | 90 | int fd, nr = 0; |
77 | 91 | ||
@@ -79,11 +93,17 @@ int fdarray__filter(struct fdarray *fda, short revents) | |||
79 | return 0; | 93 | return 0; |
80 | 94 | ||
81 | for (fd = 0; fd < fda->nr; ++fd) { | 95 | for (fd = 0; fd < fda->nr; ++fd) { |
82 | if (fda->entries[fd].revents & revents) | 96 | if (fda->entries[fd].revents & revents) { |
97 | if (entry_destructor) | ||
98 | entry_destructor(fda, fd); | ||
99 | |||
83 | continue; | 100 | continue; |
101 | } | ||
84 | 102 | ||
85 | if (fd != nr) | 103 | if (fd != nr) { |
86 | fda->entries[nr] = fda->entries[fd]; | 104 | fda->entries[nr] = fda->entries[fd]; |
105 | fda->priv[nr] = fda->priv[fd]; | ||
106 | } | ||
87 | 107 | ||
88 | ++nr; | 108 | ++nr; |
89 | } | 109 | } |
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h index de38361ba69e..45db01818f45 100644 --- a/tools/lib/api/fd/array.h +++ b/tools/lib/api/fd/array.h | |||
@@ -5,11 +5,24 @@ | |||
5 | 5 | ||
6 | struct pollfd; | 6 | struct pollfd; |
7 | 7 | ||
8 | /** | ||
9 | * struct fdarray: Array of file descriptors | ||
10 | * | ||
11 | * @priv: Per array entry priv area, users should access just its contents, | ||
12 | * not set it to anything, as it is kept in synch with @entries, being | ||
13 | * realloc'ed, * for instance, in fdarray__{grow,filter}. | ||
14 | * | ||
15 | * I.e. using 'fda->priv[N].idx = * value' where N < fda->nr is ok, | ||
16 | * but doing 'fda->priv = malloc(M)' is not allowed. | ||
17 | */ | ||
8 | struct fdarray { | 18 | struct fdarray { |
9 | int nr; | 19 | int nr; |
10 | int nr_alloc; | 20 | int nr_alloc; |
11 | int nr_autogrow; | 21 | int nr_autogrow; |
12 | struct pollfd *entries; | 22 | struct pollfd *entries; |
23 | union { | ||
24 | int idx; | ||
25 | } *priv; | ||
13 | }; | 26 | }; |
14 | 27 | ||
15 | void fdarray__init(struct fdarray *fda, int nr_autogrow); | 28 | void fdarray__init(struct fdarray *fda, int nr_autogrow); |
@@ -20,7 +33,8 @@ void fdarray__delete(struct fdarray *fda); | |||
20 | 33 | ||
21 | int fdarray__add(struct fdarray *fda, int fd, short revents); | 34 | int fdarray__add(struct fdarray *fda, int fd, short revents); |
22 | int fdarray__poll(struct fdarray *fda, int timeout); | 35 | int fdarray__poll(struct fdarray *fda, int timeout); |
23 | int fdarray__filter(struct fdarray *fda, short revents); | 36 | int fdarray__filter(struct fdarray *fda, short revents, |
37 | void (*entry_destructor)(struct fdarray *fda, int fd)); | ||
24 | int fdarray__grow(struct fdarray *fda, int extra); | 38 | int fdarray__grow(struct fdarray *fda, int extra); |
25 | int fdarray__fprintf(struct fdarray *fda, FILE *fp); | 39 | int fdarray__fprintf(struct fdarray *fda, FILE *fp); |
26 | 40 | ||
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c index a0fea62ec368..d24b837951d4 100644 --- a/tools/perf/tests/fdarray.c +++ b/tools/perf/tests/fdarray.c | |||
@@ -36,7 +36,7 @@ int test__fdarray__filter(void) | |||
36 | } | 36 | } |
37 | 37 | ||
38 | fdarray__init_revents(fda, POLLIN); | 38 | fdarray__init_revents(fda, POLLIN); |
39 | nr_fds = fdarray__filter(fda, POLLHUP); | 39 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); |
40 | if (nr_fds != fda->nr_alloc) { | 40 | if (nr_fds != fda->nr_alloc) { |
41 | pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything", | 41 | pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything", |
42 | nr_fds, fda->nr_alloc); | 42 | nr_fds, fda->nr_alloc); |
@@ -44,7 +44,7 @@ int test__fdarray__filter(void) | |||
44 | } | 44 | } |
45 | 45 | ||
46 | fdarray__init_revents(fda, POLLHUP); | 46 | fdarray__init_revents(fda, POLLHUP); |
47 | nr_fds = fdarray__filter(fda, POLLHUP); | 47 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); |
48 | if (nr_fds != 0) { | 48 | if (nr_fds != 0) { |
49 | pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds", | 49 | pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds", |
50 | nr_fds, fda->nr_alloc); | 50 | nr_fds, fda->nr_alloc); |
@@ -57,7 +57,7 @@ int test__fdarray__filter(void) | |||
57 | 57 | ||
58 | pr_debug("\nfiltering all but fda->entries[2]:"); | 58 | pr_debug("\nfiltering all but fda->entries[2]:"); |
59 | fdarray__fprintf_prefix(fda, "before", stderr); | 59 | fdarray__fprintf_prefix(fda, "before", stderr); |
60 | nr_fds = fdarray__filter(fda, POLLHUP); | 60 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); |
61 | fdarray__fprintf_prefix(fda, " after", stderr); | 61 | fdarray__fprintf_prefix(fda, " after", stderr); |
62 | if (nr_fds != 1) { | 62 | if (nr_fds != 1) { |
63 | pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds); | 63 | pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds); |
@@ -78,7 +78,7 @@ int test__fdarray__filter(void) | |||
78 | 78 | ||
79 | pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):"); | 79 | pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):"); |
80 | fdarray__fprintf_prefix(fda, "before", stderr); | 80 | fdarray__fprintf_prefix(fda, "before", stderr); |
81 | nr_fds = fdarray__filter(fda, POLLHUP); | 81 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); |
82 | fdarray__fprintf_prefix(fda, " after", stderr); | 82 | fdarray__fprintf_prefix(fda, " after", stderr); |
83 | if (nr_fds != 2) { | 83 | if (nr_fds != 2) { |
84 | pr_debug("\nfdarray__filter()=%d != 2, should have left just two events", | 84 | pr_debug("\nfdarray__filter()=%d != 2, should have left just two events", |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index efddee5a23e9..61d18dc83e8e 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -435,7 +435,7 @@ int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) | |||
435 | 435 | ||
436 | int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) | 436 | int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) |
437 | { | 437 | { |
438 | return fdarray__filter(&evlist->pollfd, revents_and_mask); | 438 | return fdarray__filter(&evlist->pollfd, revents_and_mask, NULL); |
439 | } | 439 | } |
440 | 440 | ||
441 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout) | 441 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout) |