From 639eb400354dc5b69deb17f20a52e0045f6e93e4 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 17 Sep 2006 10:41:06 +0000 Subject: [PATCH] Added support for the /dev/poll i/o interface. --- configure.in | 35 +++++++++---- src/ngircd/io.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 149 insertions(+), 14 deletions(-) diff --git a/configure.in b/configure.in index 2381916b..dcb040c1 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.122 2006/09/16 15:00:09 fw Exp $ +# $Id: configure.in,v 1.123 2006/09/17 10:41:06 fw Exp $ # # -- Initialisation -- @@ -199,7 +199,7 @@ if test "$x_zlib_on" = "yes"; then fi -x_io_backend=select +x_io_backend=select\(\) AC_ARG_WITH(poll, [ --without-poll disable poll support (autodetected by default)], [ if test "$withval" != "no"; then @@ -208,17 +208,34 @@ AC_ARG_WITH(poll, CPPFLAGS="-I$withval/include $CPPFLAGS" LDFLAGS="-L$withval/lib $LDFLAGS" fi - AC_CHECK_FUNCS(poll, x_io_backend=poll, + 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_CHECK_FUNCS(poll, x_io_backend=poll\(\)) ] ) +AC_ARG_WITH(devpoll, + [ --without-devpoll disable /dev/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_HEADERS(sys/devpoll.h,,AC_MSG_ERROR([required C header missing!])) + fi + ], + [ + AC_CHECK_HEADERS(sys/devpoll.h,x_io_backend=/dev/poll,) + ] +) + AC_ARG_WITH(epoll, [ --without-epoll disable epoll support (autodetected by default)], [ if test "$withval" != "no"; then @@ -227,13 +244,13 @@ AC_ARG_WITH(epoll, CPPFLAGS="-I$withval/include $CPPFLAGS" LDFLAGS="-L$withval/lib $LDFLAGS" fi - AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll, + AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll\(\), AC_MSG_ERROR([Can't enable epoll support!]) ) fi ], [ - AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll) + AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll\(\)) ] ) @@ -246,13 +263,13 @@ AC_ARG_WITH(kqueue, CPPFLAGS="-I$withval/include $CPPFLAGS" LDFLAGS="-L$withval/lib $LDFLAGS" fi - AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue, + AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\), AC_MSG_ERROR([Can't enable kqueue support!]) ) fi ], [ - AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue) + AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\)) ] ) @@ -502,7 +519,7 @@ test "$x_identauth_on" = "yes" \ && echo $ECHO_N "yes $ECHO_C" \ || echo $ECHO_N "no $ECHO_C" echo $ECHO_N " I/O backend: $ECHO_C" - echo "\"$x_io_backend()\"" + echo "\"$x_io_backend\"" echo diff --git a/src/ngircd/io.c b/src/ngircd/io.c index 147fe662..fb3ebd8e 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.19 2006/09/16 16:47:27 fw Exp $"; +static char UNUSED id[] = "$Id: io.c,v 1.20 2006/09/17 10:41:07 fw Exp $"; #include #include @@ -43,11 +43,15 @@ typedef struct { # ifdef HAVE_KQUEUE #define IO_USE_KQUEUE 1 # else -# ifdef HAVE_POLL -#define IO_USE_POLL 1 +# ifdef HAVE_SYS_DEVPOLL_H +#define IO_USE_DEVPOLL 1 # else +# ifdef HAVE_POLL +#define IO_USE_POLL 1 +# else #define IO_USE_SELECT 1 -# endif /* HAVE_POLL */ +# endif /* HAVE_POLL */ +# endif /* HAVE_SYS_DEVPOLL_H */ # endif /* HAVE_KQUEUE */ #endif /* HAVE_EPOLL_CREATE */ @@ -73,12 +77,20 @@ static bool io_event_change_kqueue(int, short, const int action); #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_DEVPOLL +#include +static int io_masterfd; + +static bool io_event_change_devpoll(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) */ @@ -110,6 +122,19 @@ io_event_get(int fd) } +#ifdef IO_USE_DEVPOLL +static void +io_library_init_devpoll(unsigned int eventsize) +{ + io_masterfd = open("/dev/poll", O_RDWR); + if (io_masterfd >= 0) + library_initialized = true; + Log(LOG_INFO, "IO subsystem: /dev/poll (initial maxfd %u, masterfd %d).", + eventsize, io_masterfd); +} +#endif + + #ifdef IO_USE_POLL static void io_library_init_poll(unsigned int eventsize) @@ -208,6 +233,9 @@ io_library_init(unsigned int eventsize) #ifdef IO_USE_KQUEUE io_library_init_kqueue(eventsize); #endif +#ifdef IO_USE_DEVPOLL + io_library_init_devpoll(eventsize); +#endif #ifdef IO_USE_POLL io_library_init_poll(eventsize); #endif @@ -275,6 +303,9 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short)) i->callback = cbfunc; i->what = 0; +#ifdef IO_USE_DEVPOLL + ret = io_event_change_devpoll(fd, what); +#endif #ifdef IO_USE_POLL ret = io_event_change_poll(fd, what); #endif @@ -292,6 +323,26 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short)) } +#ifdef IO_USE_DEVPOLL +static bool +io_event_change_devpoll(int fd, short what) +{ + struct pollfd p; + + p.events = 0; + + if (what & IO_WANTREAD) + p.events = POLLIN | POLLPRI; + if (what & IO_WANTWRITE) + p.events |= POLLOUT; + + p.fd = fd; + return write(io_masterfd, &p, sizeof p) == (ssize_t)sizeof p; +} +#endif + + + #ifdef IO_USE_POLL static bool io_event_change_poll(int fd, short what) @@ -405,6 +456,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_DEVPOLL + return io_event_change_devpoll(fd, i->what); +#endif #ifdef IO_USE_POLL return io_event_change_poll(fd, i->what); #endif @@ -438,6 +492,21 @@ io_setnonblock(int fd) } +#ifdef IO_USE_DEVPOLL +static void +io_close_devpoll(int fd) +{ + struct pollfd p; + p.events = POLLREMOVE; + p.fd = fd; + write(io_masterfd, &p, sizeof p); +} +#else +static inline void io_close_devpoll(int UNUSED x) { /* NOTHING */ } +#endif + + + #ifdef IO_USE_POLL static void io_close_poll(int fd) @@ -455,7 +524,6 @@ io_close_poll(int fd) break; } } -} #else static inline void io_close_poll(int UNUSED x) { /* NOTHING */ } #endif @@ -504,6 +572,7 @@ io_close(int fd) } #endif + io_close_devpoll(fd); io_close_poll(fd); io_close_select(fd); @@ -529,6 +598,9 @@ io_event_del(int fd, short what) i->what &= ~what; +#ifdef IO_USE_DEVPOLL + return io_event_change_devpoll(fd, i->what); +#endif #ifdef IO_USE_POLL return io_event_change_poll(fd, i->what); #endif @@ -588,6 +660,49 @@ io_dispatch_select(struct timeval *tv) #endif +#ifdef IO_USE_DEVPOLL +static int +io_dispatch_devpoll(struct timeval *tv) +{ + struct dvpoll dvp; + time_t sec = tv->tv_sec * 1000; + int i, total, ret, timeout = tv->tv_usec + sec; + short what; + struct pollfd p[100]; + + if (timeout < 0) + timeout = 1000; + + total = 0; + do { + dvp.dp_timeout = timeout; + dvp.dp_nfds = 100; + dvp.dp_fds = p; + ret = ioctl(io_masterfd, DP_POLL, &dvp); + total += ret; + if (ret <= 0) + return total; + for (i=0; i < ret ; 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; + } + io_docallback(p[i].fd, what); + } + } while (ret == 100); + + return total; +} +#endif + + #ifdef IO_USE_POLL static int io_dispatch_poll(struct timeval *tv) @@ -747,6 +862,9 @@ io_dispatch(struct timeval *tv) #ifdef IO_USE_KQUEUE return io_dispatch_kqueue(tv); #endif +#ifdef IO_USE_DEVPOLL + return io_dispatch_devpoll(tv); +#endif #ifdef IO_USE_POLL return io_dispatch_poll(tv); #endif