xref: /freebsd/contrib/ntp/sntp/libevent/win32select.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
12b15cb3dSCy Schubert /*
22b15cb3dSCy Schubert  * Copyright 2007-2012 Niels Provos and Nick Mathewson
32b15cb3dSCy Schubert  * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
42b15cb3dSCy Schubert  * Copyright 2003 Michael A. Davis <mike@datanerds.net>
52b15cb3dSCy Schubert  *
62b15cb3dSCy Schubert  * Redistribution and use in source and binary forms, with or without
72b15cb3dSCy Schubert  * modification, are permitted provided that the following conditions
82b15cb3dSCy Schubert  * are met:
92b15cb3dSCy Schubert  * 1. Redistributions of source code must retain the above copyright
102b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer.
112b15cb3dSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
122b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
132b15cb3dSCy Schubert  *    documentation and/or other materials provided with the distribution.
142b15cb3dSCy Schubert  * 3. The name of the author may not be used to endorse or promote products
152b15cb3dSCy Schubert  *    derived from this software without specific prior written permission.
162b15cb3dSCy Schubert  *
172b15cb3dSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
182b15cb3dSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
192b15cb3dSCy Schubert  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
202b15cb3dSCy Schubert  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
212b15cb3dSCy Schubert  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
222b15cb3dSCy Schubert  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232b15cb3dSCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242b15cb3dSCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252b15cb3dSCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
262b15cb3dSCy Schubert  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272b15cb3dSCy Schubert  */
282b15cb3dSCy Schubert #include "event2/event-config.h"
292b15cb3dSCy Schubert #include "evconfig-private.h"
302b15cb3dSCy Schubert 
312b15cb3dSCy Schubert #ifdef _WIN32
322b15cb3dSCy Schubert 
332b15cb3dSCy Schubert #include <winsock2.h>
342b15cb3dSCy Schubert #include <windows.h>
352b15cb3dSCy Schubert #include <sys/types.h>
362b15cb3dSCy Schubert #include <sys/queue.h>
372b15cb3dSCy Schubert #include <limits.h>
382b15cb3dSCy Schubert #include <signal.h>
392b15cb3dSCy Schubert #include <stdio.h>
402b15cb3dSCy Schubert #include <stdlib.h>
412b15cb3dSCy Schubert #include <string.h>
422b15cb3dSCy Schubert #include <errno.h>
432b15cb3dSCy Schubert 
442b15cb3dSCy Schubert #include "event2/util.h"
452b15cb3dSCy Schubert #include "util-internal.h"
462b15cb3dSCy Schubert #include "log-internal.h"
472b15cb3dSCy Schubert #include "event2/event.h"
482b15cb3dSCy Schubert #include "event-internal.h"
492b15cb3dSCy Schubert #include "evmap-internal.h"
502b15cb3dSCy Schubert #include "event2/thread.h"
512b15cb3dSCy Schubert #include "evthread-internal.h"
522b15cb3dSCy Schubert #include "time-internal.h"
532b15cb3dSCy Schubert 
542b15cb3dSCy Schubert #define XFREE(ptr) do { if (ptr) mm_free(ptr); } while (0)
552b15cb3dSCy Schubert 
562b15cb3dSCy Schubert extern struct event_list timequeue;
572b15cb3dSCy Schubert extern struct event_list addqueue;
582b15cb3dSCy Schubert 
592b15cb3dSCy Schubert struct win_fd_set {
60*a466cc55SCy Schubert 	unsigned int fd_count;
612b15cb3dSCy Schubert 	SOCKET fd_array[1];
622b15cb3dSCy Schubert };
632b15cb3dSCy Schubert 
642b15cb3dSCy Schubert /* MSDN says this is required to handle SIGFPE */
652b15cb3dSCy Schubert volatile double SIGFPE_REQ = 0.0f;
662b15cb3dSCy Schubert 
672b15cb3dSCy Schubert struct idx_info {
682b15cb3dSCy Schubert 	int read_pos_plus1;
692b15cb3dSCy Schubert 	int write_pos_plus1;
702b15cb3dSCy Schubert };
712b15cb3dSCy Schubert 
722b15cb3dSCy Schubert struct win32op {
732b15cb3dSCy Schubert 	unsigned num_fds_in_fd_sets;
742b15cb3dSCy Schubert 	int resize_out_sets;
752b15cb3dSCy Schubert 	struct win_fd_set *readset_in;
762b15cb3dSCy Schubert 	struct win_fd_set *writeset_in;
772b15cb3dSCy Schubert 	struct win_fd_set *readset_out;
782b15cb3dSCy Schubert 	struct win_fd_set *writeset_out;
792b15cb3dSCy Schubert 	struct win_fd_set *exset_out;
802b15cb3dSCy Schubert 	unsigned signals_are_broken : 1;
812b15cb3dSCy Schubert };
822b15cb3dSCy Schubert 
832b15cb3dSCy Schubert static void *win32_init(struct event_base *);
842b15cb3dSCy Schubert static int win32_add(struct event_base *, evutil_socket_t, short old, short events, void *idx_);
852b15cb3dSCy Schubert static int win32_del(struct event_base *, evutil_socket_t, short old, short events, void *idx_);
862b15cb3dSCy Schubert static int win32_dispatch(struct event_base *base, struct timeval *);
872b15cb3dSCy Schubert static void win32_dealloc(struct event_base *);
882b15cb3dSCy Schubert 
892b15cb3dSCy Schubert struct eventop win32ops = {
902b15cb3dSCy Schubert 	"win32",
912b15cb3dSCy Schubert 	win32_init,
922b15cb3dSCy Schubert 	win32_add,
932b15cb3dSCy Schubert 	win32_del,
942b15cb3dSCy Schubert 	win32_dispatch,
952b15cb3dSCy Schubert 	win32_dealloc,
962b15cb3dSCy Schubert 	0, /* doesn't need reinit */
972b15cb3dSCy Schubert 	0, /* No features supported. */
982b15cb3dSCy Schubert 	sizeof(struct idx_info),
992b15cb3dSCy Schubert };
1002b15cb3dSCy Schubert 
1012b15cb3dSCy Schubert #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
1022b15cb3dSCy Schubert 
1032b15cb3dSCy Schubert static int
grow_fd_sets(struct win32op * op,unsigned new_num_fds)1042b15cb3dSCy Schubert grow_fd_sets(struct win32op *op, unsigned new_num_fds)
1052b15cb3dSCy Schubert {
1062b15cb3dSCy Schubert 	size_t size;
1072b15cb3dSCy Schubert 
1082b15cb3dSCy Schubert 	EVUTIL_ASSERT(new_num_fds >= op->readset_in->fd_count &&
1092b15cb3dSCy Schubert 	       new_num_fds >= op->writeset_in->fd_count);
1102b15cb3dSCy Schubert 	EVUTIL_ASSERT(new_num_fds >= 1);
1112b15cb3dSCy Schubert 
1122b15cb3dSCy Schubert 	size = FD_SET_ALLOC_SIZE(new_num_fds);
1132b15cb3dSCy Schubert 	if (!(op->readset_in = mm_realloc(op->readset_in, size)))
1142b15cb3dSCy Schubert 		return (-1);
1152b15cb3dSCy Schubert 	if (!(op->writeset_in = mm_realloc(op->writeset_in, size)))
1162b15cb3dSCy Schubert 		return (-1);
1172b15cb3dSCy Schubert 	op->resize_out_sets = 1;
1182b15cb3dSCy Schubert 	op->num_fds_in_fd_sets = new_num_fds;
1192b15cb3dSCy Schubert 	return (0);
1202b15cb3dSCy Schubert }
1212b15cb3dSCy Schubert 
1222b15cb3dSCy Schubert static int
do_fd_set(struct win32op * op,struct idx_info * ent,evutil_socket_t s,int read)1232b15cb3dSCy Schubert do_fd_set(struct win32op *op, struct idx_info *ent, evutil_socket_t s, int read)
1242b15cb3dSCy Schubert {
1252b15cb3dSCy Schubert 	struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
1262b15cb3dSCy Schubert 	if (read) {
1272b15cb3dSCy Schubert 		if (ent->read_pos_plus1 > 0)
1282b15cb3dSCy Schubert 			return (0);
1292b15cb3dSCy Schubert 	} else {
1302b15cb3dSCy Schubert 		if (ent->write_pos_plus1 > 0)
1312b15cb3dSCy Schubert 			return (0);
1322b15cb3dSCy Schubert 	}
1332b15cb3dSCy Schubert 	if (set->fd_count == op->num_fds_in_fd_sets) {
1342b15cb3dSCy Schubert 		if (grow_fd_sets(op, op->num_fds_in_fd_sets*2))
1352b15cb3dSCy Schubert 			return (-1);
1362b15cb3dSCy Schubert 		/* set pointer will have changed and needs reiniting! */
1372b15cb3dSCy Schubert 		set = read ? op->readset_in : op->writeset_in;
1382b15cb3dSCy Schubert 	}
1392b15cb3dSCy Schubert 	set->fd_array[set->fd_count] = s;
1402b15cb3dSCy Schubert 	if (read)
1412b15cb3dSCy Schubert 		ent->read_pos_plus1 = set->fd_count+1;
1422b15cb3dSCy Schubert 	else
1432b15cb3dSCy Schubert 		ent->write_pos_plus1 = set->fd_count+1;
1442b15cb3dSCy Schubert 	return (set->fd_count++);
1452b15cb3dSCy Schubert }
1462b15cb3dSCy Schubert 
1472b15cb3dSCy Schubert static int
do_fd_clear(struct event_base * base,struct win32op * op,struct idx_info * ent,int read)1482b15cb3dSCy Schubert do_fd_clear(struct event_base *base,
1492b15cb3dSCy Schubert 			struct win32op *op, struct idx_info *ent, int read)
1502b15cb3dSCy Schubert {
1512b15cb3dSCy Schubert 	int i;
1522b15cb3dSCy Schubert 	struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
1532b15cb3dSCy Schubert 	if (read) {
1542b15cb3dSCy Schubert 		i = ent->read_pos_plus1 - 1;
1552b15cb3dSCy Schubert 		ent->read_pos_plus1 = 0;
1562b15cb3dSCy Schubert 	} else {
1572b15cb3dSCy Schubert 		i = ent->write_pos_plus1 - 1;
1582b15cb3dSCy Schubert 		ent->write_pos_plus1 = 0;
1592b15cb3dSCy Schubert 	}
1602b15cb3dSCy Schubert 	if (i < 0)
1612b15cb3dSCy Schubert 		return (0);
1622b15cb3dSCy Schubert 	if (--set->fd_count != (unsigned)i) {
1632b15cb3dSCy Schubert 		struct idx_info *ent2;
1642b15cb3dSCy Schubert 		SOCKET s2;
1652b15cb3dSCy Schubert 		s2 = set->fd_array[i] = set->fd_array[set->fd_count];
1662b15cb3dSCy Schubert 
1672b15cb3dSCy Schubert 		ent2 = evmap_io_get_fdinfo_(&base->io, s2);
1682b15cb3dSCy Schubert 
1692b15cb3dSCy Schubert 		if (!ent2) /* This indicates a bug. */
1702b15cb3dSCy Schubert 			return (0);
1712b15cb3dSCy Schubert 		if (read)
1722b15cb3dSCy Schubert 			ent2->read_pos_plus1 = i+1;
1732b15cb3dSCy Schubert 		else
1742b15cb3dSCy Schubert 			ent2->write_pos_plus1 = i+1;
1752b15cb3dSCy Schubert 	}
1762b15cb3dSCy Schubert 	return (0);
1772b15cb3dSCy Schubert }
1782b15cb3dSCy Schubert 
1792b15cb3dSCy Schubert #define NEVENT 32
1802b15cb3dSCy Schubert void *
win32_init(struct event_base * base)1812b15cb3dSCy Schubert win32_init(struct event_base *base)
1822b15cb3dSCy Schubert {
1832b15cb3dSCy Schubert 	struct win32op *winop;
1842b15cb3dSCy Schubert 	size_t size;
1852b15cb3dSCy Schubert 	if (!(winop = mm_calloc(1, sizeof(struct win32op))))
1862b15cb3dSCy Schubert 		return NULL;
1872b15cb3dSCy Schubert 	winop->num_fds_in_fd_sets = NEVENT;
1882b15cb3dSCy Schubert 	size = FD_SET_ALLOC_SIZE(NEVENT);
1892b15cb3dSCy Schubert 	if (!(winop->readset_in = mm_malloc(size)))
1902b15cb3dSCy Schubert 		goto err;
1912b15cb3dSCy Schubert 	if (!(winop->writeset_in = mm_malloc(size)))
1922b15cb3dSCy Schubert 		goto err;
1932b15cb3dSCy Schubert 	if (!(winop->readset_out = mm_malloc(size)))
1942b15cb3dSCy Schubert 		goto err;
1952b15cb3dSCy Schubert 	if (!(winop->writeset_out = mm_malloc(size)))
1962b15cb3dSCy Schubert 		goto err;
1972b15cb3dSCy Schubert 	if (!(winop->exset_out = mm_malloc(size)))
1982b15cb3dSCy Schubert 		goto err;
1992b15cb3dSCy Schubert 	winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
2002b15cb3dSCy Schubert 	winop->readset_out->fd_count = winop->writeset_out->fd_count
2012b15cb3dSCy Schubert 		= winop->exset_out->fd_count = 0;
2022b15cb3dSCy Schubert 
2032b15cb3dSCy Schubert 	if (evsig_init_(base) < 0)
2042b15cb3dSCy Schubert 		winop->signals_are_broken = 1;
2052b15cb3dSCy Schubert 
2062b15cb3dSCy Schubert 	evutil_weakrand_seed_(&base->weakrand_seed, 0);
2072b15cb3dSCy Schubert 
2082b15cb3dSCy Schubert 	return (winop);
2092b15cb3dSCy Schubert  err:
2102b15cb3dSCy Schubert 	XFREE(winop->readset_in);
2112b15cb3dSCy Schubert 	XFREE(winop->writeset_in);
2122b15cb3dSCy Schubert 	XFREE(winop->readset_out);
2132b15cb3dSCy Schubert 	XFREE(winop->writeset_out);
2142b15cb3dSCy Schubert 	XFREE(winop->exset_out);
2152b15cb3dSCy Schubert 	XFREE(winop);
2162b15cb3dSCy Schubert 	return (NULL);
2172b15cb3dSCy Schubert }
2182b15cb3dSCy Schubert 
2192b15cb3dSCy Schubert int
win32_add(struct event_base * base,evutil_socket_t fd,short old,short events,void * idx_)2202b15cb3dSCy Schubert win32_add(struct event_base *base, evutil_socket_t fd,
2212b15cb3dSCy Schubert 			 short old, short events, void *idx_)
2222b15cb3dSCy Schubert {
2232b15cb3dSCy Schubert 	struct win32op *win32op = base->evbase;
2242b15cb3dSCy Schubert 	struct idx_info *idx = idx_;
2252b15cb3dSCy Schubert 
2262b15cb3dSCy Schubert 	if ((events & EV_SIGNAL) && win32op->signals_are_broken)
2272b15cb3dSCy Schubert 		return (-1);
2282b15cb3dSCy Schubert 
2292b15cb3dSCy Schubert 	if (!(events & (EV_READ|EV_WRITE)))
2302b15cb3dSCy Schubert 		return (0);
2312b15cb3dSCy Schubert 
2322b15cb3dSCy Schubert 	event_debug(("%s: adding event for %d", __func__, (int)fd));
2332b15cb3dSCy Schubert 	if (events & EV_READ) {
2342b15cb3dSCy Schubert 		if (do_fd_set(win32op, idx, fd, 1)<0)
2352b15cb3dSCy Schubert 			return (-1);
2362b15cb3dSCy Schubert 	}
2372b15cb3dSCy Schubert 	if (events & EV_WRITE) {
2382b15cb3dSCy Schubert 		if (do_fd_set(win32op, idx, fd, 0)<0)
2392b15cb3dSCy Schubert 			return (-1);
2402b15cb3dSCy Schubert 	}
2412b15cb3dSCy Schubert 	return (0);
2422b15cb3dSCy Schubert }
2432b15cb3dSCy Schubert 
2442b15cb3dSCy Schubert int
win32_del(struct event_base * base,evutil_socket_t fd,short old,short events,void * idx_)2452b15cb3dSCy Schubert win32_del(struct event_base *base, evutil_socket_t fd, short old, short events,
2462b15cb3dSCy Schubert 		  void *idx_)
2472b15cb3dSCy Schubert {
2482b15cb3dSCy Schubert 	struct win32op *win32op = base->evbase;
2492b15cb3dSCy Schubert 	struct idx_info *idx = idx_;
2502b15cb3dSCy Schubert 
2512b15cb3dSCy Schubert 	event_debug(("%s: Removing event for "EV_SOCK_FMT,
2522b15cb3dSCy Schubert 		__func__, EV_SOCK_ARG(fd)));
2532b15cb3dSCy Schubert 	if (events & EV_READ)
2542b15cb3dSCy Schubert 		do_fd_clear(base, win32op, idx, 1);
2552b15cb3dSCy Schubert 	if (events & EV_WRITE)
2562b15cb3dSCy Schubert 		do_fd_clear(base, win32op, idx, 0);
2572b15cb3dSCy Schubert 
2582b15cb3dSCy Schubert 	return 0;
2592b15cb3dSCy Schubert }
2602b15cb3dSCy Schubert 
2612b15cb3dSCy Schubert static void
fd_set_copy(struct win_fd_set * out,const struct win_fd_set * in)2622b15cb3dSCy Schubert fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
2632b15cb3dSCy Schubert {
2642b15cb3dSCy Schubert 	out->fd_count = in->fd_count;
2652b15cb3dSCy Schubert 	memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
2662b15cb3dSCy Schubert }
2672b15cb3dSCy Schubert 
2682b15cb3dSCy Schubert /*
2692b15cb3dSCy Schubert   static void dump_fd_set(struct win_fd_set *s)
2702b15cb3dSCy Schubert   {
2712b15cb3dSCy Schubert   unsigned int i;
2722b15cb3dSCy Schubert   printf("[ ");
2732b15cb3dSCy Schubert   for(i=0;i<s->fd_count;++i)
2742b15cb3dSCy Schubert   printf("%d ",(int)s->fd_array[i]);
2752b15cb3dSCy Schubert   printf("]\n");
2762b15cb3dSCy Schubert   }
2772b15cb3dSCy Schubert */
2782b15cb3dSCy Schubert 
2792b15cb3dSCy Schubert int
win32_dispatch(struct event_base * base,struct timeval * tv)2802b15cb3dSCy Schubert win32_dispatch(struct event_base *base, struct timeval *tv)
2812b15cb3dSCy Schubert {
2822b15cb3dSCy Schubert 	struct win32op *win32op = base->evbase;
2832b15cb3dSCy Schubert 	int res = 0;
2842b15cb3dSCy Schubert 	unsigned j, i;
2852b15cb3dSCy Schubert 	int fd_count;
2862b15cb3dSCy Schubert 	SOCKET s;
2872b15cb3dSCy Schubert 
2882b15cb3dSCy Schubert 	if (win32op->resize_out_sets) {
2892b15cb3dSCy Schubert 		size_t size = FD_SET_ALLOC_SIZE(win32op->num_fds_in_fd_sets);
2902b15cb3dSCy Schubert 		if (!(win32op->readset_out = mm_realloc(win32op->readset_out, size)))
2912b15cb3dSCy Schubert 			return (-1);
2922b15cb3dSCy Schubert 		if (!(win32op->exset_out = mm_realloc(win32op->exset_out, size)))
2932b15cb3dSCy Schubert 			return (-1);
2942b15cb3dSCy Schubert 		if (!(win32op->writeset_out = mm_realloc(win32op->writeset_out, size)))
2952b15cb3dSCy Schubert 			return (-1);
2962b15cb3dSCy Schubert 		win32op->resize_out_sets = 0;
2972b15cb3dSCy Schubert 	}
2982b15cb3dSCy Schubert 
2992b15cb3dSCy Schubert 	fd_set_copy(win32op->readset_out, win32op->readset_in);
3002b15cb3dSCy Schubert 	fd_set_copy(win32op->exset_out, win32op->writeset_in);
3012b15cb3dSCy Schubert 	fd_set_copy(win32op->writeset_out, win32op->writeset_in);
3022b15cb3dSCy Schubert 
3032b15cb3dSCy Schubert 	fd_count =
3042b15cb3dSCy Schubert 	    (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
3052b15cb3dSCy Schubert 	    win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
3062b15cb3dSCy Schubert 
3072b15cb3dSCy Schubert 	if (!fd_count) {
3082b15cb3dSCy Schubert 		long msec = tv ? evutil_tv_to_msec_(tv) : LONG_MAX;
3092b15cb3dSCy Schubert 		/* Sleep's DWORD argument is unsigned long */
3102b15cb3dSCy Schubert 		if (msec < 0)
3112b15cb3dSCy Schubert 			msec = LONG_MAX;
3122b15cb3dSCy Schubert 		/* Windows doesn't like you to call select() with no sockets */
3132b15cb3dSCy Schubert 		Sleep(msec);
3142b15cb3dSCy Schubert 		return (0);
3152b15cb3dSCy Schubert 	}
3162b15cb3dSCy Schubert 
3172b15cb3dSCy Schubert 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3182b15cb3dSCy Schubert 
3192b15cb3dSCy Schubert 	res = select(fd_count,
3202b15cb3dSCy Schubert 		     (struct fd_set*)win32op->readset_out,
3212b15cb3dSCy Schubert 		     (struct fd_set*)win32op->writeset_out,
3222b15cb3dSCy Schubert 		     (struct fd_set*)win32op->exset_out, tv);
3232b15cb3dSCy Schubert 
3242b15cb3dSCy Schubert 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3252b15cb3dSCy Schubert 
3262b15cb3dSCy Schubert 	event_debug(("%s: select returned %d", __func__, res));
3272b15cb3dSCy Schubert 
3282b15cb3dSCy Schubert 	if (res <= 0) {
329*a466cc55SCy Schubert 		event_debug(("%s: %s", __func__,
330*a466cc55SCy Schubert 		    evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR())));
3312b15cb3dSCy Schubert 		return res;
3322b15cb3dSCy Schubert 	}
3332b15cb3dSCy Schubert 
3342b15cb3dSCy Schubert 	if (win32op->readset_out->fd_count) {
3352b15cb3dSCy Schubert 		i = evutil_weakrand_range_(&base->weakrand_seed,
3362b15cb3dSCy Schubert 		    win32op->readset_out->fd_count);
3372b15cb3dSCy Schubert 		for (j=0; j<win32op->readset_out->fd_count; ++j) {
3382b15cb3dSCy Schubert 			if (++i >= win32op->readset_out->fd_count)
3392b15cb3dSCy Schubert 				i = 0;
3402b15cb3dSCy Schubert 			s = win32op->readset_out->fd_array[i];
3412b15cb3dSCy Schubert 			evmap_io_active_(base, s, EV_READ);
3422b15cb3dSCy Schubert 		}
3432b15cb3dSCy Schubert 	}
3442b15cb3dSCy Schubert 	if (win32op->exset_out->fd_count) {
3452b15cb3dSCy Schubert 		i = evutil_weakrand_range_(&base->weakrand_seed,
3462b15cb3dSCy Schubert 		    win32op->exset_out->fd_count);
3472b15cb3dSCy Schubert 		for (j=0; j<win32op->exset_out->fd_count; ++j) {
3482b15cb3dSCy Schubert 			if (++i >= win32op->exset_out->fd_count)
3492b15cb3dSCy Schubert 				i = 0;
3502b15cb3dSCy Schubert 			s = win32op->exset_out->fd_array[i];
3512b15cb3dSCy Schubert 			evmap_io_active_(base, s, EV_WRITE);
3522b15cb3dSCy Schubert 		}
3532b15cb3dSCy Schubert 	}
3542b15cb3dSCy Schubert 	if (win32op->writeset_out->fd_count) {
3552b15cb3dSCy Schubert 		i = evutil_weakrand_range_(&base->weakrand_seed,
3562b15cb3dSCy Schubert 		    win32op->writeset_out->fd_count);
3572b15cb3dSCy Schubert 		for (j=0; j<win32op->writeset_out->fd_count; ++j) {
3582b15cb3dSCy Schubert 			if (++i >= win32op->writeset_out->fd_count)
3592b15cb3dSCy Schubert 				i = 0;
3602b15cb3dSCy Schubert 			s = win32op->writeset_out->fd_array[i];
3612b15cb3dSCy Schubert 			evmap_io_active_(base, s, EV_WRITE);
3622b15cb3dSCy Schubert 		}
3632b15cb3dSCy Schubert 	}
3642b15cb3dSCy Schubert 	return (0);
3652b15cb3dSCy Schubert }
3662b15cb3dSCy Schubert 
3672b15cb3dSCy Schubert void
win32_dealloc(struct event_base * base)3682b15cb3dSCy Schubert win32_dealloc(struct event_base *base)
3692b15cb3dSCy Schubert {
3702b15cb3dSCy Schubert 	struct win32op *win32op = base->evbase;
3712b15cb3dSCy Schubert 
3722b15cb3dSCy Schubert 	evsig_dealloc_(base);
3732b15cb3dSCy Schubert 	if (win32op->readset_in)
3742b15cb3dSCy Schubert 		mm_free(win32op->readset_in);
3752b15cb3dSCy Schubert 	if (win32op->writeset_in)
3762b15cb3dSCy Schubert 		mm_free(win32op->writeset_in);
3772b15cb3dSCy Schubert 	if (win32op->readset_out)
3782b15cb3dSCy Schubert 		mm_free(win32op->readset_out);
3792b15cb3dSCy Schubert 	if (win32op->writeset_out)
3802b15cb3dSCy Schubert 		mm_free(win32op->writeset_out);
3812b15cb3dSCy Schubert 	if (win32op->exset_out)
3822b15cb3dSCy Schubert 		mm_free(win32op->exset_out);
3832b15cb3dSCy Schubert 	/* XXXXX free the tree. */
3842b15cb3dSCy Schubert 
3852b15cb3dSCy Schubert 	memset(win32op, 0, sizeof(*win32op));
3862b15cb3dSCy Schubert 	mm_free(win32op);
3872b15cb3dSCy Schubert }
3882b15cb3dSCy Schubert 
3892b15cb3dSCy Schubert #endif
390