ipc/chromium/src/third_party/libevent/poll.c

changeset 0
6474c204b198
     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 +}

mercurial