Skip to content

Commit

Permalink
tools lib api: Adopt fdarray class from perf's evlist
Browse files Browse the repository at this point in the history
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.

v2: Don't use {} like in:

 libapi_dirs:
	$(QUIET_MKDIR)mkdir -p $(OUTPUT){fs,fd}/

in Makefiles, as it will not work in some systems, as in ubuntu13.10.

v3: Add fd/*.[ch] to LIBAPIKFS_SOURCES (Fix from Jiri Olsa)

v4: Leave the fcntl(fd, O_NONBLOCK) in the evlist layer, remains to
    be checked if it is really needed there, but has no place in the
    fdarray class (Fix from Jiri Olsa)

v5: Remove evlist details from fdarray grow/filter tests. Improve it a
    bit doing more tests about expected internal state.

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-kleuni3hckbc3s0lu6yb9x40@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Arnaldo Carvalho de Melo committed Sep 25, 2014
1 parent f66a889 commit 1b85337
Show file tree
Hide file tree
Showing 12 changed files with 342 additions and 278 deletions.
7 changes: 6 additions & 1 deletion tools/lib/api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ LIB_OBJS=

LIB_H += fs/debugfs.h
LIB_H += fs/fs.h
# See comment below about piggybacking...
LIB_H += fd/array.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/array.o

LIBFILE = libapikfs.a

Expand All @@ -29,7 +34,7 @@ $(LIBFILE): $(LIB_OBJS)
$(LIB_OBJS): $(LIB_H)

libapi_dirs:
$(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/
$(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs

$(OUTPUT)%.o: %.c libapi_dirs
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
Expand Down
107 changes: 107 additions & 0 deletions tools/lib/api/fd/array.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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 "array.h"
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdlib.h>
#include <unistd.h>

void fdarray__init(struct fdarray *fda, int nr_autogrow)
{
fda->entries = NULL;
fda->nr = fda->nr_alloc = 0;
fda->nr_autogrow = nr_autogrow;
}

int fdarray__grow(struct fdarray *fda, int nr)
{
int nr_alloc = fda->nr_alloc + nr;
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, int nr_autogrow)
{
struct fdarray *fda = calloc(1, sizeof(*fda));

if (fda != NULL) {
if (fdarray__grow(fda, nr_alloc)) {
free(fda);
fda = NULL;
} else {
fda->nr_autogrow = nr_autogrow;
}
}

return fda;
}

void fdarray__exit(struct fdarray *fda)
{
free(fda->entries);
fdarray__init(fda, 0);
}

void fdarray__delete(struct fdarray *fda)
{
fdarray__exit(fda);
free(fda);
}

int fdarray__add(struct fdarray *fda, int fd, short revents)
{
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;
}

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

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

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

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

++nr;
}

return fda->nr = 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, " ]");
}
32 changes: 32 additions & 0 deletions tools/lib/api/fd/array.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef __API_FD_ARRAY__
#define __API_FD_ARRAY__

#include <stdio.h>

struct pollfd;

struct fdarray {
int nr;
int nr_alloc;
int nr_autogrow;
struct pollfd *entries;
};

void fdarray__init(struct fdarray *fda, int nr_autogrow);
void fdarray__exit(struct fdarray *fda);

struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow);
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__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_ARRAY__ */
4 changes: 2 additions & 2 deletions tools/perf/Makefile.perf
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,9 @@ 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/fdarray.o
LIB_OBJS += $(OUTPUT)tests/pmu.o
LIB_OBJS += $(OUTPUT)tests/hists_common.o
LIB_OBJS += $(OUTPUT)tests/hists_link.o
Expand Down Expand Up @@ -770,7 +770,7 @@ $(LIBTRACEEVENT)-clean:
install-traceevent-plugins: $(LIBTRACEEVENT)
$(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins

LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch])
LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch])

# if subdir is set, we've been called from above so target has been built
# already
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,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) {
Expand All @@ -941,7 +941,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);
Expand Down
8 changes: 4 additions & 4 deletions tools/perf/tests/builtin-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ static struct test {
.func = test__switch_tracking,
},
{
.desc = "Filter fds with revents mask in a pollfd array",
.func = test__perf_evlist__filter_pollfd,
.desc = "Filter fds with revents mask in a fdarray",
.func = test__fdarray__filter,
},
{
.desc = "Add fd to pollfd array, making it autogrow",
.func = test__perf_evlist__add_pollfd,
.desc = "Add fd to a fdarray, making it autogrow",
.func = test__fdarray__add,
},
{
.func = NULL,
Expand Down
Loading

0 comments on commit 1b85337

Please sign in to comment.