Skip to content

Commit

Permalink
tools lib fd array: Allow associating an integer cookie with each entry
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Arnaldo Carvalho de Melo committed Sep 25, 2014
1 parent 8239698 commit 2171a92
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 10 deletions.
28 changes: 24 additions & 4 deletions tools/lib/api/fd/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,31 @@
void fdarray__init(struct fdarray *fda, int nr_autogrow)
{
fda->entries = NULL;
fda->priv = NULL;
fda->nr = fda->nr_alloc = 0;
fda->nr_autogrow = nr_autogrow;
}

int fdarray__grow(struct fdarray *fda, int nr)
{
void *priv;
int nr_alloc = fda->nr_alloc + nr;
size_t psize = sizeof(fda->priv[0]) * nr_alloc;
size_t size = sizeof(struct pollfd) * nr_alloc;
struct pollfd *entries = realloc(fda->entries, size);

if (entries == NULL)
return -ENOMEM;

priv = realloc(fda->priv, psize);
if (priv == NULL) {
free(entries);
return -ENOMEM;
}

fda->nr_alloc = nr_alloc;
fda->entries = entries;
fda->priv = priv;
return 0;
}

Expand All @@ -50,6 +60,7 @@ struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow)
void fdarray__exit(struct fdarray *fda)
{
free(fda->entries);
free(fda->priv);
fdarray__init(fda, 0);
}

Expand All @@ -61,29 +72,38 @@ void fdarray__delete(struct fdarray *fda)

int fdarray__add(struct fdarray *fda, int fd, short revents)
{
int pos = fda->nr;

if (fda->nr == fda->nr_alloc &&
fdarray__grow(fda, fda->nr_autogrow) < 0)
return -ENOMEM;

fda->entries[fda->nr].fd = fd;
fda->entries[fda->nr].events = revents;
fda->nr++;
return 0;
return pos;
}

int fdarray__filter(struct fdarray *fda, short revents)
int fdarray__filter(struct fdarray *fda, short revents,
void (*entry_destructor)(struct fdarray *fda, int fd))
{
int fd, nr = 0;

if (fda->nr == 0)
return 0;

for (fd = 0; fd < fda->nr; ++fd) {
if (fda->entries[fd].revents & revents)
if (fda->entries[fd].revents & revents) {
if (entry_destructor)
entry_destructor(fda, fd);

continue;
}

if (fd != nr)
if (fd != nr) {
fda->entries[nr] = fda->entries[fd];
fda->priv[nr] = fda->priv[fd];
}

++nr;
}
Expand Down
16 changes: 15 additions & 1 deletion tools/lib/api/fd/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,24 @@

struct pollfd;

/**
* struct fdarray: Array of file descriptors
*
* @priv: Per array entry priv area, users should access just its contents,
* not set it to anything, as it is kept in synch with @entries, being
* realloc'ed, * for instance, in fdarray__{grow,filter}.
*
* I.e. using 'fda->priv[N].idx = * value' where N < fda->nr is ok,
* but doing 'fda->priv = malloc(M)' is not allowed.
*/
struct fdarray {
int nr;
int nr_alloc;
int nr_autogrow;
struct pollfd *entries;
union {
int idx;
} *priv;
};

void fdarray__init(struct fdarray *fda, int nr_autogrow);
Expand All @@ -20,7 +33,8 @@ void fdarray__delete(struct fdarray *fda);

int fdarray__add(struct fdarray *fda, int fd, short revents);
int fdarray__poll(struct fdarray *fda, int timeout);
int fdarray__filter(struct fdarray *fda, short revents);
int fdarray__filter(struct fdarray *fda, short revents,
void (*entry_destructor)(struct fdarray *fda, int fd));
int fdarray__grow(struct fdarray *fda, int extra);
int fdarray__fprintf(struct fdarray *fda, FILE *fp);

Expand Down
8 changes: 4 additions & 4 deletions tools/perf/tests/fdarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ int test__fdarray__filter(void)
}

fdarray__init_revents(fda, POLLIN);
nr_fds = fdarray__filter(fda, POLLHUP);
nr_fds = fdarray__filter(fda, POLLHUP, NULL);
if (nr_fds != fda->nr_alloc) {
pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything",
nr_fds, fda->nr_alloc);
goto out_delete;
}

fdarray__init_revents(fda, POLLHUP);
nr_fds = fdarray__filter(fda, POLLHUP);
nr_fds = fdarray__filter(fda, POLLHUP, NULL);
if (nr_fds != 0) {
pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds",
nr_fds, fda->nr_alloc);
Expand All @@ -57,7 +57,7 @@ int test__fdarray__filter(void)

pr_debug("\nfiltering all but fda->entries[2]:");
fdarray__fprintf_prefix(fda, "before", stderr);
nr_fds = fdarray__filter(fda, POLLHUP);
nr_fds = fdarray__filter(fda, POLLHUP, NULL);
fdarray__fprintf_prefix(fda, " after", stderr);
if (nr_fds != 1) {
pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds);
Expand All @@ -78,7 +78,7 @@ int test__fdarray__filter(void)

pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):");
fdarray__fprintf_prefix(fda, "before", stderr);
nr_fds = fdarray__filter(fda, POLLHUP);
nr_fds = fdarray__filter(fda, POLLHUP, NULL);
fdarray__fprintf_prefix(fda, " after", stderr);
if (nr_fds != 2) {
pr_debug("\nfdarray__filter()=%d != 2, should have left just two events",
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)

int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
{
return fdarray__filter(&evlist->pollfd, revents_and_mask);
return fdarray__filter(&evlist->pollfd, revents_and_mask, NULL);
}

int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
Expand Down

0 comments on commit 2171a92

Please sign in to comment.