commit 639eb400354dc5b69deb17f20a52e0045f6e93e4 from: Florian Westphal date: Sun Sep 17 10:41:06 2006 UTC Added support for the /dev/poll i/o interface. commit - 0d6f9d4e3ea86e083ebd5f6e71d3f1a9133468d1 commit + 639eb400354dc5b69deb17f20a52e0045f6e93e4 blob - 2381916b36d4185c91f0deba1f088c3c7c7154bd blob + dcb040c12ac73378720847b088c6bfb62c5354b2 --- 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.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 blob - 147fe66233704e47498b228d4009106a6992ad33 blob + fb3ebd8ef883e8463791ac1ed9d75edd57df6e2a --- src/ngircd/io.c +++ 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 i #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) */ @@ -107,7 +119,20 @@ io_event_get(int fd) assert(i != NULL); return i; +} + + +#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 @@ -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) (in 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 @@ -289,9 +320,29 @@ io_event_create(int fd, short what, void (*cbfunc) (in #endif if (ret) i->what = what; return ret; +} + + +#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 @@ -435,9 +489,24 @@ io_setnonblock(int fd) flags |= O_NONBLOCK; return fcntl(fd, F_SETFL, flags) == 0; +} + + +#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