Message ID | 1359629644-21920-3-git-send-email-stefanha@redhat.com |
---|---|
State | New |
Headers | show |
Stefan Hajnoczi <stefanha@redhat.com> writes: > QEMU currently uses select(2)-style rfds/wfds/xfds for file descriptor > event polling. Unfortunately the underlying fd_set type and its macros > (FD_SET()) have a hardcoded maximum for file descriptors. It is > possible to exceed this limit so we need a more scalable event polling > structure. > > Poller is a growable array of GPollFDs that will allow us to use > g_poll(3) instead of select(2) in the future. > > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> How about using a GArray instead? Regards, Anthony Liguori > --- > include/qemu/poller.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ > util/Makefile.objs | 1 + > util/poller.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 111 insertions(+) > create mode 100644 include/qemu/poller.h > create mode 100644 util/poller.c > > diff --git a/include/qemu/poller.h b/include/qemu/poller.h > new file mode 100644 > index 0000000..7630099 > --- /dev/null > +++ b/include/qemu/poller.h > @@ -0,0 +1,56 @@ > +/* > + * Growable GPollFD arrays > + * > + * Copyright 2013 Red Hat, Inc. and/or its affiliates > + * > + * Authors: > + * Stefan Hajnoczi <stefanha@redhat.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2 or later. > + * See the COPYING.LIB file in the top-level directory. > + * > + */ > + > +#ifndef QEMU_POLLER_H > +#define QEMU_POLLER_H > + > +#include "qemu-common.h" > + > +typedef struct { > + GPollFD *poll_fds; > + int nfds; > + int max; > +} Poller; > + > +void poller_init(Poller *p); > +void poller_cleanup(Poller *p); > + > +/** > + * poller_reset: Forget all added file descriptors > + */ > +void poller_reset(Poller *p); > + > +/** > + * poller_add_fd: Enable event polling on a file descriptor > + * > + * Called by *_fill() functions that are invoked by the main loop to enable > + * event polling on file descriptors that they care about. The results can be > + * fetched with poller_get_revents() when the corresponding *_poll() function > + * is invoked by the main loop. > + * > + * Return an index that can be used with poller_get_revents(). > + * > + * @events: GIOCondition (G_IO_IN, G_IO_OUT, etc) bitmask > + */ > +int poller_add_fd(Poller *p, int fd, int events); > + > +/** > + * poller_get_revents: Fetch event polling results for an added file descriptor > + * > + * Return the GIOCondition (G_IO_IN, G_IO_OUT, etc) bitmask. > + * > + * @index: Return value from poller_add_fd(). This is not an fd! > + */ > +int poller_get_revents(Poller *p, int index); > + > +#endif /* QEMU_POLLER_H */ > diff --git a/util/Makefile.objs b/util/Makefile.objs > index 495a178..7ff18d6 100644 > --- a/util/Makefile.objs > +++ b/util/Makefile.objs > @@ -8,3 +8,4 @@ util-obj-y += error.o qemu-error.o > util-obj-$(CONFIG_POSIX) += compatfd.o > util-obj-y += iov.o aes.o qemu-config.o qemu-sockets.o uri.o notify.o > util-obj-y += qemu-option.o qemu-progress.o > +util-obj-y += poller.o > diff --git a/util/poller.c b/util/poller.c > new file mode 100644 > index 0000000..663e7a9 > --- /dev/null > +++ b/util/poller.c > @@ -0,0 +1,54 @@ > +/* > + * Growable GPollFD arrays > + * > + * Copyright 2013 Red Hat, Inc. and/or its affiliates > + * > + * Authors: > + * Stefan Hajnoczi <stefanha@redhat.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2 or later. > + * See the COPYING.LIB file in the top-level directory. > + * > + */ > + > +#include <assert.h> > +#include <string.h> > +#include "qemu/poller.h" > + > +void poller_init(Poller *p) > +{ > + memset(p, 0, sizeof(*p)); > +} > + > +void poller_cleanup(Poller *p) > +{ > + g_free(p->poll_fds); > +} > + > +void poller_reset(Poller *p) > +{ > + p->nfds = 0; > +} > + > +int poller_add_fd(Poller *p, int fd, int events) > +{ > + int index; > + > + index = p->nfds++; > + if (index >= p->max) { > + p->max += 64; /* avoid constant reallocation */ > + p->poll_fds = g_realloc(p->poll_fds, p->max * sizeof(p->poll_fds[0])); > + } > + > + p->poll_fds[index] = (GPollFD){ > + .fd = fd, > + .events = events, > + }; > + return index; > +} > + > +int poller_get_revents(Poller *p, int index) > +{ > + assert(index < p->nfds); > + return p->poll_fds[index].revents; > +} > -- > 1.8.1
On Thu, Jan 31, 2013 at 06:56:56AM -0600, Anthony Liguori wrote: > Stefan Hajnoczi <stefanha@redhat.com> writes: > > > QEMU currently uses select(2)-style rfds/wfds/xfds for file descriptor > > event polling. Unfortunately the underlying fd_set type and its macros > > (FD_SET()) have a hardcoded maximum for file descriptors. It is > > possible to exceed this limit so we need a more scalable event polling > > structure. > > > > Poller is a growable array of GPollFDs that will allow us to use > > g_poll(3) instead of select(2) in the future. > > > > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> > > How about using a GArray instead? g_poll(3) needs a contiguous array of GPollFD structs. I can't see how GArray can provide that - it seems to only work if you're using g_array_*() accessor functions and doesn't give you a contiguous C array. Stefan
Stefan Hajnoczi <stefanha@redhat.com> writes: > On Thu, Jan 31, 2013 at 06:56:56AM -0600, Anthony Liguori wrote: >> Stefan Hajnoczi <stefanha@redhat.com> writes: >> >> > QEMU currently uses select(2)-style rfds/wfds/xfds for file descriptor >> > event polling. Unfortunately the underlying fd_set type and its macros >> > (FD_SET()) have a hardcoded maximum for file descriptors. It is >> > possible to exceed this limit so we need a more scalable event polling >> > structure. >> > >> > Poller is a growable array of GPollFDs that will allow us to use >> > g_poll(3) instead of select(2) in the future. >> > >> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> >> >> How about using a GArray instead? > > g_poll(3) needs a contiguous array of GPollFD structs. I can't see how > GArray can provide that - it seems to only work if you're using > g_array_*() accessor functions and doesn't give you a contiguous C > array. The data member is public and points to the start of the array. So you can just pass array->data. Regards, Anthony Liguori > > Stefan
diff --git a/include/qemu/poller.h b/include/qemu/poller.h new file mode 100644 index 0000000..7630099 --- /dev/null +++ b/include/qemu/poller.h @@ -0,0 +1,56 @@ +/* + * Growable GPollFD arrays + * + * Copyright 2013 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi <stefanha@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef QEMU_POLLER_H +#define QEMU_POLLER_H + +#include "qemu-common.h" + +typedef struct { + GPollFD *poll_fds; + int nfds; + int max; +} Poller; + +void poller_init(Poller *p); +void poller_cleanup(Poller *p); + +/** + * poller_reset: Forget all added file descriptors + */ +void poller_reset(Poller *p); + +/** + * poller_add_fd: Enable event polling on a file descriptor + * + * Called by *_fill() functions that are invoked by the main loop to enable + * event polling on file descriptors that they care about. The results can be + * fetched with poller_get_revents() when the corresponding *_poll() function + * is invoked by the main loop. + * + * Return an index that can be used with poller_get_revents(). + * + * @events: GIOCondition (G_IO_IN, G_IO_OUT, etc) bitmask + */ +int poller_add_fd(Poller *p, int fd, int events); + +/** + * poller_get_revents: Fetch event polling results for an added file descriptor + * + * Return the GIOCondition (G_IO_IN, G_IO_OUT, etc) bitmask. + * + * @index: Return value from poller_add_fd(). This is not an fd! + */ +int poller_get_revents(Poller *p, int index); + +#endif /* QEMU_POLLER_H */ diff --git a/util/Makefile.objs b/util/Makefile.objs index 495a178..7ff18d6 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -8,3 +8,4 @@ util-obj-y += error.o qemu-error.o util-obj-$(CONFIG_POSIX) += compatfd.o util-obj-y += iov.o aes.o qemu-config.o qemu-sockets.o uri.o notify.o util-obj-y += qemu-option.o qemu-progress.o +util-obj-y += poller.o diff --git a/util/poller.c b/util/poller.c new file mode 100644 index 0000000..663e7a9 --- /dev/null +++ b/util/poller.c @@ -0,0 +1,54 @@ +/* + * Growable GPollFD arrays + * + * Copyright 2013 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Hajnoczi <stefanha@redhat.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include <assert.h> +#include <string.h> +#include "qemu/poller.h" + +void poller_init(Poller *p) +{ + memset(p, 0, sizeof(*p)); +} + +void poller_cleanup(Poller *p) +{ + g_free(p->poll_fds); +} + +void poller_reset(Poller *p) +{ + p->nfds = 0; +} + +int poller_add_fd(Poller *p, int fd, int events) +{ + int index; + + index = p->nfds++; + if (index >= p->max) { + p->max += 64; /* avoid constant reallocation */ + p->poll_fds = g_realloc(p->poll_fds, p->max * sizeof(p->poll_fds[0])); + } + + p->poll_fds[index] = (GPollFD){ + .fd = fd, + .events = events, + }; + return index; +} + +int poller_get_revents(Poller *p, int index) +{ + assert(index < p->nfds); + return p->poll_fds[index].revents; +}
QEMU currently uses select(2)-style rfds/wfds/xfds for file descriptor event polling. Unfortunately the underlying fd_set type and its macros (FD_SET()) have a hardcoded maximum for file descriptors. It is possible to exceed this limit so we need a more scalable event polling structure. Poller is a growable array of GPollFDs that will allow us to use g_poll(3) instead of select(2) in the future. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> --- include/qemu/poller.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ util/Makefile.objs | 1 + util/poller.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 include/qemu/poller.h create mode 100644 util/poller.c