From 147de9dfa9aea84f7b7cd0eded7a0f07ba36ea06 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 16 Sep 2006 15:00:09 +0000 Subject: [PATCH] add support for the poll() interface --- configure.in | 22 +++++++- src/ngircd/io.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index ee45da37..2381916b 100644 --- a/configure.in +++ b/configure.in @@ -8,7 +8,7 @@ # (at your option) any later version. # Please read the file COPYING, README and AUTHORS for more information. # -# $Id: configure.in,v 1.121 2006/09/09 17:07:39 fw Exp $ +# $Id: configure.in,v 1.122 2006/09/16 15:00:09 fw Exp $ # # -- Initialisation -- @@ -200,6 +200,25 @@ fi x_io_backend=select +AC_ARG_WITH(poll, + [ --without-poll disable poll support (autodetected by default)], + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_FUNCS(poll, x_io_backend=poll, + AC_MSG_ERROR([Can't enable poll support!]) + ) + fi + ], + [ + AC_CHECK_FUNCS(poll, x_io_backend=poll) + ] +) + + AC_ARG_WITH(epoll, [ --without-epoll disable epoll support (autodetected by default)], [ if test "$withval" != "no"; then @@ -218,6 +237,7 @@ AC_ARG_WITH(epoll, ] ) + AC_ARG_WITH(kqueue, [ --without-kqueue disable kqueue support (autodetected by default)], [ if test "$withval" != "no"; then diff --git a/src/ngircd/io.c b/src/ngircd/io.c index 39b994b2..9633f6ce 100644 --- a/src/ngircd/io.c +++ b/src/ngircd/io.c @@ -12,7 +12,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: io.c,v 1.17 2006/09/16 14:49:26 fw Exp $"; +static char UNUSED id[] = "$Id: io.c,v 1.18 2006/09/16 15:00:10 fw Exp $"; #include #include @@ -43,7 +43,11 @@ typedef struct { # ifdef HAVE_KQUEUE #define IO_USE_KQUEUE 1 # else +# ifdef HAVE_POLL +#define IO_USE_POLL 1 +# else #define IO_USE_SELECT 1 +# endif /* HAVE_POLL */ # endif /* HAVE_KQUEUE */ #endif /* HAVE_EPOLL_CREATE */ @@ -67,6 +71,14 @@ static int io_dispatch_kqueue(struct timeval *tv); static bool io_event_change_kqueue(int, short, const int action); #endif +#ifdef IO_USE_POLL +#include +static array pollfds; +static int poll_maxfd; + +static bool io_event_change_poll(int fd, short what); +#endif + #ifdef IO_USE_SELECT #include "defines.h" /* for conn.h */ #include "conn.h" /* for CONN_IDX (needed by resolve.h) */ @@ -98,6 +110,29 @@ io_event_get(int fd) } +#ifdef IO_USE_POLL +static bool +io_library_init_poll(unsigned int eventsize) +{ + struct pollfd *p; + array_init(&pollfds); + poll_maxfd = 0; + Log(LOG_INFO, "IO subsystem: poll (initial maxfd %u).", + eventsize); + p = array_alloc(&pollfds, sizeof(struct pollfd), eventsize); + if (p) { + unsigned i; + p = array_start(&pollfds); + for (i = 0; i < eventsize; i++) + p[i].fd = -1; + + library_initialized = true; + } + return p != NULL; +} +#endif + + #ifdef IO_USE_SELECT static bool io_library_init_select(unsigned int eventsize) @@ -180,6 +215,9 @@ io_library_init(unsigned int eventsize) #ifdef IO_USE_KQUEUE return io_library_init_kqueue(eventsize); #endif +#ifdef IO_USE_POLL + return io_library_init_poll(eventsize); +#endif #ifdef IO_USE_SELECT return io_library_init_select(eventsize); #endif @@ -243,6 +281,9 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short)) i->callback = cbfunc; i->what = 0; +#ifdef IO_USE_POLL + ret = io_event_change_poll(fd, what); +#endif #ifdef IO_USE_EPOLL ret = io_event_change_epoll(fd, what, EPOLL_CTL_ADD); #endif @@ -257,6 +298,29 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short)) } +#ifdef IO_USE_POLL +static bool +io_event_change_poll(int fd, short what) +{ + struct pollfd *p; + short events = 0; + + if (what & IO_WANTREAD) + events = POLLIN | POLLPRI; + if (what & IO_WANTWRITE) + events |= POLLOUT; + + p = array_alloc(&pollfds, sizeof *p, fd); + if (p) { + p->events = events; + p->fd = fd; + if (fd > poll_maxfd) + poll_maxfd = fd; + } + return p != NULL; +} +#endif + #ifdef IO_USE_EPOLL static bool io_event_change_epoll(int fd, short what, const int action) @@ -347,6 +411,9 @@ io_event_add(int fd, short what) #ifdef IO_USE_KQUEUE return io_event_change_kqueue(fd, what, EV_ADD | EV_ENABLE); #endif +#ifdef IO_USE_POLL + return io_event_change_poll(fd, i->what); +#endif #ifdef IO_USE_SELECT if (fd > select_maxfd) select_maxfd = fd; @@ -377,6 +444,29 @@ io_setnonblock(int fd) } +#ifdef IO_USE_POLL +static void +io_close_poll(int fd) +{ + struct pollfd *p; + p = array_get(&pollfds, sizeof *p, fd); + if (!p) return; + + p->fd = -1; + if (fd == poll_maxfd) { + while (poll_maxfd > 0) { + --poll_maxfd; + p = array_get(&pollfds, sizeof *p, poll_maxfd); + if (p && p->fd >= 0) + break; + } + } +} +#else +static inline void io_close_poll(int UNUSED x) { /* NOTHING */ } +#endif + + #ifdef IO_USE_SELECT static void io_close_select(int fd) @@ -420,6 +510,7 @@ io_close(int fd) } #endif + io_close_poll(fd); io_close_select(fd); #ifdef IO_USE_EPOLL @@ -444,6 +535,9 @@ io_event_del(int fd, short what) i->what &= ~what; +#ifdef IO_USE_POLL + return io_event_change_poll(fd, i->what); +#endif #ifdef IO_USE_EPOLL return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD); #endif @@ -500,6 +594,49 @@ io_dispatch_select(struct timeval *tv) #endif +#ifdef IO_USE_POLL +static int +io_dispatch_poll(struct timeval *tv) +{ + time_t sec = tv->tv_sec * 1000; + int i, ret, timeout = tv->tv_usec + sec; + int fds_ready; + short what; + struct pollfd *p = array_start(&pollfds); + + if (timeout < 0) + timeout = 1000; + + ret = poll(p, poll_maxfd + 1, timeout); + if (ret <= 0) + return ret; + + fds_ready = ret; + for (i=0; i <= poll_maxfd; i++) { + what = 0; + if (p[i].revents & (POLLIN|POLLPRI)) + what = IO_WANTREAD; + + if (p[i].revents & POLLOUT) + what |= IO_WANTWRITE; + + if (p[i].revents && !what) { + /* other flag is set, probably POLLERR */ + what = IO_ERROR; + } + if (what) { + fds_ready--; + io_docallback(i, what); + } + if (fds_ready <= 0) + break; + } + + return ret; +} +#endif + + #ifdef IO_USE_EPOLL static int io_dispatch_epoll(struct timeval *tv) @@ -616,6 +753,9 @@ io_dispatch(struct timeval *tv) #ifdef IO_USE_KQUEUE return io_dispatch_kqueue(tv); #endif +#ifdef IO_USE_POLL + return io_dispatch_poll(tv); +#endif #ifdef IO_USE_EPOLL return io_dispatch_epoll(tv); #endif -- 2.39.2