diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-09-03 17:02:59 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-09-25 15:46:55 -0400 |
| commit | 1b85337d0685d1dc5a6f9061434ba4316d69f3b8 (patch) | |
| tree | 2aae4189996ae07c65c8aaa2fc205ceba58cc7fb /tools/lib | |
| parent | f66a889dbc96dd342c87232d74f0956076707746 (diff) | |
tools lib api: Adopt fdarray class from perf's evlist
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>
Diffstat (limited to 'tools/lib')
| -rw-r--r-- | tools/lib/api/Makefile | 7 | ||||
| -rw-r--r-- | tools/lib/api/fd/array.c | 107 | ||||
| -rw-r--r-- | tools/lib/api/fd/array.h | 32 |
3 files changed, 145 insertions, 1 deletions
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile index ce00f7ee6455..36c08b1f4afb 100644 --- a/tools/lib/api/Makefile +++ b/tools/lib/api/Makefile | |||
| @@ -10,9 +10,14 @@ LIB_OBJS= | |||
| 10 | 10 | ||
| 11 | LIB_H += fs/debugfs.h | 11 | LIB_H += fs/debugfs.h |
| 12 | LIB_H += fs/fs.h | 12 | LIB_H += fs/fs.h |
| 13 | # See comment below about piggybacking... | ||
| 14 | LIB_H += fd/array.h | ||
| 13 | 15 | ||
| 14 | LIB_OBJS += $(OUTPUT)fs/debugfs.o | 16 | LIB_OBJS += $(OUTPUT)fs/debugfs.o |
| 15 | LIB_OBJS += $(OUTPUT)fs/fs.o | 17 | LIB_OBJS += $(OUTPUT)fs/fs.o |
| 18 | # XXX piggybacking here, need to introduce libapikfd, or rename this | ||
| 19 | # to plain libapik.a and make it have it all api goodies | ||
| 20 | LIB_OBJS += $(OUTPUT)fd/array.o | ||
| 16 | 21 | ||
| 17 | LIBFILE = libapikfs.a | 22 | LIBFILE = libapikfs.a |
| 18 | 23 | ||
| @@ -29,7 +34,7 @@ $(LIBFILE): $(LIB_OBJS) | |||
| 29 | $(LIB_OBJS): $(LIB_H) | 34 | $(LIB_OBJS): $(LIB_H) |
| 30 | 35 | ||
| 31 | libapi_dirs: | 36 | libapi_dirs: |
| 32 | $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/ | 37 | $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs |
| 33 | 38 | ||
| 34 | $(OUTPUT)%.o: %.c libapi_dirs | 39 | $(OUTPUT)%.o: %.c libapi_dirs |
| 35 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< | 40 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< |
diff --git a/tools/lib/api/fd/array.c b/tools/lib/api/fd/array.c new file mode 100644 index 000000000000..4889c7d42961 --- /dev/null +++ b/tools/lib/api/fd/array.c | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> | ||
| 3 | * | ||
| 4 | * Released under the GPL v2. (and only v2, not any later version) | ||
| 5 | */ | ||
| 6 | #include "array.h" | ||
| 7 | #include <errno.h> | ||
| 8 | #include <fcntl.h> | ||
| 9 | #include <poll.h> | ||
| 10 | #include <stdlib.h> | ||
| 11 | #include <unistd.h> | ||
| 12 | |||
| 13 | void fdarray__init(struct fdarray *fda, int nr_autogrow) | ||
| 14 | { | ||
| 15 | fda->entries = NULL; | ||
| 16 | fda->nr = fda->nr_alloc = 0; | ||
| 17 | fda->nr_autogrow = nr_autogrow; | ||
| 18 | } | ||
| 19 | |||
| 20 | int fdarray__grow(struct fdarray *fda, int nr) | ||
| 21 | { | ||
| 22 | int nr_alloc = fda->nr_alloc + nr; | ||
| 23 | size_t size = sizeof(struct pollfd) * nr_alloc; | ||
| 24 | struct pollfd *entries = realloc(fda->entries, size); | ||
| 25 | |||
| 26 | if (entries == NULL) | ||
| 27 | return -ENOMEM; | ||
| 28 | |||
| 29 | fda->nr_alloc = nr_alloc; | ||
| 30 | fda->entries = entries; | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | |||
| 34 | struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow) | ||
| 35 | { | ||
| 36 | struct fdarray *fda = calloc(1, sizeof(*fda)); | ||
| 37 | |||
| 38 | if (fda != NULL) { | ||
| 39 | if (fdarray__grow(fda, nr_alloc)) { | ||
| 40 | free(fda); | ||
| 41 | fda = NULL; | ||
| 42 | } else { | ||
| 43 | fda->nr_autogrow = nr_autogrow; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | return fda; | ||
| 48 | } | ||
| 49 | |||
| 50 | void fdarray__exit(struct fdarray *fda) | ||
| 51 | { | ||
| 52 | free(fda->entries); | ||
| 53 | fdarray__init(fda, 0); | ||
| 54 | } | ||
| 55 | |||
| 56 | void fdarray__delete(struct fdarray *fda) | ||
| 57 | { | ||
| 58 | fdarray__exit(fda); | ||
| 59 | free(fda); | ||
| 60 | } | ||
| 61 | |||
| 62 | int fdarray__add(struct fdarray *fda, int fd, short revents) | ||
| 63 | { | ||
| 64 | if (fda->nr == fda->nr_alloc && | ||
| 65 | fdarray__grow(fda, fda->nr_autogrow) < 0) | ||
| 66 | return -ENOMEM; | ||
| 67 | |||
| 68 | fda->entries[fda->nr].fd = fd; | ||
| 69 | fda->entries[fda->nr].events = revents; | ||
| 70 | fda->nr++; | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | int fdarray__filter(struct fdarray *fda, short revents) | ||
| 75 | { | ||
| 76 | int fd, nr = 0; | ||
| 77 | |||
| 78 | if (fda->nr == 0) | ||
| 79 | return 0; | ||
| 80 | |||
| 81 | for (fd = 0; fd < fda->nr; ++fd) { | ||
| 82 | if (fda->entries[fd].revents & revents) | ||
| 83 | continue; | ||
| 84 | |||
| 85 | if (fd != nr) | ||
| 86 | fda->entries[nr] = fda->entries[fd]; | ||
| 87 | |||
| 88 | ++nr; | ||
| 89 | } | ||
| 90 | |||
| 91 | return fda->nr = nr; | ||
| 92 | } | ||
| 93 | |||
| 94 | int fdarray__poll(struct fdarray *fda, int timeout) | ||
| 95 | { | ||
| 96 | return poll(fda->entries, fda->nr, timeout); | ||
| 97 | } | ||
| 98 | |||
| 99 | int fdarray__fprintf(struct fdarray *fda, FILE *fp) | ||
| 100 | { | ||
| 101 | int fd, printed = fprintf(fp, "%d [ ", fda->nr); | ||
| 102 | |||
| 103 | for (fd = 0; fd < fda->nr; ++fd) | ||
| 104 | printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd); | ||
| 105 | |||
| 106 | return printed + fprintf(fp, " ]"); | ||
| 107 | } | ||
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h new file mode 100644 index 000000000000..de38361ba69e --- /dev/null +++ b/tools/lib/api/fd/array.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | #ifndef __API_FD_ARRAY__ | ||
| 2 | #define __API_FD_ARRAY__ | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | |||
| 6 | struct pollfd; | ||
| 7 | |||
| 8 | struct fdarray { | ||
| 9 | int nr; | ||
| 10 | int nr_alloc; | ||
| 11 | int nr_autogrow; | ||
| 12 | struct pollfd *entries; | ||
| 13 | }; | ||
| 14 | |||
| 15 | void fdarray__init(struct fdarray *fda, int nr_autogrow); | ||
| 16 | void fdarray__exit(struct fdarray *fda); | ||
| 17 | |||
| 18 | struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow); | ||
| 19 | void fdarray__delete(struct fdarray *fda); | ||
| 20 | |||
| 21 | int fdarray__add(struct fdarray *fda, int fd, short revents); | ||
| 22 | int fdarray__poll(struct fdarray *fda, int timeout); | ||
| 23 | int fdarray__filter(struct fdarray *fda, short revents); | ||
| 24 | int fdarray__grow(struct fdarray *fda, int extra); | ||
| 25 | int fdarray__fprintf(struct fdarray *fda, FILE *fp); | ||
| 26 | |||
| 27 | static inline int fdarray__available_entries(struct fdarray *fda) | ||
| 28 | { | ||
| 29 | return fda->nr_alloc - fda->nr; | ||
| 30 | } | ||
| 31 | |||
| 32 | #endif /* __API_FD_ARRAY__ */ | ||
