1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/select.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,333 @@ 1.4 +/* $OpenBSD: select.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 +#ifdef _EVENT_HAVE_SYS_SELECT_H 1.39 +#include <sys/select.h> 1.40 +#endif 1.41 +#include <sys/queue.h> 1.42 +#include <signal.h> 1.43 +#include <stdio.h> 1.44 +#include <stdlib.h> 1.45 +#include <string.h> 1.46 +#include <unistd.h> 1.47 +#include <errno.h> 1.48 + 1.49 +#include "event-internal.h" 1.50 +#include "evsignal-internal.h" 1.51 +#include "event2/thread.h" 1.52 +#include "evthread-internal.h" 1.53 +#include "log-internal.h" 1.54 +#include "evmap-internal.h" 1.55 + 1.56 +#ifndef _EVENT_HAVE_FD_MASK 1.57 +/* This type is mandatory, but Android doesn't define it. */ 1.58 +typedef unsigned long fd_mask; 1.59 +#endif 1.60 + 1.61 +#ifndef NFDBITS 1.62 +#define NFDBITS (sizeof(fd_mask)*8) 1.63 +#endif 1.64 + 1.65 +/* Divide positive x by y, rounding up. */ 1.66 +#define DIV_ROUNDUP(x, y) (((x)+((y)-1))/(y)) 1.67 + 1.68 +/* How many bytes to allocate for N fds? */ 1.69 +#define SELECT_ALLOC_SIZE(n) \ 1.70 + (DIV_ROUNDUP(n, NFDBITS) * sizeof(fd_mask)) 1.71 + 1.72 +struct selectop { 1.73 + int event_fds; /* Highest fd in fd set */ 1.74 + int event_fdsz; 1.75 + int resize_out_sets; 1.76 + fd_set *event_readset_in; 1.77 + fd_set *event_writeset_in; 1.78 + fd_set *event_readset_out; 1.79 + fd_set *event_writeset_out; 1.80 +}; 1.81 + 1.82 +static void *select_init(struct event_base *); 1.83 +static int select_add(struct event_base *, int, short old, short events, void*); 1.84 +static int select_del(struct event_base *, int, short old, short events, void*); 1.85 +static int select_dispatch(struct event_base *, struct timeval *); 1.86 +static void select_dealloc(struct event_base *); 1.87 + 1.88 +const struct eventop selectops = { 1.89 + "select", 1.90 + select_init, 1.91 + select_add, 1.92 + select_del, 1.93 + select_dispatch, 1.94 + select_dealloc, 1.95 + 0, /* doesn't need reinit. */ 1.96 + EV_FEATURE_FDS, 1.97 + 0, 1.98 +}; 1.99 + 1.100 +static int select_resize(struct selectop *sop, int fdsz); 1.101 +static void select_free_selectop(struct selectop *sop); 1.102 + 1.103 +static void * 1.104 +select_init(struct event_base *base) 1.105 +{ 1.106 + struct selectop *sop; 1.107 + 1.108 + if (!(sop = mm_calloc(1, sizeof(struct selectop)))) 1.109 + return (NULL); 1.110 + 1.111 + if (select_resize(sop, SELECT_ALLOC_SIZE(32 + 1))) { 1.112 + select_free_selectop(sop); 1.113 + return (NULL); 1.114 + } 1.115 + 1.116 + evsig_init(base); 1.117 + 1.118 + return (sop); 1.119 +} 1.120 + 1.121 +#ifdef CHECK_INVARIANTS 1.122 +static void 1.123 +check_selectop(struct selectop *sop) 1.124 +{ 1.125 + /* nothing to be done here */ 1.126 +} 1.127 +#else 1.128 +#define check_selectop(sop) do { (void) sop; } while (0) 1.129 +#endif 1.130 + 1.131 +static int 1.132 +select_dispatch(struct event_base *base, struct timeval *tv) 1.133 +{ 1.134 + int res=0, i, j, nfds; 1.135 + struct selectop *sop = base->evbase; 1.136 + 1.137 + check_selectop(sop); 1.138 + if (sop->resize_out_sets) { 1.139 + fd_set *readset_out=NULL, *writeset_out=NULL; 1.140 + size_t sz = sop->event_fdsz; 1.141 + if (!(readset_out = mm_realloc(sop->event_readset_out, sz))) 1.142 + return (-1); 1.143 + sop->event_readset_out = readset_out; 1.144 + if (!(writeset_out = mm_realloc(sop->event_writeset_out, sz))) { 1.145 + /* We don't free readset_out here, since it was 1.146 + * already successfully reallocated. The next time 1.147 + * we call select_dispatch, the realloc will be a 1.148 + * no-op. */ 1.149 + return (-1); 1.150 + } 1.151 + sop->event_writeset_out = writeset_out; 1.152 + sop->resize_out_sets = 0; 1.153 + } 1.154 + 1.155 + memcpy(sop->event_readset_out, sop->event_readset_in, 1.156 + sop->event_fdsz); 1.157 + memcpy(sop->event_writeset_out, sop->event_writeset_in, 1.158 + sop->event_fdsz); 1.159 + 1.160 + nfds = sop->event_fds+1; 1.161 + 1.162 + EVBASE_RELEASE_LOCK(base, th_base_lock); 1.163 + 1.164 + res = select(nfds, sop->event_readset_out, 1.165 + sop->event_writeset_out, NULL, tv); 1.166 + 1.167 + EVBASE_ACQUIRE_LOCK(base, th_base_lock); 1.168 + 1.169 + check_selectop(sop); 1.170 + 1.171 + if (res == -1) { 1.172 + if (errno != EINTR) { 1.173 + event_warn("select"); 1.174 + return (-1); 1.175 + } 1.176 + 1.177 + return (0); 1.178 + } 1.179 + 1.180 + event_debug(("%s: select reports %d", __func__, res)); 1.181 + 1.182 + check_selectop(sop); 1.183 + i = random() % nfds; 1.184 + for (j = 0; j < nfds; ++j) { 1.185 + if (++i >= nfds) 1.186 + i = 0; 1.187 + res = 0; 1.188 + if (FD_ISSET(i, sop->event_readset_out)) 1.189 + res |= EV_READ; 1.190 + if (FD_ISSET(i, sop->event_writeset_out)) 1.191 + res |= EV_WRITE; 1.192 + 1.193 + if (res == 0) 1.194 + continue; 1.195 + 1.196 + evmap_io_active(base, i, res); 1.197 + } 1.198 + check_selectop(sop); 1.199 + 1.200 + return (0); 1.201 +} 1.202 + 1.203 +static int 1.204 +select_resize(struct selectop *sop, int fdsz) 1.205 +{ 1.206 + fd_set *readset_in = NULL; 1.207 + fd_set *writeset_in = NULL; 1.208 + 1.209 + if (sop->event_readset_in) 1.210 + check_selectop(sop); 1.211 + 1.212 + if ((readset_in = mm_realloc(sop->event_readset_in, fdsz)) == NULL) 1.213 + goto error; 1.214 + sop->event_readset_in = readset_in; 1.215 + if ((writeset_in = mm_realloc(sop->event_writeset_in, fdsz)) == NULL) { 1.216 + /* Note that this will leave event_readset_in expanded. 1.217 + * That's okay; we wouldn't want to free it, since that would 1.218 + * change the semantics of select_resize from "expand the 1.219 + * readset_in and writeset_in, or return -1" to "expand the 1.220 + * *set_in members, or trash them and return -1." 1.221 + */ 1.222 + goto error; 1.223 + } 1.224 + sop->event_writeset_in = writeset_in; 1.225 + sop->resize_out_sets = 1; 1.226 + 1.227 + memset((char *)sop->event_readset_in + sop->event_fdsz, 0, 1.228 + fdsz - sop->event_fdsz); 1.229 + memset((char *)sop->event_writeset_in + sop->event_fdsz, 0, 1.230 + fdsz - sop->event_fdsz); 1.231 + 1.232 + sop->event_fdsz = fdsz; 1.233 + check_selectop(sop); 1.234 + 1.235 + return (0); 1.236 + 1.237 + error: 1.238 + event_warn("malloc"); 1.239 + return (-1); 1.240 +} 1.241 + 1.242 + 1.243 +static int 1.244 +select_add(struct event_base *base, int fd, short old, short events, void *p) 1.245 +{ 1.246 + struct selectop *sop = base->evbase; 1.247 + (void) p; 1.248 + 1.249 + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); 1.250 + check_selectop(sop); 1.251 + /* 1.252 + * Keep track of the highest fd, so that we can calculate the size 1.253 + * of the fd_sets for select(2) 1.254 + */ 1.255 + if (sop->event_fds < fd) { 1.256 + int fdsz = sop->event_fdsz; 1.257 + 1.258 + if (fdsz < (int)sizeof(fd_mask)) 1.259 + fdsz = (int)sizeof(fd_mask); 1.260 + 1.261 + /* In theory we should worry about overflow here. In 1.262 + * reality, though, the highest fd on a unixy system will 1.263 + * not overflow here. XXXX */ 1.264 + while (fdsz < (int) SELECT_ALLOC_SIZE(fd + 1)) 1.265 + fdsz *= 2; 1.266 + 1.267 + if (fdsz != sop->event_fdsz) { 1.268 + if (select_resize(sop, fdsz)) { 1.269 + check_selectop(sop); 1.270 + return (-1); 1.271 + } 1.272 + } 1.273 + 1.274 + sop->event_fds = fd; 1.275 + } 1.276 + 1.277 + if (events & EV_READ) 1.278 + FD_SET(fd, sop->event_readset_in); 1.279 + if (events & EV_WRITE) 1.280 + FD_SET(fd, sop->event_writeset_in); 1.281 + check_selectop(sop); 1.282 + 1.283 + return (0); 1.284 +} 1.285 + 1.286 +/* 1.287 + * Nothing to be done here. 1.288 + */ 1.289 + 1.290 +static int 1.291 +select_del(struct event_base *base, int fd, short old, short events, void *p) 1.292 +{ 1.293 + struct selectop *sop = base->evbase; 1.294 + (void)p; 1.295 + 1.296 + EVUTIL_ASSERT((events & EV_SIGNAL) == 0); 1.297 + check_selectop(sop); 1.298 + 1.299 + if (sop->event_fds < fd) { 1.300 + check_selectop(sop); 1.301 + return (0); 1.302 + } 1.303 + 1.304 + if (events & EV_READ) 1.305 + FD_CLR(fd, sop->event_readset_in); 1.306 + 1.307 + if (events & EV_WRITE) 1.308 + FD_CLR(fd, sop->event_writeset_in); 1.309 + 1.310 + check_selectop(sop); 1.311 + return (0); 1.312 +} 1.313 + 1.314 +static void 1.315 +select_free_selectop(struct selectop *sop) 1.316 +{ 1.317 + if (sop->event_readset_in) 1.318 + mm_free(sop->event_readset_in); 1.319 + if (sop->event_writeset_in) 1.320 + mm_free(sop->event_writeset_in); 1.321 + if (sop->event_readset_out) 1.322 + mm_free(sop->event_readset_out); 1.323 + if (sop->event_writeset_out) 1.324 + mm_free(sop->event_writeset_out); 1.325 + 1.326 + memset(sop, 0, sizeof(struct selectop)); 1.327 + mm_free(sop); 1.328 +} 1.329 + 1.330 +static void 1.331 +select_dealloc(struct event_base *base) 1.332 +{ 1.333 + evsig_dealloc(base); 1.334 + 1.335 + select_free_selectop(base->evbase); 1.336 +}