--------------------- PatchSet 11479 Date: 2007/06/22 12:07:34 Author: adrian Branch: SQUID_2_6 Tag: (none) Log: Author: Adrian Chadd Bring over Solaris/IRIX /dev/poll network IO support from Squid-2, enabled by compiling with --enable-devpoll This includes a number of changes: * add commloop layer open/close hooks, so events can be properly deleted * add in an "OK" implementation of /dev/poll. its not as optimal as it could be but its not overly naive. It should perform fine. * It currently doesn't autodetect /dev/poll support - you need to compile squid with --enable-devpoll. Members: configure.in:1.416.2.12->1.416.2.13 src/Makefile.am:1.56.2.1->1.56.2.2 src/comm_devpoll.c:NEW->1.3.2.1 src/comm_epoll.c:1.27->1.27.2.1 src/comm_kqueue.c:1.10.2.1->1.10.2.2 src/comm_poll.c:1.23->1.23.2.1 src/comm_select.c:1.80->1.80.2.1 src/comm_select_simple.c:1.3->1.3.2.1 src/comm_select_win32.c:1.7->1.7.2.1 src/fd.c:1.55->1.55.2.1 src/protos.h:1.520.2.1->1.520.2.2 Index: squid/configure.in =================================================================== RCS file: /cvsroot/squid/squid/configure.in,v retrieving revision 1.416.2.12 retrieving revision 1.416.2.13 diff -u -r1.416.2.12 -r1.416.2.13 --- squid/configure.in 3 Jun 2007 00:51:15 -0000 1.416.2.12 +++ squid/configure.in 22 Jun 2007 12:07:34 -0000 1.416.2.13 @@ -1,7 +1,7 @@ dnl dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.416.2.12 2007/06/03 00:51:15 hno Exp $ +dnl $Id: configure.in,v 1.416.2.13 2007/06/22 12:07:34 adrian Exp $ dnl dnl dnl @@ -10,7 +10,7 @@ AM_CONFIG_HEADER(include/autoconf.h) AC_CONFIG_AUX_DIR(cfgaux) AM_INIT_AUTOMAKE -AC_REVISION($Revision: 1.416.2.12 $)dnl +AC_REVISION($Revision: 1.416.2.13 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -927,6 +927,27 @@ esac ]) +dnl Enable devpoll +AC_ARG_ENABLE(devpoll, +[ --enable-devpoll Force the use of devpoll even if automatic checks + indicate devpoll may not be supported. + --disable-devpoll Disable devpoll support. ], + +[ + case "$enableval" in + yes) + echo "Forcing devpoll to be enabled" + SELECT_TYPE="devpoll" + ac_cv_func_devpoll='yes' + ;; + no) + echo "Forcing devpoll to be disabled" + ac_cv_func_devpoll='no' + ;; + esac +]) + + dnl Disable HTTP violations HTTP_VIOLATIONS=1 AC_ARG_ENABLE(http-violations, @@ -2428,6 +2449,8 @@ AM_CONDITIONAL([USE_SELECT_SIMPLE], [test $SELECT_TYPE = select_simple]) AM_CONDITIONAL([USE_SELECT_WIN32], [test $SELECT_TYPE = select_win32]) AM_CONDITIONAL([USE_KQUEUE], [test $SELECT_TYPE = kqueue]) +AM_CONDITIONAL([USE_DEVPOLL], [test $SELECT_TYPE = devpoll]) + dnl Hmm.. some OS:es (i.e. FreeBSD) can't handle large AF_UNIX dgram packets. dnl Verify that at least 16K is supported, if not fall back on using Index: squid/src/Makefile.am =================================================================== RCS file: /cvsroot/squid/squid/src/Makefile.am,v retrieving revision 1.56.2.1 retrieving revision 1.56.2.2 diff -u -r1.56.2.1 -r1.56.2.2 --- squid/src/Makefile.am 5 May 2007 22:06:55 -0000 1.56.2.1 +++ squid/src/Makefile.am 22 Jun 2007 12:07:35 -0000 1.56.2.2 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.56.2.1 2007/05/05 22:06:55 hno Exp $ +# $Id: Makefile.am,v 1.56.2.2 2007/06/22 12:07:35 adrian Exp $ # # Uncomment and customize the following to suit your needs: # @@ -88,6 +88,9 @@ if USE_KQUEUE COMMLOOP_SOURCE = comm_kqueue.c endif +if USE_DEVPOLL +COMMLOOP_SOURCE = comm_devpoll.c +endif SUBDIRS = fs repl auth @@ -132,6 +135,7 @@ comm_select_win32.c \ comm_select_simple.c \ comm_kqueue.c \ + comm_devpoll.c \ comm_generic.c \ ipc.c \ ipc_win32.c \ Index: squid/src/comm_devpoll.c diff -u /dev/null squid/src/comm_devpoll.c:1.3.2.1 --- /dev/null Tue Jul 17 14:45:31 2007 +++ squid/src/comm_devpoll.c Fri Jun 22 06:07:35 2007 @@ -0,0 +1,243 @@ + +/* + * $Id: comm_devpoll.c,v 1.3.2.1 2007/06/22 12:07:35 adrian Exp $ + * + * DEBUG: section 5 Socket Functions + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "comm_generic.c" + +#include + +#define STATE_READ 1 +#define STATE_WRITE 2 + + +static int devpoll_fd; +static struct timespec zero_timespec; + +/* + * This is a very simple driver for Solaris /dev/poll. + * + * The updates are batched, one trip through the comm loop. + * (like libevent.) We keep a pointer into the structs so we + * can zero out an entry in the poll list if its active. + */ + +struct _devpoll_state { + char state; + int offset; +}; + +struct _devpoll_events { + int ds_used; + int ds_size; + struct pollfd *events; +}; + +static struct _devpoll_state *devpoll_state; +static struct _devpoll_events ds_events; +static struct dvpoll do_poll; +static int dpoll_nfds; + +static void +do_select_init() +{ + devpoll_fd = open("/dev/poll", O_RDWR); + if (devpoll_fd < 0) + fatalf("comm_select_init: can't open /dev/poll: %s\n", xstrerror()); + + zero_timespec.tv_sec = 0; + zero_timespec.tv_nsec = 0; + + /* This tracks the FD devpoll offset+state */ + devpoll_state = xcalloc(Squid_MaxFD, sizeof(struct _devpoll_state)); + + /* And this stuff is list used to submit events */ + ds_events.events = xcalloc(1024, sizeof(struct pollfd)); + ds_events.ds_used = 0; + ds_events.ds_size = 1024; + + /* And this is the stuff we use to read events */ + do_poll.dp_fds = xcalloc(1024, sizeof(struct pollfd)); + dpoll_nfds = 1024; + + fd_open(devpoll_fd, FD_UNKNOWN, "devpoll ctl"); + commSetCloseOnExec(devpoll_fd); +} + +static void +comm_submit_updates() +{ + int i; + + if (ds_events.ds_used == 0) + return; + debug(5, 5) ("comm_submit_updates: have %d updates to submit..\n", ds_events.ds_used); + i = write(devpoll_fd, ds_events.events, ds_events.ds_used * sizeof(struct pollfd)); + debug(5, 5) ("comm_submit_updates: .. and wrote %d bytes\n", i); + /* Could we handle "partial" writes? */ + assert(i == (sizeof(struct pollfd) * ds_events.ds_used)); + ds_events.ds_used = 0; + /* XXX bzero the array after? */ +} + +static void +comm_add_update(int fd, int events) +{ + debug(5, 5) ("comm_add_update: FD %d: added (%d) %s %s %s\n", fd, events, (events & POLLIN) ? "POLLIN" : "", (events & POLLOUT) ? "POLLOUT" : "", (events & POLLREMOVE) ? "POLLREMOVE" : ""); + int i = ds_events.ds_used; + ds_events.events[i].fd = fd; + ds_events.events[i].events = events; + ds_events.events[i].revents = 0; + ds_events.ds_used++; + + if (ds_events.ds_used == ds_events.ds_size) + comm_submit_updates(); +} + +void +comm_select_postinit() +{ + debug(5, 1) ("Using /dev/poll for the IO loop\n"); +} + +static void +do_select_shutdown() +{ + fd_close(devpoll_fd); + close(devpoll_fd); + devpoll_fd = -1; + xfree(devpoll_state); +} + +void +comm_select_status(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "\tIO loop method: /dev/poll\n"); +} + +void +commOpen(int fd) +{ + devpoll_state[fd].state = 0; + devpoll_state[fd].offset = 0; +} + +void +commClose(int fd) +{ + int o; + /* + * Is there a pending event in the array for this + * particular FD? Delete if so. + */ + o = devpoll_state[fd].offset; + if (devpoll_state[fd].offset <= ds_events.ds_used && fd == ds_events.events[devpoll_state[fd].offset].fd) { + ds_events.events[devpoll_state[fd].offset].events = 0; + ds_events.events[devpoll_state[fd].offset].fd = 0; + } +} + +void +commSetEvents(int fd, int need_read, int need_write) +{ + int st_new = (need_read ? STATE_READ : 0) | (need_write ? STATE_WRITE : 0); + int st_change; + int events = 0; + + debug(5, 5) ("commSetEvents(fd=%d, read=%d, write=%d)\n", fd, need_read, need_write); + + st_change = devpoll_state[fd].state ^ st_new; + if (!st_change) + return; + + if (need_read) + events |= POLLIN; + if (need_write) + events |= POLLOUT; + if (events == 0) + events |= POLLREMOVE; + + /* Is the existing poll entry ours? If so, then update it */ + if (devpoll_state[fd].offset < ds_events.ds_used && fd == ds_events.events[devpoll_state[fd].offset].fd) { + /* Just update it */ + ds_events.events[devpoll_state[fd].offset].events = events; + } else { + /* Nope, new one required */ + comm_add_update(fd, events); + } +} + +static int +do_comm_select(int msec) +{ + int i; + int num; + + statCounter.syscalls.polls++; + + comm_submit_updates(); + + do_poll.dp_timeout = msec; + do_poll.dp_nfds = dpoll_nfds; + /* dp_fds is already allocated */ + + num = ioctl(devpoll_fd, DP_POLL, &do_poll); + + if (num < 0) { + getCurrentTime(); + if (ignoreErrno(errno)) + return COMM_OK; + + debug(5, 1) ("comm_select: devpoll ioctl(DP_POLL) failure: %s\n", xstrerror()); + return COMM_ERROR; + } + statHistCount(&statCounter.select_fds_hist, num); + if (num == 0) + return COMM_TIMEOUT; + + for (i = 0; i < num; i++) { + int fd = (int) do_poll.dp_fds[i].fd; + if (do_poll.dp_fds[i].revents & POLLERR) { + debug(5, 3) ("comm_select: devpoll event error: fd %d\n", fd); + continue; /* XXX! */ + } + if (do_poll.dp_fds[i].revents & POLLIN) { + comm_call_handlers(fd, 1, 0); + } + if (do_poll.dp_fds[i].revents & POLLOUT) { + comm_call_handlers(fd, 0, 1); + } + } + + return COMM_OK; +} Index: squid/src/comm_epoll.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm_epoll.c,v retrieving revision 1.27 retrieving revision 1.27.2.1 diff -u -r1.27 -r1.27.2.1 --- squid/src/comm_epoll.c 23 Oct 2006 11:22:21 -0000 1.27 +++ squid/src/comm_epoll.c 22 Jun 2007 12:07:35 -0000 1.27.2.1 @@ -1,6 +1,6 @@ /* - * $Id: comm_epoll.c,v 1.27 2006/10/23 11:22:21 hno Exp $ + * $Id: comm_epoll.c,v 1.27.2.1 2007/06/22 12:07:35 adrian Exp $ * * DEBUG: section 5 Socket Functions * @@ -99,6 +99,17 @@ } void +commOpen(int fd) +{ +} + +void +commClose(int fd) +{ + commSetEvents(fd, 0, 0); +} + +void commSetEvents(int fd, int need_read, int need_write) { int epoll_ctl_type = 0; Index: squid/src/comm_kqueue.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm_kqueue.c,v retrieving revision 1.10.2.1 retrieving revision 1.10.2.2 diff -u -r1.10.2.1 -r1.10.2.2 --- squid/src/comm_kqueue.c 12 Mar 2007 22:23:04 -0000 1.10.2.1 +++ squid/src/comm_kqueue.c 22 Jun 2007 12:07:35 -0000 1.10.2.2 @@ -1,6 +1,6 @@ /* - * $Id: comm_kqueue.c,v 1.10.2.1 2007/03/12 22:23:04 hno Exp $ + * $Id: comm_kqueue.c,v 1.10.2.2 2007/06/22 12:07:35 adrian Exp $ * * DEBUG: section 5 Socket Functions * @@ -89,6 +89,17 @@ } void +commOpen(int fd) +{ +} + +void +commClose(int fd) +{ + commSetEvents(fd, 0, 0); +} + +void commSetEvents(int fd, int need_read, int need_write) { struct kevent *kep; Index: squid/src/comm_poll.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm_poll.c,v retrieving revision 1.23 retrieving revision 1.23.2.1 diff -u -r1.23 -r1.23.2.1 --- squid/src/comm_poll.c 28 Oct 2006 00:34:54 -0000 1.23 +++ squid/src/comm_poll.c 22 Jun 2007 12:07:35 -0000 1.23.2.1 @@ -1,6 +1,6 @@ /* - * $Id: comm_poll.c,v 1.23 2006/10/28 00:34:54 hno Exp $ + * $Id: comm_poll.c,v 1.23.2.1 2007/06/22 12:07:35 adrian Exp $ * * DEBUG: section 5 Socket Functions * @@ -76,6 +76,17 @@ } void +commOpen(int fd) +{ +} + +void +commClose(int fd) +{ + commSetEvents(fd, 0, 0); +} + +void commSetEvents(int fd, int need_read, int need_write) { int pfdn = pfd_map[fd]; Index: squid/src/comm_select.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm_select.c,v retrieving revision 1.80 retrieving revision 1.80.2.1 diff -u -r1.80 -r1.80.2.1 --- squid/src/comm_select.c 28 Dec 2006 22:11:26 -0000 1.80 +++ squid/src/comm_select.c 22 Jun 2007 12:07:35 -0000 1.80.2.1 @@ -1,6 +1,6 @@ /* - * $Id: comm_select.c,v 1.80 2006/12/28 22:11:26 hno Exp $ + * $Id: comm_select.c,v 1.80.2.1 2007/06/22 12:07:35 adrian Exp $ * * DEBUG: section 5 Socket Functions * @@ -94,6 +94,17 @@ } void +commClose(int fd) +{ +} + +void +commClose(int fd) +{ + commSetEvents(fd, 0, 0); +} + +void commSetEvents(int fd, int need_read, int need_write) { if (need_read && !FD_ISSET(fd, global_readfds)) { Index: squid/src/comm_select_simple.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm_select_simple.c,v retrieving revision 1.3 retrieving revision 1.3.2.1 diff -u -r1.3 -r1.3.2.1 --- squid/src/comm_select_simple.c 28 Dec 2006 22:11:26 -0000 1.3 +++ squid/src/comm_select_simple.c 22 Jun 2007 12:07:35 -0000 1.3.2.1 @@ -1,6 +1,6 @@ /* - * $Id: comm_select_simple.c,v 1.3 2006/12/28 22:11:26 hno Exp $ + * $Id: comm_select_simple.c,v 1.3.2.1 2007/06/22 12:07:35 adrian Exp $ * * DEBUG: section 5 Socket Functions * @@ -74,6 +74,17 @@ } void +commOpen(int fd) +{ +} + +void +commClose(int fd) +{ + commSetEvents(fd, 0, 0); +} + +void commSetEvents(int fd, int need_read, int need_write) { if (need_read && !FD_ISSET(fd, &global_readfds)) { Index: squid/src/comm_select_win32.c =================================================================== RCS file: /cvsroot/squid/squid/src/comm_select_win32.c,v retrieving revision 1.7 retrieving revision 1.7.2.1 diff -u -r1.7 -r1.7.2.1 --- squid/src/comm_select_win32.c 28 Dec 2006 22:11:26 -0000 1.7 +++ squid/src/comm_select_win32.c 22 Jun 2007 12:07:36 -0000 1.7.2.1 @@ -1,6 +1,6 @@ /* - * $Id: comm_select_win32.c,v 1.7 2006/12/28 22:11:26 hno Exp $ + * $Id: comm_select_win32.c,v 1.7.2.1 2007/06/22 12:07:36 adrian Exp $ * * DEBUG: section 5 Socket Functions * @@ -71,6 +71,17 @@ } void +commOpen(int fd) +{ +} + +void +commClose(int fd) +{ + commSetEvents(fd, 0, 0); +} + +void commSetEvents(int fd, int need_read, int need_write) { if (need_read && !__WSAFDIsSet(fd_table[fd].win32.handle, &global_readfds)) { Index: squid/src/fd.c =================================================================== RCS file: /cvsroot/squid/squid/src/fd.c,v retrieving revision 1.55 retrieving revision 1.55.2.1 diff -u -r1.55 -r1.55.2.1 --- squid/src/fd.c 23 Oct 2006 11:25:29 -0000 1.55 +++ squid/src/fd.c 22 Jun 2007 12:07:36 -0000 1.55.2.1 @@ -1,6 +1,6 @@ /* - * $Id: fd.c,v 1.55 2006/10/23 11:25:29 hno Exp $ + * $Id: fd.c,v 1.55.2.1 2007/06/22 12:07:36 adrian Exp $ * * DEBUG: section 51 Filedescriptor Functions * AUTHOR: Duane Wessels @@ -90,7 +90,7 @@ assert(F->write_handler == NULL); } debug(51, 3) ("fd_close FD %d %s\n", fd, F->desc); - commSetEvents(fd, 0, 0); + commClose(fd); F->flags.open = 0; #if DELAY_POOLS if (F->slow_id) @@ -154,6 +154,7 @@ debug(51, 3) ("fd_open FD %d %s\n", fd, desc); F->type = type; F->flags.open = 1; + commOpen(fd); #ifdef _SQUID_MSWIN_ F->win32.handle = _get_osfhandle(fd); switch (type) { Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid/squid/src/protos.h,v retrieving revision 1.520.2.1 retrieving revision 1.520.2.2 diff -u -r1.520.2.1 -r1.520.2.2 --- squid/src/protos.h 26 Mar 2007 23:14:09 -0000 1.520.2.1 +++ squid/src/protos.h 22 Jun 2007 12:07:36 -0000 1.520.2.2 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.520.2.1 2007/03/26 23:14:09 hno Exp $ + * $Id: protos.h,v 1.520.2.2 2007/06/22 12:07:36 adrian Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -193,6 +193,8 @@ extern int comm_select(int); extern void commUpdateEvents(int fd); extern void commSetEvents(int fd, int need_read, int need_write); +extern void commClose(int fd); +extern void commOpen(int fd); extern void commUpdateReadHandler(int, PF *, void *); extern void commUpdateWriteHandler(int, PF *, void *); extern void comm_quick_poll_required(void);