xref: /aosp_15_r20/external/libevent/poll.c (revision 663afb9b963571284e0f0a60f257164ab54f64bf)
1*663afb9bSAndroid Build Coastguard Worker /*	$OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $	*/
2*663afb9bSAndroid Build Coastguard Worker 
3*663afb9bSAndroid Build Coastguard Worker /*
4*663afb9bSAndroid Build Coastguard Worker  * Copyright 2000-2007 Niels Provos <[email protected]>
5*663afb9bSAndroid Build Coastguard Worker  * Copyright 2007-2012 Niels Provos and Nick Mathewson
6*663afb9bSAndroid Build Coastguard Worker  *
7*663afb9bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
8*663afb9bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
9*663afb9bSAndroid Build Coastguard Worker  * are met:
10*663afb9bSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
11*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
12*663afb9bSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
13*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
14*663afb9bSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
15*663afb9bSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
16*663afb9bSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
17*663afb9bSAndroid Build Coastguard Worker  *
18*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*663afb9bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*663afb9bSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*663afb9bSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*663afb9bSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*663afb9bSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*663afb9bSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*663afb9bSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*663afb9bSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*663afb9bSAndroid Build Coastguard Worker  */
29*663afb9bSAndroid Build Coastguard Worker #include "event2/event-config.h"
30*663afb9bSAndroid Build Coastguard Worker #include "evconfig-private.h"
31*663afb9bSAndroid Build Coastguard Worker 
32*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_POLL
33*663afb9bSAndroid Build Coastguard Worker 
34*663afb9bSAndroid Build Coastguard Worker #include <sys/types.h>
35*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_TIME_H
36*663afb9bSAndroid Build Coastguard Worker #include <sys/time.h>
37*663afb9bSAndroid Build Coastguard Worker #endif
38*663afb9bSAndroid Build Coastguard Worker #include <sys/queue.h>
39*663afb9bSAndroid Build Coastguard Worker #include <poll.h>
40*663afb9bSAndroid Build Coastguard Worker #include <signal.h>
41*663afb9bSAndroid Build Coastguard Worker #include <limits.h>
42*663afb9bSAndroid Build Coastguard Worker #include <stdio.h>
43*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
44*663afb9bSAndroid Build Coastguard Worker #include <string.h>
45*663afb9bSAndroid Build Coastguard Worker #include <unistd.h>
46*663afb9bSAndroid Build Coastguard Worker #include <errno.h>
47*663afb9bSAndroid Build Coastguard Worker 
48*663afb9bSAndroid Build Coastguard Worker #include "event-internal.h"
49*663afb9bSAndroid Build Coastguard Worker #include "evsignal-internal.h"
50*663afb9bSAndroid Build Coastguard Worker #include "log-internal.h"
51*663afb9bSAndroid Build Coastguard Worker #include "evmap-internal.h"
52*663afb9bSAndroid Build Coastguard Worker #include "event2/thread.h"
53*663afb9bSAndroid Build Coastguard Worker #include "evthread-internal.h"
54*663afb9bSAndroid Build Coastguard Worker #include "time-internal.h"
55*663afb9bSAndroid Build Coastguard Worker 
56*663afb9bSAndroid Build Coastguard Worker /* Since Linux 2.6.17, poll is able to report about peer half-closed connection
57*663afb9bSAndroid Build Coastguard Worker    using special POLLRDHUP flag on a read event.
58*663afb9bSAndroid Build Coastguard Worker */
59*663afb9bSAndroid Build Coastguard Worker #if !defined(POLLRDHUP)
60*663afb9bSAndroid Build Coastguard Worker #define POLLRDHUP 0
61*663afb9bSAndroid Build Coastguard Worker #define EARLY_CLOSE_IF_HAVE_RDHUP 0
62*663afb9bSAndroid Build Coastguard Worker #else
63*663afb9bSAndroid Build Coastguard Worker #define EARLY_CLOSE_IF_HAVE_RDHUP EV_FEATURE_EARLY_CLOSE
64*663afb9bSAndroid Build Coastguard Worker #endif
65*663afb9bSAndroid Build Coastguard Worker 
66*663afb9bSAndroid Build Coastguard Worker 
67*663afb9bSAndroid Build Coastguard Worker struct pollidx {
68*663afb9bSAndroid Build Coastguard Worker 	int idxplus1;
69*663afb9bSAndroid Build Coastguard Worker };
70*663afb9bSAndroid Build Coastguard Worker 
71*663afb9bSAndroid Build Coastguard Worker struct pollop {
72*663afb9bSAndroid Build Coastguard Worker 	int event_count;		/* Highest number alloc */
73*663afb9bSAndroid Build Coastguard Worker 	int nfds;			/* Highest number used */
74*663afb9bSAndroid Build Coastguard Worker 	int realloc_copy;		/* True iff we must realloc
75*663afb9bSAndroid Build Coastguard Worker 					 * event_set_copy */
76*663afb9bSAndroid Build Coastguard Worker 	struct pollfd *event_set;
77*663afb9bSAndroid Build Coastguard Worker 	struct pollfd *event_set_copy;
78*663afb9bSAndroid Build Coastguard Worker };
79*663afb9bSAndroid Build Coastguard Worker 
80*663afb9bSAndroid Build Coastguard Worker static void *poll_init(struct event_base *);
81*663afb9bSAndroid Build Coastguard Worker static int poll_add(struct event_base *, int, short old, short events, void *idx);
82*663afb9bSAndroid Build Coastguard Worker static int poll_del(struct event_base *, int, short old, short events, void *idx);
83*663afb9bSAndroid Build Coastguard Worker static int poll_dispatch(struct event_base *, struct timeval *);
84*663afb9bSAndroid Build Coastguard Worker static void poll_dealloc(struct event_base *);
85*663afb9bSAndroid Build Coastguard Worker 
86*663afb9bSAndroid Build Coastguard Worker const struct eventop pollops = {
87*663afb9bSAndroid Build Coastguard Worker 	"poll",
88*663afb9bSAndroid Build Coastguard Worker 	poll_init,
89*663afb9bSAndroid Build Coastguard Worker 	poll_add,
90*663afb9bSAndroid Build Coastguard Worker 	poll_del,
91*663afb9bSAndroid Build Coastguard Worker 	poll_dispatch,
92*663afb9bSAndroid Build Coastguard Worker 	poll_dealloc,
93*663afb9bSAndroid Build Coastguard Worker 	1, /* need_reinit */
94*663afb9bSAndroid Build Coastguard Worker 	EV_FEATURE_FDS|EARLY_CLOSE_IF_HAVE_RDHUP,
95*663afb9bSAndroid Build Coastguard Worker 	sizeof(struct pollidx),
96*663afb9bSAndroid Build Coastguard Worker };
97*663afb9bSAndroid Build Coastguard Worker 
98*663afb9bSAndroid Build Coastguard Worker static void *
poll_init(struct event_base * base)99*663afb9bSAndroid Build Coastguard Worker poll_init(struct event_base *base)
100*663afb9bSAndroid Build Coastguard Worker {
101*663afb9bSAndroid Build Coastguard Worker 	struct pollop *pollop;
102*663afb9bSAndroid Build Coastguard Worker 
103*663afb9bSAndroid Build Coastguard Worker 	if (!(pollop = mm_calloc(1, sizeof(struct pollop))))
104*663afb9bSAndroid Build Coastguard Worker 		return (NULL);
105*663afb9bSAndroid Build Coastguard Worker 
106*663afb9bSAndroid Build Coastguard Worker 	evsig_init_(base);
107*663afb9bSAndroid Build Coastguard Worker 
108*663afb9bSAndroid Build Coastguard Worker 	evutil_weakrand_seed_(&base->weakrand_seed, 0);
109*663afb9bSAndroid Build Coastguard Worker 
110*663afb9bSAndroid Build Coastguard Worker 	return (pollop);
111*663afb9bSAndroid Build Coastguard Worker }
112*663afb9bSAndroid Build Coastguard Worker 
113*663afb9bSAndroid Build Coastguard Worker #ifdef CHECK_INVARIANTS
114*663afb9bSAndroid Build Coastguard Worker static void
poll_check_ok(struct pollop * pop)115*663afb9bSAndroid Build Coastguard Worker poll_check_ok(struct pollop *pop)
116*663afb9bSAndroid Build Coastguard Worker {
117*663afb9bSAndroid Build Coastguard Worker 	int i, idx;
118*663afb9bSAndroid Build Coastguard Worker 	struct event *ev;
119*663afb9bSAndroid Build Coastguard Worker 
120*663afb9bSAndroid Build Coastguard Worker 	for (i = 0; i < pop->fd_count; ++i) {
121*663afb9bSAndroid Build Coastguard Worker 		idx = pop->idxplus1_by_fd[i]-1;
122*663afb9bSAndroid Build Coastguard Worker 		if (idx < 0)
123*663afb9bSAndroid Build Coastguard Worker 			continue;
124*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(pop->event_set[idx].fd == i);
125*663afb9bSAndroid Build Coastguard Worker 	}
126*663afb9bSAndroid Build Coastguard Worker 	for (i = 0; i < pop->nfds; ++i) {
127*663afb9bSAndroid Build Coastguard Worker 		struct pollfd *pfd = &pop->event_set[i];
128*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(pop->idxplus1_by_fd[pfd->fd] == i+1);
129*663afb9bSAndroid Build Coastguard Worker 	}
130*663afb9bSAndroid Build Coastguard Worker }
131*663afb9bSAndroid Build Coastguard Worker #else
132*663afb9bSAndroid Build Coastguard Worker #define poll_check_ok(pop)
133*663afb9bSAndroid Build Coastguard Worker #endif
134*663afb9bSAndroid Build Coastguard Worker 
135*663afb9bSAndroid Build Coastguard Worker static int
poll_dispatch(struct event_base * base,struct timeval * tv)136*663afb9bSAndroid Build Coastguard Worker poll_dispatch(struct event_base *base, struct timeval *tv)
137*663afb9bSAndroid Build Coastguard Worker {
138*663afb9bSAndroid Build Coastguard Worker 	int res, i, j, nfds;
139*663afb9bSAndroid Build Coastguard Worker 	long msec = -1;
140*663afb9bSAndroid Build Coastguard Worker 	struct pollop *pop = base->evbase;
141*663afb9bSAndroid Build Coastguard Worker 	struct pollfd *event_set;
142*663afb9bSAndroid Build Coastguard Worker 
143*663afb9bSAndroid Build Coastguard Worker 	poll_check_ok(pop);
144*663afb9bSAndroid Build Coastguard Worker 
145*663afb9bSAndroid Build Coastguard Worker 	nfds = pop->nfds;
146*663afb9bSAndroid Build Coastguard Worker 
147*663afb9bSAndroid Build Coastguard Worker #ifndef EVENT__DISABLE_THREAD_SUPPORT
148*663afb9bSAndroid Build Coastguard Worker 	if (base->th_base_lock) {
149*663afb9bSAndroid Build Coastguard Worker 		/* If we're using this backend in a multithreaded setting,
150*663afb9bSAndroid Build Coastguard Worker 		 * then we need to work on a copy of event_set, so that we can
151*663afb9bSAndroid Build Coastguard Worker 		 * let other threads modify the main event_set while we're
152*663afb9bSAndroid Build Coastguard Worker 		 * polling. If we're not multithreaded, then we'll skip the
153*663afb9bSAndroid Build Coastguard Worker 		 * copy step here to save memory and time. */
154*663afb9bSAndroid Build Coastguard Worker 		if (pop->realloc_copy) {
155*663afb9bSAndroid Build Coastguard Worker 			struct pollfd *tmp = mm_realloc(pop->event_set_copy,
156*663afb9bSAndroid Build Coastguard Worker 			    pop->event_count * sizeof(struct pollfd));
157*663afb9bSAndroid Build Coastguard Worker 			if (tmp == NULL) {
158*663afb9bSAndroid Build Coastguard Worker 				event_warn("realloc");
159*663afb9bSAndroid Build Coastguard Worker 				return -1;
160*663afb9bSAndroid Build Coastguard Worker 			}
161*663afb9bSAndroid Build Coastguard Worker 			pop->event_set_copy = tmp;
162*663afb9bSAndroid Build Coastguard Worker 			pop->realloc_copy = 0;
163*663afb9bSAndroid Build Coastguard Worker 		}
164*663afb9bSAndroid Build Coastguard Worker 		memcpy(pop->event_set_copy, pop->event_set,
165*663afb9bSAndroid Build Coastguard Worker 		    sizeof(struct pollfd)*nfds);
166*663afb9bSAndroid Build Coastguard Worker 		event_set = pop->event_set_copy;
167*663afb9bSAndroid Build Coastguard Worker 	} else {
168*663afb9bSAndroid Build Coastguard Worker 		event_set = pop->event_set;
169*663afb9bSAndroid Build Coastguard Worker 	}
170*663afb9bSAndroid Build Coastguard Worker #else
171*663afb9bSAndroid Build Coastguard Worker 	event_set = pop->event_set;
172*663afb9bSAndroid Build Coastguard Worker #endif
173*663afb9bSAndroid Build Coastguard Worker 
174*663afb9bSAndroid Build Coastguard Worker 	if (tv != NULL) {
175*663afb9bSAndroid Build Coastguard Worker 		msec = evutil_tv_to_msec_(tv);
176*663afb9bSAndroid Build Coastguard Worker 		if (msec < 0 || msec > INT_MAX)
177*663afb9bSAndroid Build Coastguard Worker 			msec = INT_MAX;
178*663afb9bSAndroid Build Coastguard Worker 	}
179*663afb9bSAndroid Build Coastguard Worker 
180*663afb9bSAndroid Build Coastguard Worker 	EVBASE_RELEASE_LOCK(base, th_base_lock);
181*663afb9bSAndroid Build Coastguard Worker 
182*663afb9bSAndroid Build Coastguard Worker 	res = poll(event_set, nfds, msec);
183*663afb9bSAndroid Build Coastguard Worker 
184*663afb9bSAndroid Build Coastguard Worker 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
185*663afb9bSAndroid Build Coastguard Worker 
186*663afb9bSAndroid Build Coastguard Worker 	if (res == -1) {
187*663afb9bSAndroid Build Coastguard Worker 		if (errno != EINTR) {
188*663afb9bSAndroid Build Coastguard Worker 			event_warn("poll");
189*663afb9bSAndroid Build Coastguard Worker 			return (-1);
190*663afb9bSAndroid Build Coastguard Worker 		}
191*663afb9bSAndroid Build Coastguard Worker 
192*663afb9bSAndroid Build Coastguard Worker 		return (0);
193*663afb9bSAndroid Build Coastguard Worker 	}
194*663afb9bSAndroid Build Coastguard Worker 
195*663afb9bSAndroid Build Coastguard Worker 	event_debug(("%s: poll reports %d", __func__, res));
196*663afb9bSAndroid Build Coastguard Worker 
197*663afb9bSAndroid Build Coastguard Worker 	if (res == 0 || nfds == 0)
198*663afb9bSAndroid Build Coastguard Worker 		return (0);
199*663afb9bSAndroid Build Coastguard Worker 
200*663afb9bSAndroid Build Coastguard Worker 	i = evutil_weakrand_range_(&base->weakrand_seed, nfds);
201*663afb9bSAndroid Build Coastguard Worker 	for (j = 0; j < nfds; j++) {
202*663afb9bSAndroid Build Coastguard Worker 		int what;
203*663afb9bSAndroid Build Coastguard Worker 		if (++i == nfds)
204*663afb9bSAndroid Build Coastguard Worker 			i = 0;
205*663afb9bSAndroid Build Coastguard Worker 		what = event_set[i].revents;
206*663afb9bSAndroid Build Coastguard Worker 		if (!what)
207*663afb9bSAndroid Build Coastguard Worker 			continue;
208*663afb9bSAndroid Build Coastguard Worker 
209*663afb9bSAndroid Build Coastguard Worker 		res = 0;
210*663afb9bSAndroid Build Coastguard Worker 
211*663afb9bSAndroid Build Coastguard Worker 		/* If the file gets closed notify */
212*663afb9bSAndroid Build Coastguard Worker 		if (what & (POLLHUP|POLLERR|POLLNVAL))
213*663afb9bSAndroid Build Coastguard Worker 			what |= POLLIN|POLLOUT;
214*663afb9bSAndroid Build Coastguard Worker 		if (what & POLLIN)
215*663afb9bSAndroid Build Coastguard Worker 			res |= EV_READ;
216*663afb9bSAndroid Build Coastguard Worker 		if (what & POLLOUT)
217*663afb9bSAndroid Build Coastguard Worker 			res |= EV_WRITE;
218*663afb9bSAndroid Build Coastguard Worker 		if (what & POLLRDHUP)
219*663afb9bSAndroid Build Coastguard Worker 			res |= EV_CLOSED;
220*663afb9bSAndroid Build Coastguard Worker 		if (res == 0)
221*663afb9bSAndroid Build Coastguard Worker 			continue;
222*663afb9bSAndroid Build Coastguard Worker 
223*663afb9bSAndroid Build Coastguard Worker 		evmap_io_active_(base, event_set[i].fd, res);
224*663afb9bSAndroid Build Coastguard Worker 	}
225*663afb9bSAndroid Build Coastguard Worker 
226*663afb9bSAndroid Build Coastguard Worker 	return (0);
227*663afb9bSAndroid Build Coastguard Worker }
228*663afb9bSAndroid Build Coastguard Worker 
229*663afb9bSAndroid Build Coastguard Worker static int
poll_add(struct event_base * base,int fd,short old,short events,void * idx_)230*663afb9bSAndroid Build Coastguard Worker poll_add(struct event_base *base, int fd, short old, short events, void *idx_)
231*663afb9bSAndroid Build Coastguard Worker {
232*663afb9bSAndroid Build Coastguard Worker 	struct pollop *pop = base->evbase;
233*663afb9bSAndroid Build Coastguard Worker 	struct pollfd *pfd = NULL;
234*663afb9bSAndroid Build Coastguard Worker 	struct pollidx *idx = idx_;
235*663afb9bSAndroid Build Coastguard Worker 	int i;
236*663afb9bSAndroid Build Coastguard Worker 
237*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
238*663afb9bSAndroid Build Coastguard Worker 	if (!(events & (EV_READ|EV_WRITE|EV_CLOSED)))
239*663afb9bSAndroid Build Coastguard Worker 		return (0);
240*663afb9bSAndroid Build Coastguard Worker 
241*663afb9bSAndroid Build Coastguard Worker 	poll_check_ok(pop);
242*663afb9bSAndroid Build Coastguard Worker 	if (pop->nfds + 1 >= pop->event_count) {
243*663afb9bSAndroid Build Coastguard Worker 		struct pollfd *tmp_event_set;
244*663afb9bSAndroid Build Coastguard Worker 		int tmp_event_count;
245*663afb9bSAndroid Build Coastguard Worker 
246*663afb9bSAndroid Build Coastguard Worker 		if (pop->event_count < 32)
247*663afb9bSAndroid Build Coastguard Worker 			tmp_event_count = 32;
248*663afb9bSAndroid Build Coastguard Worker 		else
249*663afb9bSAndroid Build Coastguard Worker 			tmp_event_count = pop->event_count * 2;
250*663afb9bSAndroid Build Coastguard Worker 
251*663afb9bSAndroid Build Coastguard Worker 		/* We need more file descriptors */
252*663afb9bSAndroid Build Coastguard Worker 		tmp_event_set = mm_realloc(pop->event_set,
253*663afb9bSAndroid Build Coastguard Worker 				 tmp_event_count * sizeof(struct pollfd));
254*663afb9bSAndroid Build Coastguard Worker 		if (tmp_event_set == NULL) {
255*663afb9bSAndroid Build Coastguard Worker 			event_warn("realloc");
256*663afb9bSAndroid Build Coastguard Worker 			return (-1);
257*663afb9bSAndroid Build Coastguard Worker 		}
258*663afb9bSAndroid Build Coastguard Worker 		pop->event_set = tmp_event_set;
259*663afb9bSAndroid Build Coastguard Worker 
260*663afb9bSAndroid Build Coastguard Worker 		pop->event_count = tmp_event_count;
261*663afb9bSAndroid Build Coastguard Worker 		pop->realloc_copy = 1;
262*663afb9bSAndroid Build Coastguard Worker 	}
263*663afb9bSAndroid Build Coastguard Worker 
264*663afb9bSAndroid Build Coastguard Worker 	i = idx->idxplus1 - 1;
265*663afb9bSAndroid Build Coastguard Worker 
266*663afb9bSAndroid Build Coastguard Worker 	if (i >= 0) {
267*663afb9bSAndroid Build Coastguard Worker 		pfd = &pop->event_set[i];
268*663afb9bSAndroid Build Coastguard Worker 	} else {
269*663afb9bSAndroid Build Coastguard Worker 		i = pop->nfds++;
270*663afb9bSAndroid Build Coastguard Worker 		pfd = &pop->event_set[i];
271*663afb9bSAndroid Build Coastguard Worker 		pfd->events = 0;
272*663afb9bSAndroid Build Coastguard Worker 		pfd->fd = fd;
273*663afb9bSAndroid Build Coastguard Worker 		idx->idxplus1 = i + 1;
274*663afb9bSAndroid Build Coastguard Worker 	}
275*663afb9bSAndroid Build Coastguard Worker 
276*663afb9bSAndroid Build Coastguard Worker 	pfd->revents = 0;
277*663afb9bSAndroid Build Coastguard Worker 	if (events & EV_WRITE)
278*663afb9bSAndroid Build Coastguard Worker 		pfd->events |= POLLOUT;
279*663afb9bSAndroid Build Coastguard Worker 	if (events & EV_READ)
280*663afb9bSAndroid Build Coastguard Worker 		pfd->events |= POLLIN;
281*663afb9bSAndroid Build Coastguard Worker 	if (events & EV_CLOSED)
282*663afb9bSAndroid Build Coastguard Worker 		pfd->events |= POLLRDHUP;
283*663afb9bSAndroid Build Coastguard Worker 	poll_check_ok(pop);
284*663afb9bSAndroid Build Coastguard Worker 
285*663afb9bSAndroid Build Coastguard Worker 	return (0);
286*663afb9bSAndroid Build Coastguard Worker }
287*663afb9bSAndroid Build Coastguard Worker 
288*663afb9bSAndroid Build Coastguard Worker /*
289*663afb9bSAndroid Build Coastguard Worker  * Nothing to be done here.
290*663afb9bSAndroid Build Coastguard Worker  */
291*663afb9bSAndroid Build Coastguard Worker 
292*663afb9bSAndroid Build Coastguard Worker static int
poll_del(struct event_base * base,int fd,short old,short events,void * idx_)293*663afb9bSAndroid Build Coastguard Worker poll_del(struct event_base *base, int fd, short old, short events, void *idx_)
294*663afb9bSAndroid Build Coastguard Worker {
295*663afb9bSAndroid Build Coastguard Worker 	struct pollop *pop = base->evbase;
296*663afb9bSAndroid Build Coastguard Worker 	struct pollfd *pfd = NULL;
297*663afb9bSAndroid Build Coastguard Worker 	struct pollidx *idx = idx_;
298*663afb9bSAndroid Build Coastguard Worker 	int i;
299*663afb9bSAndroid Build Coastguard Worker 
300*663afb9bSAndroid Build Coastguard Worker 	EVUTIL_ASSERT((events & EV_SIGNAL) == 0);
301*663afb9bSAndroid Build Coastguard Worker 	if (!(events & (EV_READ|EV_WRITE|EV_CLOSED)))
302*663afb9bSAndroid Build Coastguard Worker 		return (0);
303*663afb9bSAndroid Build Coastguard Worker 
304*663afb9bSAndroid Build Coastguard Worker 	poll_check_ok(pop);
305*663afb9bSAndroid Build Coastguard Worker 	i = idx->idxplus1 - 1;
306*663afb9bSAndroid Build Coastguard Worker 	if (i < 0)
307*663afb9bSAndroid Build Coastguard Worker 		return (-1);
308*663afb9bSAndroid Build Coastguard Worker 
309*663afb9bSAndroid Build Coastguard Worker 	/* Do we still want to read or write? */
310*663afb9bSAndroid Build Coastguard Worker 	pfd = &pop->event_set[i];
311*663afb9bSAndroid Build Coastguard Worker 	if (events & EV_READ)
312*663afb9bSAndroid Build Coastguard Worker 		pfd->events &= ~POLLIN;
313*663afb9bSAndroid Build Coastguard Worker 	if (events & EV_WRITE)
314*663afb9bSAndroid Build Coastguard Worker 		pfd->events &= ~POLLOUT;
315*663afb9bSAndroid Build Coastguard Worker 	if (events & EV_CLOSED)
316*663afb9bSAndroid Build Coastguard Worker 		pfd->events &= ~POLLRDHUP;
317*663afb9bSAndroid Build Coastguard Worker 	poll_check_ok(pop);
318*663afb9bSAndroid Build Coastguard Worker 	if (pfd->events)
319*663afb9bSAndroid Build Coastguard Worker 		/* Another event cares about that fd. */
320*663afb9bSAndroid Build Coastguard Worker 		return (0);
321*663afb9bSAndroid Build Coastguard Worker 
322*663afb9bSAndroid Build Coastguard Worker 	/* Okay, so we aren't interested in that fd anymore. */
323*663afb9bSAndroid Build Coastguard Worker 	idx->idxplus1 = 0;
324*663afb9bSAndroid Build Coastguard Worker 
325*663afb9bSAndroid Build Coastguard Worker 	--pop->nfds;
326*663afb9bSAndroid Build Coastguard Worker 	if (i != pop->nfds) {
327*663afb9bSAndroid Build Coastguard Worker 		/*
328*663afb9bSAndroid Build Coastguard Worker 		 * Shift the last pollfd down into the now-unoccupied
329*663afb9bSAndroid Build Coastguard Worker 		 * position.
330*663afb9bSAndroid Build Coastguard Worker 		 */
331*663afb9bSAndroid Build Coastguard Worker 		memcpy(&pop->event_set[i], &pop->event_set[pop->nfds],
332*663afb9bSAndroid Build Coastguard Worker 		       sizeof(struct pollfd));
333*663afb9bSAndroid Build Coastguard Worker 		idx = evmap_io_get_fdinfo_(&base->io, pop->event_set[i].fd);
334*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(idx);
335*663afb9bSAndroid Build Coastguard Worker 		EVUTIL_ASSERT(idx->idxplus1 == pop->nfds + 1);
336*663afb9bSAndroid Build Coastguard Worker 		idx->idxplus1 = i + 1;
337*663afb9bSAndroid Build Coastguard Worker 	}
338*663afb9bSAndroid Build Coastguard Worker 
339*663afb9bSAndroid Build Coastguard Worker 	poll_check_ok(pop);
340*663afb9bSAndroid Build Coastguard Worker 	return (0);
341*663afb9bSAndroid Build Coastguard Worker }
342*663afb9bSAndroid Build Coastguard Worker 
343*663afb9bSAndroid Build Coastguard Worker static void
poll_dealloc(struct event_base * base)344*663afb9bSAndroid Build Coastguard Worker poll_dealloc(struct event_base *base)
345*663afb9bSAndroid Build Coastguard Worker {
346*663afb9bSAndroid Build Coastguard Worker 	struct pollop *pop = base->evbase;
347*663afb9bSAndroid Build Coastguard Worker 
348*663afb9bSAndroid Build Coastguard Worker 	evsig_dealloc_(base);
349*663afb9bSAndroid Build Coastguard Worker 	if (pop->event_set)
350*663afb9bSAndroid Build Coastguard Worker 		mm_free(pop->event_set);
351*663afb9bSAndroid Build Coastguard Worker 	if (pop->event_set_copy)
352*663afb9bSAndroid Build Coastguard Worker 		mm_free(pop->event_set_copy);
353*663afb9bSAndroid Build Coastguard Worker 
354*663afb9bSAndroid Build Coastguard Worker 	memset(pop, 0, sizeof(struct pollop));
355*663afb9bSAndroid Build Coastguard Worker 	mm_free(pop);
356*663afb9bSAndroid Build Coastguard Worker }
357*663afb9bSAndroid Build Coastguard Worker 
358*663afb9bSAndroid Build Coastguard Worker #endif /* EVENT__HAVE_POLL */
359