commit 147de9dfa9aea84f7b7cd0eded7a0f07ba36ea06 from: Florian Westphal date: Sat Sep 16 15:00:09 2006 UTC add support for the poll() interface commit - f6e729443e6f1ef72d5687828bfe2bb327d552ac commit + 147de9dfa9aea84f7b7cd0eded7a0f07ba36ea06 blob - ee45da37c8da31c6603c1ccefe4f5b50afa78755 blob + 2381916b36d4185c91f0deba1f088c3c7c7154bd --- configure.in +++ 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 blob - 39b994b22fb67b19d41f52339e9d3f8f300ead94 blob + 9633f6cedf6eeaf7003ad0ee45abc3b1e3eaa395 --- src/ngircd/io.c +++ 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) (in 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) (in } +#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; @@ -374,7 +441,30 @@ io_setnonblock(int fd) flags |= O_NONBLOCK; return fcntl(fd, F_SETFL, flags) == 0; +} + + +#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 @@ -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 @@ -490,7 +584,50 @@ io_dispatch_select(struct timeval *tv) fds_ready--; } if (what) + io_docallback(i, what); + if (fds_ready <= 0) + break; + } + + return ret; +} +#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; } @@ -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