1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/poll.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,333 @@ 1.4 +/* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 1.5 + 1.6 +/* 1.7 + * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> 1.8 + * Copyright 2007-2012 Niels Provos and Nick Mathewson 1.9 + * 1.10 + * Redistribution and use in source and binary forms, with or without 1.11 + * modification, are permitted provided that the following conditions 1.12 + * are met: 1.13 + * 1. Redistributions of source code must retain the above copyright 1.14 + * notice, this list of conditions and the following disclaimer. 1.15 + * 2. Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in the 1.17 + * documentation and/or other materials provided with the distribution. 1.18 + * 3. The name of the author may not be used to endorse or promote products 1.19 + * derived from this software without specific prior written permission. 1.20 + * 1.21 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.22 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.23 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.24 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.25 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.26 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.27 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.28 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.29 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.30 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.31 + */ 1.32 +#include "event2/event-config.h" 1.33 + 1.34 +#include <sys/types.h> 1.35 +#ifdef _EVENT_HAVE_SYS_TIME_H 1.36 +#include <sys/time.h> 1.37 +#endif 1.38 +#include <sys/queue.h> 1.39 +#include <poll.h> 1.40 +#include <signal.h> 1.41 +#include <limits.h> 1.42 +#include <stdio.h> 1.43 +#include <stdlib.h> 1.44 +#include <string.h> 1.45 +#include <unistd.h> 1.46 +#include <errno.h> 1.47 + 1.48 +#include "event-internal.h" 1.49 +#include "evsignal-internal.h" 1.50 +#include "log-internal.h" 1.51 +#include "evmap-internal.h" 1.52 +#include "event2/thread.h" 1.53 +#include "evthread-internal.h" 1.54 + 1.55 +struct pollidx { 1.56 + int idxplus1; 1.57 +}; 1.58 + 1.59 +struct pollop { 1.60 + int event_count; /* Highest number alloc */ 1.61 + int nfds; /* Highest number used */ 1.62 + int realloc_copy; /* True iff we must realloc 1.63 + * event_set_copy */ 1.64 + struct pollfd *event_set; 1.65 + struct pollfd *event_set_copy; 1.66 +}; 1.67 + 1.68 +static void *poll_init(struct event_base *); 1.69 +static int poll_add(struct event_base *, int, short old, short events, void *_idx); 1.70 +static int poll_del(struct event_base *, int, short old, short events, void *_idx); 1.71 +static int poll_dispatch(struct event_base *, struct timeval *); 1.72 +static void poll_dealloc(struct event_base *); 1.73 + 1.74 +const struct eventop pollops = { 1.75 + "poll", 1.76 + poll_init, 1.77 + poll_add, 1.78 + poll_del, 1.79 + poll_dispatch, 1.80 + poll_dealloc, 1.81 + 0, /* doesn't need_reinit */ 1.82 + EV_FEATURE_FDS, 1.83 + sizeof(struct pollidx), 1.84 +}; 1.85 + 1.86 +static void * 1.87 +poll_init(struct event_base *base) 1.88 +{ 1.89 + struct pollop *pollop; 1.90 + 1.91 + if (!(pollop = mm_calloc(1, sizeof(struct pollop)))) 1.92 + return (NULL); 1.93 + 1.94 + evsig_init(base); 1.95 + 1.96 + return (pollop); 1.97 +} 1.98 + 1.99 +#ifdef CHECK_INVARIANTS 1.100 +static void 1.101 +poll_check_ok(struct pollop *pop) 1.102 +{ 1.103 + int i, idx; 1.104 + struct event *ev; 1.105 + 1.106 + for (i = 0; i < pop->fd_count; ++i) { 1.107 + idx = pop->idxplus1_by_fd[i]-1; 1.108 + if (idx < 0) 1.109 + continue; 1.110 + EVUTIL_ASSERT(pop->event_set[idx].fd == i); 1.111 + } 1.112 + for (i = 0; i < pop->nfds; ++i) { 1.113 + struct pollfd *pfd = &pop->event_set[i]; 1.114 + EVUTIL_ASSERT(pop->idxplus1_by_fd[pfd->fd] == i+1); 1.115 + } 1.116 +} 1.117 +#else 1.118 +#define poll_check_ok(pop) 1.119 +#endif 1.120 + 1.121 +static int 1.122 +poll_dispatch(struct event_base *base, struct timeval *tv) 1.123 +{ 1.124 + int res, i, j, nfds; 1.125 + long msec = -1; 1.126 + struct pollop *pop = base->evbase; 1.127 + struct pollfd *event_set; 1.128 + 1.129 + poll_check_ok(pop); 1.130 + 1.131 + nfds = pop->nfds; 1.132 + 1.133 +#ifndef _EVENT_DISABLE_THREAD_SUPPORT 1.134 + if (base->th_base_lock) { 1.135 + /* If we're using this backend in a multithreaded setting, 1.136 + * then we need to work on a copy of event_set, so that we can 1.137 + * let other threads modify the main event_set while we're 1.138 + * polling. If we're not multithreaded, then we'll skip the 1.139 + * copy step here to save memory and time. */ 1.140 + if (pop->realloc_copy) { 1.141 + struct pollfd *tmp = mm_realloc(pop->event_set_copy, 1.142 + pop->event_count * sizeof(struct pollfd)); 1.143 + if (tmp == NULL) { 1.144 + event_warn("realloc"); 1.145 + return -1; 1.146 + } 1.147 + pop->event_set_copy = tmp; 1.148 + pop->realloc_copy = 0; 1.149 + } 1.150 + memcpy(pop->event_set_copy, pop->event_set, 1.151 + sizeof(struct pollfd)*nfds); 1.152 + event_set = pop->event_set_copy; 1.153 + } else { 1.154 + event_set = pop->event_set; 1.155 + } 1.156 +#else 1.157 + event_set = pop->event_set; 1.158 +#endif 1.159 + 1.160 + if (tv != NULL) { 1.161 + msec = evutil_tv_to_msec(tv); 1.162 + if (msec < 0 || msec > INT_MAX) 1.163 + msec = INT_MAX; 1.164 + } 1.165 + 1.166 + EVBASE_RELEASE_LOCK(base, th_base_lock); 1.167 + 1.168 + res = poll(event_set, nfds, msec); 1.169 + 1.170 + EVBASE_ACQUIRE_LOCK(base, th_base_lock); 1.171 + 1.172 + if (res == -1) { 1.173 + if (errno != EINTR) { 1.174 + event_warn("poll"); 1.175 + return (-1); 1.176 + } 1.177 + 1.178 + return (0); 1.179 + } 1.180 + 1.181 + event_debug(("%s: poll reports %d", __func__, res)); 1.182 + 1.183 + if (res == 0 || nfds == 0) 1.184 + return (0); 1.185 + 1.186 + i = random() % nfds; 1.187 + for (j = 0; j < nfds; j++) { 1.188 + int what; 1.189 + if (++i == nfds) 1.190 + i = 0; 1.191 + what = event_set[i].revents; 1.192 + if (!what) 1.193 + continue; 1.194 + 1.195 + res = 0; 1.196 + 1.197 + /* If the file gets closed notify */ 1.198 + if (what & (POLLHUP|POLLERR)) 1.199 + what |= POLLIN|POLLOUT; 1.200 + if (what & POLLIN) 1.201 + res |= EV_READ; 1.202 + if (what & POLLOUT) 1.203 + res |= EV_WRITE; 1.204 + if (res == 0) 1.205 + continue; 1.206 + 1.207 + evmap_io_active(base, event_set[i].fd, res); 1.208 + } 1.209 + 1.210 + return (0); 1.211 +} 1.212 + 1.213 +static int 1.214 +poll_add(struct event_base *base, int fd, short old, short events, void *_idx) 1.215 +{ 1.216 + struct pollop *pop = base->evbase; 1.217 + struct pollfd *pfd = NULL; 1.218 + struct pollidx *idx = _idx; 1.219 + int i; 1.220 + 1.221 + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); 1.222 + if (!(events & (EV_READ|EV_WRITE))) 1.223 + return (0); 1.224 + 1.225 + poll_check_ok(pop); 1.226 + if (pop->nfds + 1 >= pop->event_count) { 1.227 + struct pollfd *tmp_event_set; 1.228 + int tmp_event_count; 1.229 + 1.230 + if (pop->event_count < 32) 1.231 + tmp_event_count = 32; 1.232 + else 1.233 + tmp_event_count = pop->event_count * 2; 1.234 + 1.235 + /* We need more file descriptors */ 1.236 + tmp_event_set = mm_realloc(pop->event_set, 1.237 + tmp_event_count * sizeof(struct pollfd)); 1.238 + if (tmp_event_set == NULL) { 1.239 + event_warn("realloc"); 1.240 + return (-1); 1.241 + } 1.242 + pop->event_set = tmp_event_set; 1.243 + 1.244 + pop->event_count = tmp_event_count; 1.245 + pop->realloc_copy = 1; 1.246 + } 1.247 + 1.248 + i = idx->idxplus1 - 1; 1.249 + 1.250 + if (i >= 0) { 1.251 + pfd = &pop->event_set[i]; 1.252 + } else { 1.253 + i = pop->nfds++; 1.254 + pfd = &pop->event_set[i]; 1.255 + pfd->events = 0; 1.256 + pfd->fd = fd; 1.257 + idx->idxplus1 = i + 1; 1.258 + } 1.259 + 1.260 + pfd->revents = 0; 1.261 + if (events & EV_WRITE) 1.262 + pfd->events |= POLLOUT; 1.263 + if (events & EV_READ) 1.264 + pfd->events |= POLLIN; 1.265 + poll_check_ok(pop); 1.266 + 1.267 + return (0); 1.268 +} 1.269 + 1.270 +/* 1.271 + * Nothing to be done here. 1.272 + */ 1.273 + 1.274 +static int 1.275 +poll_del(struct event_base *base, int fd, short old, short events, void *_idx) 1.276 +{ 1.277 + struct pollop *pop = base->evbase; 1.278 + struct pollfd *pfd = NULL; 1.279 + struct pollidx *idx = _idx; 1.280 + int i; 1.281 + 1.282 + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); 1.283 + if (!(events & (EV_READ|EV_WRITE))) 1.284 + return (0); 1.285 + 1.286 + poll_check_ok(pop); 1.287 + i = idx->idxplus1 - 1; 1.288 + if (i < 0) 1.289 + return (-1); 1.290 + 1.291 + /* Do we still want to read or write? */ 1.292 + pfd = &pop->event_set[i]; 1.293 + if (events & EV_READ) 1.294 + pfd->events &= ~POLLIN; 1.295 + if (events & EV_WRITE) 1.296 + pfd->events &= ~POLLOUT; 1.297 + poll_check_ok(pop); 1.298 + if (pfd->events) 1.299 + /* Another event cares about that fd. */ 1.300 + return (0); 1.301 + 1.302 + /* Okay, so we aren't interested in that fd anymore. */ 1.303 + idx->idxplus1 = 0; 1.304 + 1.305 + --pop->nfds; 1.306 + if (i != pop->nfds) { 1.307 + /* 1.308 + * Shift the last pollfd down into the now-unoccupied 1.309 + * position. 1.310 + */ 1.311 + memcpy(&pop->event_set[i], &pop->event_set[pop->nfds], 1.312 + sizeof(struct pollfd)); 1.313 + idx = evmap_io_get_fdinfo(&base->io, pop->event_set[i].fd); 1.314 + EVUTIL_ASSERT(idx); 1.315 + EVUTIL_ASSERT(idx->idxplus1 == pop->nfds + 1); 1.316 + idx->idxplus1 = i + 1; 1.317 + } 1.318 + 1.319 + poll_check_ok(pop); 1.320 + return (0); 1.321 +} 1.322 + 1.323 +static void 1.324 +poll_dealloc(struct event_base *base) 1.325 +{ 1.326 + struct pollop *pop = base->evbase; 1.327 + 1.328 + evsig_dealloc(base); 1.329 + if (pop->event_set) 1.330 + mm_free(pop->event_set); 1.331 + if (pop->event_set_copy) 1.332 + mm_free(pop->event_set_copy); 1.333 + 1.334 + memset(pop, 0, sizeof(struct pollop)); 1.335 + mm_free(pop); 1.336 +}