1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Copyright 2000-2004 Niels Provos <provos@citi.umich.edu> 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * All rights reserved. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Redistribution and use in source and binary forms, with or without 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * modification, are permitted provided that the following conditions 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * are met: 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 1. Redistributions of source code must retain the above copyright 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * notice, this list of conditions and the following disclaimer. 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 2. Redistributions in binary form must reproduce the above copyright 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * notice, this list of conditions and the following disclaimer in the 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * documentation and/or other materials provided with the distribution. 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 3. The name of the author may not be used to endorse or promote products 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * derived from this software without specific prior written permission. 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef HAVE_CONFIG_H 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "config.h" 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/types.h> 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/resource.h> 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef HAVE_SYS_TIME_H 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/time.h> 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/_libevent_time.h> 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/queue.h> 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/devpoll.h> 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <signal.h> 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdio.h> 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h> 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string.h> 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <unistd.h> 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <fcntl.h> 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h> 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <assert.h> 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "event.h" 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "event-internal.h" 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "evsignal.h" 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "log.h" 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* due to limitations in the devpoll interface, we need to keep track of 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * all file descriptors outself. 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct evdevpoll { 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct event *evread; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct event *evwrite; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct devpollop { 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct evdevpoll *fds; 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nfds; 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct pollfd *events; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nevents; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int dpfd; 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct pollfd *changes; 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nchanges; 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void *devpoll_init (struct event_base *); 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int devpoll_add (void *, struct event *); 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int devpoll_del (void *, struct event *); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int devpoll_dispatch (struct event_base *, void *, struct timeval *); 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void devpoll_dealloc (struct event_base *, void *); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst struct eventop devpollops = { 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "devpoll", 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_init, 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_add, 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_del, 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_dispatch, 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_dealloc, 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1 /* need reinit */ 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NEVENT 32000 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_commit(struct devpollop *devpollop) 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Due to a bug in Solaris, we have to use pwrite with an offset of 0. 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Write is limited to 2GB of data, until it will fail. 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pwrite(devpollop->dpfd, devpollop->changes, 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(struct pollfd) * devpollop->nchanges, 0) == -1) 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(-1); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->nchanges = 0; 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(0); 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_queue(struct devpollop *devpollop, int fd, int events) { 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct pollfd *pfd; 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->nchanges >= devpollop->nevents) { 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Change buffer is full, must commit it to /dev/poll before 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * adding more 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpoll_commit(devpollop) != 0) 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(-1); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pfd = &devpollop->changes[devpollop->nchanges++]; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pfd->fd = fd; 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pfd->events = events; 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pfd->revents = 0; 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(0); 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void * 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_init(struct event_base *base) 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int dpfd, nfiles = NEVENT; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct rlimit rl; 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct devpollop *devpollop; 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Disable devpoll when this environment variable is set */ 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evutil_getenv("EVENT_NODEVPOLL")) 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (NULL); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!(devpollop = calloc(1, sizeof(struct devpollop)))) 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (NULL); 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rl.rlim_cur != RLIM_INFINITY) 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nfiles = rl.rlim_cur; 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Initialize the kernel queue */ 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((dpfd = open("/dev/poll", O_RDWR)) == -1) { 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_warn("open: /dev/poll"); 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop); 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (NULL); 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->dpfd = dpfd; 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Initialize fields */ 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->events = calloc(nfiles, sizeof(struct pollfd)); 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->events == NULL) { 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop); 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(dpfd); 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (NULL); 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->nevents = nfiles; 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll)); 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->fds == NULL) { 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop->events); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop); 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(dpfd); 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (NULL); 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->nfds = nfiles; 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->changes = calloc(nfiles, sizeof(struct pollfd)); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->changes == NULL) { 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop->fds); 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop->events); 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop); 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(dpfd); 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (NULL); 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evsignal_init(base); 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (devpollop); 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_recalc(struct event_base *base, void *arg, int max) 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct devpollop *devpollop = arg; 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (max >= devpollop->nfds) { 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct evdevpoll *fds; 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nfds; 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nfds = devpollop->nfds; 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (nfds <= max) 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott nfds <<= 1; 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll)); 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fds == NULL) { 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_warn("realloc"); 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (-1); 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->fds = fds; 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(fds + devpollop->nfds, 0, 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (nfds - devpollop->nfds) * sizeof(struct evdevpoll)); 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpollop->nfds = nfds; 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (0); 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv) 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct devpollop *devpollop = arg; 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct pollfd *events = devpollop->events; 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct dvpoll dvp; 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct evdevpoll *evdp; 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int i, res, timeout = -1; 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->nchanges) 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_commit(devpollop); 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tv != NULL) 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dvp.dp_fds = devpollop->events; 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dvp.dp_nfds = devpollop->nevents; 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dvp.dp_timeout = timeout; 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott res = ioctl(devpollop->dpfd, DP_POLL, &dvp); 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (res == -1) { 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (errno != EINTR) { 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_warn("ioctl: DP_POLL"); 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (-1); 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evsignal_process(base); 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (0); 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (base->sig.evsignal_caught) { 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evsignal_process(base); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_debug(("%s: devpoll_wait reports %d", __func__, res)); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (i = 0; i < res; i++) { 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int which = 0; 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int what = events[i].revents; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct event *evread = NULL, *evwrite = NULL; 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott assert(events[i].fd < devpollop->nfds); 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evdp = &devpollop->fds[events[i].fd]; 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (what & POLLHUP) 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott what |= POLLIN | POLLOUT; 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (what & POLLERR) 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott what |= POLLIN | POLLOUT; 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (what & POLLIN) { 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evread = evdp->evread; 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott which |= EV_READ; 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (what & POLLOUT) { 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evwrite = evdp->evwrite; 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott which |= EV_WRITE; 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!which) 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evread != NULL && !(evread->ev_events & EV_PERSIST)) 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(evread); 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evwrite != NULL && evwrite != evread && 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott !(evwrite->ev_events & EV_PERSIST)) 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(evwrite); 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evread != NULL) 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_active(evread, EV_READ, 1); 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evwrite != NULL) 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_active(evwrite, EV_WRITE, 1); 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (0); 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_add(void *arg, struct event *ev) 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct devpollop *devpollop = arg; 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct evdevpoll *evdp; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd, events; 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_SIGNAL) 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (evsignal_add(ev)); 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd = ev->ev_fd; 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd >= devpollop->nfds) { 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Extend the file descriptor array as necessary */ 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1) 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (-1); 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evdp = &devpollop->fds[fd]; 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * It's not necessary to OR the existing read/write events that we 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * are currently interested in with the new event we are adding. 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The /dev/poll driver ORs any new events with the existing events 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * that it has cached for the fd. 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events = 0; 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_READ) { 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evdp->evread && evdp->evread != ev) { 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* There is already a different read event registered */ 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(-1); 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events |= POLLIN; 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_WRITE) { 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evdp->evwrite && evdp->evwrite != ev) { 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* There is already a different write event registered */ 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(-1); 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events |= POLLOUT; 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpoll_queue(devpollop, fd, events) != 0) 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(-1); 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Update events responsible */ 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_READ) 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evdp->evread = ev; 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_WRITE) 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evdp->evwrite = ev; 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (0); 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_del(void *arg, struct event *ev) 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct devpollop *devpollop = arg; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct evdevpoll *evdp; 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd, events; 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int needwritedelete = 1, needreaddelete = 1; 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_SIGNAL) 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (evsignal_del(ev)); 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd = ev->ev_fd; 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd >= devpollop->nfds) 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (0); 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evdp = &devpollop->fds[fd]; 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events = 0; 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_READ) 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events |= POLLIN; 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ev->ev_events & EV_WRITE) 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events |= POLLOUT; 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The only way to remove an fd from the /dev/poll monitored set is 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * to use POLLREMOVE by itself. This removes ALL events for the fd 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * provided so if we care about two events and are only removing one 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * we must re-add the other event after POLLREMOVE. 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0) 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return(-1); 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) { 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * We're not deleting all events, so we must resubmit the 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * event that we are still interested in if one exists. 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((events & POLLIN) && evdp->evwrite != NULL) { 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Deleting read, still care about write */ 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_queue(devpollop, fd, POLLOUT); 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott needwritedelete = 0; 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if ((events & POLLOUT) && evdp->evread != NULL) { 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Deleting write, still care about read */ 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott devpoll_queue(devpollop, fd, POLLIN); 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott needreaddelete = 0; 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (needreaddelete) 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evdp->evread = NULL; 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (needwritedelete) 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evdp->evwrite = NULL; 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (0); 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdevpoll_dealloc(struct event_base *base, void *arg) 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct devpollop *devpollop = arg; 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evsignal_dealloc(base); 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->fds) 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop->fds); 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->events) 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop->events); 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->changes) 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop->changes); 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (devpollop->dpfd >= 0) 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(devpollop->dpfd); 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(devpollop, 0, sizeof(struct devpollop)); 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott free(devpollop); 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 418