1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/win32select.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,377 @@ 1.4 +/* 1.5 + * Copyright 2007-2012 Niels Provos and Nick Mathewson 1.6 + * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> 1.7 + * Copyright 2003 Michael A. Davis <mike@datanerds.net> 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions 1.11 + * are met: 1.12 + * 1. Redistributions of source code must retain the above copyright 1.13 + * notice, this list of conditions and the following disclaimer. 1.14 + * 2. Redistributions in binary form must reproduce the above copyright 1.15 + * notice, this list of conditions and the following disclaimer in the 1.16 + * documentation and/or other materials provided with the distribution. 1.17 + * 3. The name of the author may not be used to endorse or promote products 1.18 + * derived from this software without specific prior written permission. 1.19 + * 1.20 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.21 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.22 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.23 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.24 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.25 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.26 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.27 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.28 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.29 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.30 + */ 1.31 + 1.32 +#include <winsock2.h> 1.33 +#include <windows.h> 1.34 +#include <sys/types.h> 1.35 +#include <sys/queue.h> 1.36 +#include <limits.h> 1.37 +#include <signal.h> 1.38 +#include <stdio.h> 1.39 +#include <stdlib.h> 1.40 +#include <string.h> 1.41 +#include <errno.h> 1.42 + 1.43 +#include "event2/util.h" 1.44 +#include "event2/event-config.h" 1.45 +#include "util-internal.h" 1.46 +#include "log-internal.h" 1.47 +#include "event2/event.h" 1.48 +#include "event-internal.h" 1.49 +#include "evmap-internal.h" 1.50 +#include "event2/thread.h" 1.51 +#include "evthread-internal.h" 1.52 + 1.53 +#define XFREE(ptr) do { if (ptr) mm_free(ptr); } while (0) 1.54 + 1.55 +extern struct event_list timequeue; 1.56 +extern struct event_list addqueue; 1.57 + 1.58 +struct win_fd_set { 1.59 + u_int fd_count; 1.60 + SOCKET fd_array[1]; 1.61 +}; 1.62 + 1.63 +/* MSDN says this is required to handle SIGFPE */ 1.64 +volatile double SIGFPE_REQ = 0.0f; 1.65 + 1.66 +struct idx_info { 1.67 + int read_pos_plus1; 1.68 + int write_pos_plus1; 1.69 +}; 1.70 + 1.71 +struct win32op { 1.72 + unsigned num_fds_in_fd_sets; 1.73 + int resize_out_sets; 1.74 + struct win_fd_set *readset_in; 1.75 + struct win_fd_set *writeset_in; 1.76 + struct win_fd_set *readset_out; 1.77 + struct win_fd_set *writeset_out; 1.78 + struct win_fd_set *exset_out; 1.79 + unsigned signals_are_broken : 1; 1.80 +}; 1.81 + 1.82 +static void *win32_init(struct event_base *); 1.83 +static int win32_add(struct event_base *, evutil_socket_t, short old, short events, void *_idx); 1.84 +static int win32_del(struct event_base *, evutil_socket_t, short old, short events, void *_idx); 1.85 +static int win32_dispatch(struct event_base *base, struct timeval *); 1.86 +static void win32_dealloc(struct event_base *); 1.87 + 1.88 +struct eventop win32ops = { 1.89 + "win32", 1.90 + win32_init, 1.91 + win32_add, 1.92 + win32_del, 1.93 + win32_dispatch, 1.94 + win32_dealloc, 1.95 + 0, /* doesn't need reinit */ 1.96 + 0, /* No features supported. */ 1.97 + sizeof(struct idx_info), 1.98 +}; 1.99 + 1.100 +#define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET))) 1.101 + 1.102 +static int 1.103 +grow_fd_sets(struct win32op *op, unsigned new_num_fds) 1.104 +{ 1.105 + size_t size; 1.106 + 1.107 + EVUTIL_ASSERT(new_num_fds >= op->readset_in->fd_count && 1.108 + new_num_fds >= op->writeset_in->fd_count); 1.109 + EVUTIL_ASSERT(new_num_fds >= 1); 1.110 + 1.111 + size = FD_SET_ALLOC_SIZE(new_num_fds); 1.112 + if (!(op->readset_in = mm_realloc(op->readset_in, size))) 1.113 + return (-1); 1.114 + if (!(op->writeset_in = mm_realloc(op->writeset_in, size))) 1.115 + return (-1); 1.116 + op->resize_out_sets = 1; 1.117 + op->num_fds_in_fd_sets = new_num_fds; 1.118 + return (0); 1.119 +} 1.120 + 1.121 +static int 1.122 +do_fd_set(struct win32op *op, struct idx_info *ent, evutil_socket_t s, int read) 1.123 +{ 1.124 + struct win_fd_set *set = read ? op->readset_in : op->writeset_in; 1.125 + if (read) { 1.126 + if (ent->read_pos_plus1 > 0) 1.127 + return (0); 1.128 + } else { 1.129 + if (ent->write_pos_plus1 > 0) 1.130 + return (0); 1.131 + } 1.132 + if (set->fd_count == op->num_fds_in_fd_sets) { 1.133 + if (grow_fd_sets(op, op->num_fds_in_fd_sets*2)) 1.134 + return (-1); 1.135 + /* set pointer will have changed and needs reiniting! */ 1.136 + set = read ? op->readset_in : op->writeset_in; 1.137 + } 1.138 + set->fd_array[set->fd_count] = s; 1.139 + if (read) 1.140 + ent->read_pos_plus1 = set->fd_count+1; 1.141 + else 1.142 + ent->write_pos_plus1 = set->fd_count+1; 1.143 + return (set->fd_count++); 1.144 +} 1.145 + 1.146 +static int 1.147 +do_fd_clear(struct event_base *base, 1.148 + struct win32op *op, struct idx_info *ent, int read) 1.149 +{ 1.150 + int i; 1.151 + struct win_fd_set *set = read ? op->readset_in : op->writeset_in; 1.152 + if (read) { 1.153 + i = ent->read_pos_plus1 - 1; 1.154 + ent->read_pos_plus1 = 0; 1.155 + } else { 1.156 + i = ent->write_pos_plus1 - 1; 1.157 + ent->write_pos_plus1 = 0; 1.158 + } 1.159 + if (i < 0) 1.160 + return (0); 1.161 + if (--set->fd_count != (unsigned)i) { 1.162 + struct idx_info *ent2; 1.163 + SOCKET s2; 1.164 + s2 = set->fd_array[i] = set->fd_array[set->fd_count]; 1.165 + 1.166 + ent2 = evmap_io_get_fdinfo(&base->io, s2); 1.167 + 1.168 + if (!ent2) /* This indicates a bug. */ 1.169 + return (0); 1.170 + if (read) 1.171 + ent2->read_pos_plus1 = i+1; 1.172 + else 1.173 + ent2->write_pos_plus1 = i+1; 1.174 + } 1.175 + return (0); 1.176 +} 1.177 + 1.178 +#define NEVENT 32 1.179 +void * 1.180 +win32_init(struct event_base *_base) 1.181 +{ 1.182 + struct win32op *winop; 1.183 + size_t size; 1.184 + if (!(winop = mm_calloc(1, sizeof(struct win32op)))) 1.185 + return NULL; 1.186 + winop->num_fds_in_fd_sets = NEVENT; 1.187 + size = FD_SET_ALLOC_SIZE(NEVENT); 1.188 + if (!(winop->readset_in = mm_malloc(size))) 1.189 + goto err; 1.190 + if (!(winop->writeset_in = mm_malloc(size))) 1.191 + goto err; 1.192 + if (!(winop->readset_out = mm_malloc(size))) 1.193 + goto err; 1.194 + if (!(winop->writeset_out = mm_malloc(size))) 1.195 + goto err; 1.196 + if (!(winop->exset_out = mm_malloc(size))) 1.197 + goto err; 1.198 + winop->readset_in->fd_count = winop->writeset_in->fd_count = 0; 1.199 + winop->readset_out->fd_count = winop->writeset_out->fd_count 1.200 + = winop->exset_out->fd_count = 0; 1.201 + 1.202 + if (evsig_init(_base) < 0) 1.203 + winop->signals_are_broken = 1; 1.204 + 1.205 + return (winop); 1.206 + err: 1.207 + XFREE(winop->readset_in); 1.208 + XFREE(winop->writeset_in); 1.209 + XFREE(winop->readset_out); 1.210 + XFREE(winop->writeset_out); 1.211 + XFREE(winop->exset_out); 1.212 + XFREE(winop); 1.213 + return (NULL); 1.214 +} 1.215 + 1.216 +int 1.217 +win32_add(struct event_base *base, evutil_socket_t fd, 1.218 + short old, short events, void *_idx) 1.219 +{ 1.220 + struct win32op *win32op = base->evbase; 1.221 + struct idx_info *idx = _idx; 1.222 + 1.223 + if ((events & EV_SIGNAL) && win32op->signals_are_broken) 1.224 + return (-1); 1.225 + 1.226 + if (!(events & (EV_READ|EV_WRITE))) 1.227 + return (0); 1.228 + 1.229 + event_debug(("%s: adding event for %d", __func__, (int)fd)); 1.230 + if (events & EV_READ) { 1.231 + if (do_fd_set(win32op, idx, fd, 1)<0) 1.232 + return (-1); 1.233 + } 1.234 + if (events & EV_WRITE) { 1.235 + if (do_fd_set(win32op, idx, fd, 0)<0) 1.236 + return (-1); 1.237 + } 1.238 + return (0); 1.239 +} 1.240 + 1.241 +int 1.242 +win32_del(struct event_base *base, evutil_socket_t fd, short old, short events, 1.243 + void *_idx) 1.244 +{ 1.245 + struct win32op *win32op = base->evbase; 1.246 + struct idx_info *idx = _idx; 1.247 + 1.248 + event_debug(("%s: Removing event for "EV_SOCK_FMT, 1.249 + __func__, EV_SOCK_ARG(fd))); 1.250 + if (events & EV_READ) 1.251 + do_fd_clear(base, win32op, idx, 1); 1.252 + if (events & EV_WRITE) 1.253 + do_fd_clear(base, win32op, idx, 0); 1.254 + 1.255 + return 0; 1.256 +} 1.257 + 1.258 +static void 1.259 +fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in) 1.260 +{ 1.261 + out->fd_count = in->fd_count; 1.262 + memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET))); 1.263 +} 1.264 + 1.265 +/* 1.266 + static void dump_fd_set(struct win_fd_set *s) 1.267 + { 1.268 + unsigned int i; 1.269 + printf("[ "); 1.270 + for(i=0;i<s->fd_count;++i) 1.271 + printf("%d ",(int)s->fd_array[i]); 1.272 + printf("]\n"); 1.273 + } 1.274 +*/ 1.275 + 1.276 +int 1.277 +win32_dispatch(struct event_base *base, struct timeval *tv) 1.278 +{ 1.279 + struct win32op *win32op = base->evbase; 1.280 + int res = 0; 1.281 + unsigned j, i; 1.282 + int fd_count; 1.283 + SOCKET s; 1.284 + 1.285 + if (win32op->resize_out_sets) { 1.286 + size_t size = FD_SET_ALLOC_SIZE(win32op->num_fds_in_fd_sets); 1.287 + if (!(win32op->readset_out = mm_realloc(win32op->readset_out, size))) 1.288 + return (-1); 1.289 + if (!(win32op->exset_out = mm_realloc(win32op->exset_out, size))) 1.290 + return (-1); 1.291 + if (!(win32op->writeset_out = mm_realloc(win32op->writeset_out, size))) 1.292 + return (-1); 1.293 + win32op->resize_out_sets = 0; 1.294 + } 1.295 + 1.296 + fd_set_copy(win32op->readset_out, win32op->readset_in); 1.297 + fd_set_copy(win32op->exset_out, win32op->writeset_in); 1.298 + fd_set_copy(win32op->writeset_out, win32op->writeset_in); 1.299 + 1.300 + fd_count = 1.301 + (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ? 1.302 + win32op->readset_out->fd_count : win32op->writeset_out->fd_count; 1.303 + 1.304 + if (!fd_count) { 1.305 + long msec = tv ? evutil_tv_to_msec(tv) : LONG_MAX; 1.306 + /* Sleep's DWORD argument is unsigned long */ 1.307 + if (msec < 0) 1.308 + msec = LONG_MAX; 1.309 + /* Windows doesn't like you to call select() with no sockets */ 1.310 + Sleep(msec); 1.311 + return (0); 1.312 + } 1.313 + 1.314 + EVBASE_RELEASE_LOCK(base, th_base_lock); 1.315 + 1.316 + res = select(fd_count, 1.317 + (struct fd_set*)win32op->readset_out, 1.318 + (struct fd_set*)win32op->writeset_out, 1.319 + (struct fd_set*)win32op->exset_out, tv); 1.320 + 1.321 + EVBASE_ACQUIRE_LOCK(base, th_base_lock); 1.322 + 1.323 + event_debug(("%s: select returned %d", __func__, res)); 1.324 + 1.325 + if (res <= 0) { 1.326 + return res; 1.327 + } 1.328 + 1.329 + if (win32op->readset_out->fd_count) { 1.330 + i = rand() % win32op->readset_out->fd_count; 1.331 + for (j=0; j<win32op->readset_out->fd_count; ++j) { 1.332 + if (++i >= win32op->readset_out->fd_count) 1.333 + i = 0; 1.334 + s = win32op->readset_out->fd_array[i]; 1.335 + evmap_io_active(base, s, EV_READ); 1.336 + } 1.337 + } 1.338 + if (win32op->exset_out->fd_count) { 1.339 + i = rand() % win32op->exset_out->fd_count; 1.340 + for (j=0; j<win32op->exset_out->fd_count; ++j) { 1.341 + if (++i >= win32op->exset_out->fd_count) 1.342 + i = 0; 1.343 + s = win32op->exset_out->fd_array[i]; 1.344 + evmap_io_active(base, s, EV_WRITE); 1.345 + } 1.346 + } 1.347 + if (win32op->writeset_out->fd_count) { 1.348 + SOCKET s; 1.349 + i = rand() % win32op->writeset_out->fd_count; 1.350 + for (j=0; j<win32op->writeset_out->fd_count; ++j) { 1.351 + if (++i >= win32op->writeset_out->fd_count) 1.352 + i = 0; 1.353 + s = win32op->writeset_out->fd_array[i]; 1.354 + evmap_io_active(base, s, EV_WRITE); 1.355 + } 1.356 + } 1.357 + return (0); 1.358 +} 1.359 + 1.360 +void 1.361 +win32_dealloc(struct event_base *_base) 1.362 +{ 1.363 + struct win32op *win32op = _base->evbase; 1.364 + 1.365 + evsig_dealloc(_base); 1.366 + if (win32op->readset_in) 1.367 + mm_free(win32op->readset_in); 1.368 + if (win32op->writeset_in) 1.369 + mm_free(win32op->writeset_in); 1.370 + if (win32op->readset_out) 1.371 + mm_free(win32op->readset_out); 1.372 + if (win32op->writeset_out) 1.373 + mm_free(win32op->writeset_out); 1.374 + if (win32op->exset_out) 1.375 + mm_free(win32op->exset_out); 1.376 + /* XXXXX free the tree. */ 1.377 + 1.378 + memset(win32op, 0, sizeof(win32op)); 1.379 + mm_free(win32op); 1.380 +}