xref: /aosp_15_r20/external/wpa_supplicant_8/src/utils/eloop.c (revision 03f9172ca588f91df233974f4258bab95191f931)
1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker  * Event loop based on select() loop
3*03f9172cSAndroid Build Coastguard Worker  * Copyright (c) 2002-2009, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker  *
5*03f9172cSAndroid Build Coastguard Worker  * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker  * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker  */
8*03f9172cSAndroid Build Coastguard Worker 
9*03f9172cSAndroid Build Coastguard Worker #include "includes.h"
10*03f9172cSAndroid Build Coastguard Worker #include <assert.h>
11*03f9172cSAndroid Build Coastguard Worker 
12*03f9172cSAndroid Build Coastguard Worker #include "common.h"
13*03f9172cSAndroid Build Coastguard Worker #include "trace.h"
14*03f9172cSAndroid Build Coastguard Worker #include "list.h"
15*03f9172cSAndroid Build Coastguard Worker #include "eloop.h"
16*03f9172cSAndroid Build Coastguard Worker 
17*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL)
18*03f9172cSAndroid Build Coastguard Worker #error Do not define both of poll and epoll
19*03f9172cSAndroid Build Coastguard Worker #endif
20*03f9172cSAndroid Build Coastguard Worker 
21*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_KQUEUE)
22*03f9172cSAndroid Build Coastguard Worker #error Do not define both of poll and kqueue
23*03f9172cSAndroid Build Coastguard Worker #endif
24*03f9172cSAndroid Build Coastguard Worker 
25*03f9172cSAndroid Build Coastguard Worker #if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) && \
26*03f9172cSAndroid Build Coastguard Worker     !defined(CONFIG_ELOOP_KQUEUE)
27*03f9172cSAndroid Build Coastguard Worker #define CONFIG_ELOOP_SELECT
28*03f9172cSAndroid Build Coastguard Worker #endif
29*03f9172cSAndroid Build Coastguard Worker 
30*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
31*03f9172cSAndroid Build Coastguard Worker #include <poll.h>
32*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
33*03f9172cSAndroid Build Coastguard Worker 
34*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
35*03f9172cSAndroid Build Coastguard Worker #include <sys/epoll.h>
36*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
37*03f9172cSAndroid Build Coastguard Worker 
38*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
39*03f9172cSAndroid Build Coastguard Worker #include <sys/event.h>
40*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
41*03f9172cSAndroid Build Coastguard Worker 
42*03f9172cSAndroid Build Coastguard Worker struct eloop_sock {
43*03f9172cSAndroid Build Coastguard Worker 	int sock;
44*03f9172cSAndroid Build Coastguard Worker 	void *eloop_data;
45*03f9172cSAndroid Build Coastguard Worker 	void *user_data;
46*03f9172cSAndroid Build Coastguard Worker 	eloop_sock_handler handler;
47*03f9172cSAndroid Build Coastguard Worker 	WPA_TRACE_REF(eloop);
48*03f9172cSAndroid Build Coastguard Worker 	WPA_TRACE_REF(user);
49*03f9172cSAndroid Build Coastguard Worker 	WPA_TRACE_INFO
50*03f9172cSAndroid Build Coastguard Worker };
51*03f9172cSAndroid Build Coastguard Worker 
52*03f9172cSAndroid Build Coastguard Worker struct eloop_timeout {
53*03f9172cSAndroid Build Coastguard Worker 	struct dl_list list;
54*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime time;
55*03f9172cSAndroid Build Coastguard Worker 	void *eloop_data;
56*03f9172cSAndroid Build Coastguard Worker 	void *user_data;
57*03f9172cSAndroid Build Coastguard Worker 	eloop_timeout_handler handler;
58*03f9172cSAndroid Build Coastguard Worker 	WPA_TRACE_REF(eloop);
59*03f9172cSAndroid Build Coastguard Worker 	WPA_TRACE_REF(user);
60*03f9172cSAndroid Build Coastguard Worker 	WPA_TRACE_INFO
61*03f9172cSAndroid Build Coastguard Worker };
62*03f9172cSAndroid Build Coastguard Worker 
63*03f9172cSAndroid Build Coastguard Worker struct eloop_signal {
64*03f9172cSAndroid Build Coastguard Worker 	int sig;
65*03f9172cSAndroid Build Coastguard Worker 	void *user_data;
66*03f9172cSAndroid Build Coastguard Worker 	eloop_signal_handler handler;
67*03f9172cSAndroid Build Coastguard Worker 	int signaled;
68*03f9172cSAndroid Build Coastguard Worker };
69*03f9172cSAndroid Build Coastguard Worker 
70*03f9172cSAndroid Build Coastguard Worker struct eloop_sock_table {
71*03f9172cSAndroid Build Coastguard Worker 	size_t count;
72*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock *table;
73*03f9172cSAndroid Build Coastguard Worker 	eloop_event_type type;
74*03f9172cSAndroid Build Coastguard Worker 	int changed;
75*03f9172cSAndroid Build Coastguard Worker };
76*03f9172cSAndroid Build Coastguard Worker 
77*03f9172cSAndroid Build Coastguard Worker struct eloop_data {
78*03f9172cSAndroid Build Coastguard Worker 	int max_sock;
79*03f9172cSAndroid Build Coastguard Worker 
80*03f9172cSAndroid Build Coastguard Worker 	size_t count; /* sum of all table counts */
81*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
82*03f9172cSAndroid Build Coastguard Worker 	size_t max_pollfd_map; /* number of pollfds_map currently allocated */
83*03f9172cSAndroid Build Coastguard Worker 	size_t max_poll_fds; /* number of pollfds currently allocated */
84*03f9172cSAndroid Build Coastguard Worker 	struct pollfd *pollfds;
85*03f9172cSAndroid Build Coastguard Worker 	struct pollfd **pollfds_map;
86*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
87*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
88*03f9172cSAndroid Build Coastguard Worker 	int max_fd;
89*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock *fd_table;
90*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
91*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
92*03f9172cSAndroid Build Coastguard Worker 	int epollfd;
93*03f9172cSAndroid Build Coastguard Worker 	size_t epoll_max_event_num;
94*03f9172cSAndroid Build Coastguard Worker 	struct epoll_event *epoll_events;
95*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
96*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
97*03f9172cSAndroid Build Coastguard Worker 	int kqueuefd;
98*03f9172cSAndroid Build Coastguard Worker 	size_t kqueue_nevents;
99*03f9172cSAndroid Build Coastguard Worker 	struct kevent *kqueue_events;
100*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
101*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock_table readers;
102*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock_table writers;
103*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock_table exceptions;
104*03f9172cSAndroid Build Coastguard Worker 
105*03f9172cSAndroid Build Coastguard Worker 	struct dl_list timeout;
106*03f9172cSAndroid Build Coastguard Worker 
107*03f9172cSAndroid Build Coastguard Worker 	size_t signal_count;
108*03f9172cSAndroid Build Coastguard Worker 	struct eloop_signal *signals;
109*03f9172cSAndroid Build Coastguard Worker 	int signaled;
110*03f9172cSAndroid Build Coastguard Worker 	int pending_terminate;
111*03f9172cSAndroid Build Coastguard Worker 
112*03f9172cSAndroid Build Coastguard Worker 	int terminate;
113*03f9172cSAndroid Build Coastguard Worker };
114*03f9172cSAndroid Build Coastguard Worker 
115*03f9172cSAndroid Build Coastguard Worker static struct eloop_data eloop;
116*03f9172cSAndroid Build Coastguard Worker 
117*03f9172cSAndroid Build Coastguard Worker 
118*03f9172cSAndroid Build Coastguard Worker #ifdef WPA_TRACE
119*03f9172cSAndroid Build Coastguard Worker 
eloop_sigsegv_handler(int sig)120*03f9172cSAndroid Build Coastguard Worker static void eloop_sigsegv_handler(int sig)
121*03f9172cSAndroid Build Coastguard Worker {
122*03f9172cSAndroid Build Coastguard Worker 	wpa_trace_show("eloop SIGSEGV");
123*03f9172cSAndroid Build Coastguard Worker 	abort();
124*03f9172cSAndroid Build Coastguard Worker }
125*03f9172cSAndroid Build Coastguard Worker 
eloop_trace_sock_add_ref(struct eloop_sock_table * table)126*03f9172cSAndroid Build Coastguard Worker static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
127*03f9172cSAndroid Build Coastguard Worker {
128*03f9172cSAndroid Build Coastguard Worker 	size_t i;
129*03f9172cSAndroid Build Coastguard Worker 
130*03f9172cSAndroid Build Coastguard Worker 	if (table == NULL || table->table == NULL)
131*03f9172cSAndroid Build Coastguard Worker 		return;
132*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < table->count; i++) {
133*03f9172cSAndroid Build Coastguard Worker 		wpa_trace_add_ref(&table->table[i], eloop,
134*03f9172cSAndroid Build Coastguard Worker 				  table->table[i].eloop_data);
135*03f9172cSAndroid Build Coastguard Worker 		wpa_trace_add_ref(&table->table[i], user,
136*03f9172cSAndroid Build Coastguard Worker 				  table->table[i].user_data);
137*03f9172cSAndroid Build Coastguard Worker 	}
138*03f9172cSAndroid Build Coastguard Worker }
139*03f9172cSAndroid Build Coastguard Worker 
140*03f9172cSAndroid Build Coastguard Worker 
eloop_trace_sock_remove_ref(struct eloop_sock_table * table)141*03f9172cSAndroid Build Coastguard Worker static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
142*03f9172cSAndroid Build Coastguard Worker {
143*03f9172cSAndroid Build Coastguard Worker 	size_t i;
144*03f9172cSAndroid Build Coastguard Worker 
145*03f9172cSAndroid Build Coastguard Worker 	if (table == NULL || table->table == NULL)
146*03f9172cSAndroid Build Coastguard Worker 		return;
147*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < table->count; i++) {
148*03f9172cSAndroid Build Coastguard Worker 		wpa_trace_remove_ref(&table->table[i], eloop,
149*03f9172cSAndroid Build Coastguard Worker 				     table->table[i].eloop_data);
150*03f9172cSAndroid Build Coastguard Worker 		wpa_trace_remove_ref(&table->table[i], user,
151*03f9172cSAndroid Build Coastguard Worker 				     table->table[i].user_data);
152*03f9172cSAndroid Build Coastguard Worker 	}
153*03f9172cSAndroid Build Coastguard Worker }
154*03f9172cSAndroid Build Coastguard Worker 
155*03f9172cSAndroid Build Coastguard Worker #else /* WPA_TRACE */
156*03f9172cSAndroid Build Coastguard Worker 
157*03f9172cSAndroid Build Coastguard Worker #define eloop_trace_sock_add_ref(table) do { } while (0)
158*03f9172cSAndroid Build Coastguard Worker #define eloop_trace_sock_remove_ref(table) do { } while (0)
159*03f9172cSAndroid Build Coastguard Worker 
160*03f9172cSAndroid Build Coastguard Worker #endif /* WPA_TRACE */
161*03f9172cSAndroid Build Coastguard Worker 
162*03f9172cSAndroid Build Coastguard Worker 
eloop_init(void)163*03f9172cSAndroid Build Coastguard Worker int eloop_init(void)
164*03f9172cSAndroid Build Coastguard Worker {
165*03f9172cSAndroid Build Coastguard Worker 	os_memset(&eloop, 0, sizeof(eloop));
166*03f9172cSAndroid Build Coastguard Worker 	dl_list_init(&eloop.timeout);
167*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
168*03f9172cSAndroid Build Coastguard Worker 	eloop.epollfd = epoll_create1(0);
169*03f9172cSAndroid Build Coastguard Worker 	if (eloop.epollfd < 0) {
170*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s",
171*03f9172cSAndroid Build Coastguard Worker 			   __func__, strerror(errno));
172*03f9172cSAndroid Build Coastguard Worker 		return -1;
173*03f9172cSAndroid Build Coastguard Worker 	}
174*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
175*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
176*03f9172cSAndroid Build Coastguard Worker 	eloop.kqueuefd = kqueue();
177*03f9172cSAndroid Build Coastguard Worker 	if (eloop.kqueuefd < 0) {
178*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "%s: kqueue failed: %s",
179*03f9172cSAndroid Build Coastguard Worker 			   __func__, strerror(errno));
180*03f9172cSAndroid Build Coastguard Worker 		return -1;
181*03f9172cSAndroid Build Coastguard Worker 	}
182*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
183*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
184*03f9172cSAndroid Build Coastguard Worker 	eloop.readers.type = EVENT_TYPE_READ;
185*03f9172cSAndroid Build Coastguard Worker 	eloop.writers.type = EVENT_TYPE_WRITE;
186*03f9172cSAndroid Build Coastguard Worker 	eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
187*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
188*03f9172cSAndroid Build Coastguard Worker #ifdef WPA_TRACE
189*03f9172cSAndroid Build Coastguard Worker 	signal(SIGSEGV, eloop_sigsegv_handler);
190*03f9172cSAndroid Build Coastguard Worker #endif /* WPA_TRACE */
191*03f9172cSAndroid Build Coastguard Worker 	return 0;
192*03f9172cSAndroid Build Coastguard Worker }
193*03f9172cSAndroid Build Coastguard Worker 
194*03f9172cSAndroid Build Coastguard Worker 
195*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
eloop_sock_queue(int sock,eloop_event_type type)196*03f9172cSAndroid Build Coastguard Worker static int eloop_sock_queue(int sock, eloop_event_type type)
197*03f9172cSAndroid Build Coastguard Worker {
198*03f9172cSAndroid Build Coastguard Worker 	struct epoll_event ev;
199*03f9172cSAndroid Build Coastguard Worker 
200*03f9172cSAndroid Build Coastguard Worker 	os_memset(&ev, 0, sizeof(ev));
201*03f9172cSAndroid Build Coastguard Worker 	switch (type) {
202*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_READ:
203*03f9172cSAndroid Build Coastguard Worker 		ev.events = EPOLLIN;
204*03f9172cSAndroid Build Coastguard Worker 		break;
205*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_WRITE:
206*03f9172cSAndroid Build Coastguard Worker 		ev.events = EPOLLOUT;
207*03f9172cSAndroid Build Coastguard Worker 		break;
208*03f9172cSAndroid Build Coastguard Worker 	/*
209*03f9172cSAndroid Build Coastguard Worker 	 * Exceptions are always checked when using epoll, but I suppose it's
210*03f9172cSAndroid Build Coastguard Worker 	 * possible that someone registered a socket *only* for exception
211*03f9172cSAndroid Build Coastguard Worker 	 * handling.
212*03f9172cSAndroid Build Coastguard Worker 	 */
213*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_EXCEPTION:
214*03f9172cSAndroid Build Coastguard Worker 		ev.events = EPOLLERR | EPOLLHUP;
215*03f9172cSAndroid Build Coastguard Worker 		break;
216*03f9172cSAndroid Build Coastguard Worker 	}
217*03f9172cSAndroid Build Coastguard Worker 	ev.data.fd = sock;
218*03f9172cSAndroid Build Coastguard Worker 	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
219*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d failed: %s",
220*03f9172cSAndroid Build Coastguard Worker 			   __func__, sock, strerror(errno));
221*03f9172cSAndroid Build Coastguard Worker 		return -1;
222*03f9172cSAndroid Build Coastguard Worker 	}
223*03f9172cSAndroid Build Coastguard Worker 	return 0;
224*03f9172cSAndroid Build Coastguard Worker }
225*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
226*03f9172cSAndroid Build Coastguard Worker 
227*03f9172cSAndroid Build Coastguard Worker 
228*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
229*03f9172cSAndroid Build Coastguard Worker 
event_type_kevent_filter(eloop_event_type type)230*03f9172cSAndroid Build Coastguard Worker static short event_type_kevent_filter(eloop_event_type type)
231*03f9172cSAndroid Build Coastguard Worker {
232*03f9172cSAndroid Build Coastguard Worker 	switch (type) {
233*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_READ:
234*03f9172cSAndroid Build Coastguard Worker 		return EVFILT_READ;
235*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_WRITE:
236*03f9172cSAndroid Build Coastguard Worker 		return EVFILT_WRITE;
237*03f9172cSAndroid Build Coastguard Worker 	default:
238*03f9172cSAndroid Build Coastguard Worker 		return 0;
239*03f9172cSAndroid Build Coastguard Worker 	}
240*03f9172cSAndroid Build Coastguard Worker }
241*03f9172cSAndroid Build Coastguard Worker 
242*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_queue(int sock,eloop_event_type type)243*03f9172cSAndroid Build Coastguard Worker static int eloop_sock_queue(int sock, eloop_event_type type)
244*03f9172cSAndroid Build Coastguard Worker {
245*03f9172cSAndroid Build Coastguard Worker 	struct kevent ke;
246*03f9172cSAndroid Build Coastguard Worker 
247*03f9172cSAndroid Build Coastguard Worker 	EV_SET(&ke, sock, event_type_kevent_filter(type), EV_ADD, 0, 0, 0);
248*03f9172cSAndroid Build Coastguard Worker 	if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) == -1) {
249*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "%s: kevent(ADD) for fd=%d failed: %s",
250*03f9172cSAndroid Build Coastguard Worker 			   __func__, sock, strerror(errno));
251*03f9172cSAndroid Build Coastguard Worker 		return -1;
252*03f9172cSAndroid Build Coastguard Worker 	}
253*03f9172cSAndroid Build Coastguard Worker 	return 0;
254*03f9172cSAndroid Build Coastguard Worker }
255*03f9172cSAndroid Build Coastguard Worker 
256*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
257*03f9172cSAndroid Build Coastguard Worker 
258*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_add_sock(struct eloop_sock_table * table,int sock,eloop_sock_handler handler,void * eloop_data,void * user_data)259*03f9172cSAndroid Build Coastguard Worker static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
260*03f9172cSAndroid Build Coastguard Worker                                      int sock, eloop_sock_handler handler,
261*03f9172cSAndroid Build Coastguard Worker                                      void *eloop_data, void *user_data)
262*03f9172cSAndroid Build Coastguard Worker {
263*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
264*03f9172cSAndroid Build Coastguard Worker 	struct epoll_event *temp_events;
265*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
266*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
267*03f9172cSAndroid Build Coastguard Worker 	struct kevent *temp_events;
268*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
269*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
270*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock *temp_table;
271*03f9172cSAndroid Build Coastguard Worker 	size_t next;
272*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
273*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock *tmp;
274*03f9172cSAndroid Build Coastguard Worker 	int new_max_sock;
275*03f9172cSAndroid Build Coastguard Worker 
276*03f9172cSAndroid Build Coastguard Worker 	if (sock > eloop.max_sock)
277*03f9172cSAndroid Build Coastguard Worker 		new_max_sock = sock;
278*03f9172cSAndroid Build Coastguard Worker 	else
279*03f9172cSAndroid Build Coastguard Worker 		new_max_sock = eloop.max_sock;
280*03f9172cSAndroid Build Coastguard Worker 
281*03f9172cSAndroid Build Coastguard Worker 	if (table == NULL)
282*03f9172cSAndroid Build Coastguard Worker 		return -1;
283*03f9172cSAndroid Build Coastguard Worker 
284*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
285*03f9172cSAndroid Build Coastguard Worker 	if ((size_t) new_max_sock >= eloop.max_pollfd_map) {
286*03f9172cSAndroid Build Coastguard Worker 		struct pollfd **nmap;
287*03f9172cSAndroid Build Coastguard Worker 		nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50,
288*03f9172cSAndroid Build Coastguard Worker 					sizeof(struct pollfd *));
289*03f9172cSAndroid Build Coastguard Worker 		if (nmap == NULL)
290*03f9172cSAndroid Build Coastguard Worker 			return -1;
291*03f9172cSAndroid Build Coastguard Worker 
292*03f9172cSAndroid Build Coastguard Worker 		eloop.max_pollfd_map = new_max_sock + 50;
293*03f9172cSAndroid Build Coastguard Worker 		eloop.pollfds_map = nmap;
294*03f9172cSAndroid Build Coastguard Worker 	}
295*03f9172cSAndroid Build Coastguard Worker 
296*03f9172cSAndroid Build Coastguard Worker 	if (eloop.count + 1 > eloop.max_poll_fds) {
297*03f9172cSAndroid Build Coastguard Worker 		struct pollfd *n;
298*03f9172cSAndroid Build Coastguard Worker 		size_t nmax = eloop.count + 1 + 50;
299*03f9172cSAndroid Build Coastguard Worker 
300*03f9172cSAndroid Build Coastguard Worker 		n = os_realloc_array(eloop.pollfds, nmax,
301*03f9172cSAndroid Build Coastguard Worker 				     sizeof(struct pollfd));
302*03f9172cSAndroid Build Coastguard Worker 		if (n == NULL)
303*03f9172cSAndroid Build Coastguard Worker 			return -1;
304*03f9172cSAndroid Build Coastguard Worker 
305*03f9172cSAndroid Build Coastguard Worker 		eloop.max_poll_fds = nmax;
306*03f9172cSAndroid Build Coastguard Worker 		eloop.pollfds = n;
307*03f9172cSAndroid Build Coastguard Worker 	}
308*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
309*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
310*03f9172cSAndroid Build Coastguard Worker 	if (new_max_sock >= eloop.max_fd) {
311*03f9172cSAndroid Build Coastguard Worker 		next = new_max_sock + 16;
312*03f9172cSAndroid Build Coastguard Worker 		temp_table = os_realloc_array(eloop.fd_table, next,
313*03f9172cSAndroid Build Coastguard Worker 					      sizeof(struct eloop_sock));
314*03f9172cSAndroid Build Coastguard Worker 		if (temp_table == NULL)
315*03f9172cSAndroid Build Coastguard Worker 			return -1;
316*03f9172cSAndroid Build Coastguard Worker 
317*03f9172cSAndroid Build Coastguard Worker 		eloop.max_fd = next;
318*03f9172cSAndroid Build Coastguard Worker 		eloop.fd_table = temp_table;
319*03f9172cSAndroid Build Coastguard Worker 	}
320*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
321*03f9172cSAndroid Build Coastguard Worker 
322*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
323*03f9172cSAndroid Build Coastguard Worker 	if (eloop.count + 1 > eloop.epoll_max_event_num) {
324*03f9172cSAndroid Build Coastguard Worker 		next = eloop.epoll_max_event_num == 0 ? 8 :
325*03f9172cSAndroid Build Coastguard Worker 			eloop.epoll_max_event_num * 2;
326*03f9172cSAndroid Build Coastguard Worker 		temp_events = os_realloc_array(eloop.epoll_events, next,
327*03f9172cSAndroid Build Coastguard Worker 					       sizeof(struct epoll_event));
328*03f9172cSAndroid Build Coastguard Worker 		if (temp_events == NULL) {
329*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "%s: malloc for epoll failed: %s",
330*03f9172cSAndroid Build Coastguard Worker 				   __func__, strerror(errno));
331*03f9172cSAndroid Build Coastguard Worker 			return -1;
332*03f9172cSAndroid Build Coastguard Worker 		}
333*03f9172cSAndroid Build Coastguard Worker 
334*03f9172cSAndroid Build Coastguard Worker 		eloop.epoll_max_event_num = next;
335*03f9172cSAndroid Build Coastguard Worker 		eloop.epoll_events = temp_events;
336*03f9172cSAndroid Build Coastguard Worker 	}
337*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
338*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
339*03f9172cSAndroid Build Coastguard Worker 	if (eloop.count + 1 > eloop.kqueue_nevents) {
340*03f9172cSAndroid Build Coastguard Worker 		next = eloop.kqueue_nevents == 0 ? 8 : eloop.kqueue_nevents * 2;
341*03f9172cSAndroid Build Coastguard Worker 		temp_events = os_malloc(next * sizeof(*temp_events));
342*03f9172cSAndroid Build Coastguard Worker 		if (!temp_events) {
343*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR,
344*03f9172cSAndroid Build Coastguard Worker 				   "%s: malloc for kqueue failed: %s",
345*03f9172cSAndroid Build Coastguard Worker 				   __func__, strerror(errno));
346*03f9172cSAndroid Build Coastguard Worker 			return -1;
347*03f9172cSAndroid Build Coastguard Worker 		}
348*03f9172cSAndroid Build Coastguard Worker 
349*03f9172cSAndroid Build Coastguard Worker 		os_free(eloop.kqueue_events);
350*03f9172cSAndroid Build Coastguard Worker 		eloop.kqueue_events = temp_events;
351*03f9172cSAndroid Build Coastguard Worker 		eloop.kqueue_nevents = next;
352*03f9172cSAndroid Build Coastguard Worker 	}
353*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
354*03f9172cSAndroid Build Coastguard Worker 
355*03f9172cSAndroid Build Coastguard Worker 	eloop_trace_sock_remove_ref(table);
356*03f9172cSAndroid Build Coastguard Worker 	tmp = os_realloc_array(table->table, table->count + 1,
357*03f9172cSAndroid Build Coastguard Worker 			       sizeof(struct eloop_sock));
358*03f9172cSAndroid Build Coastguard Worker 	if (tmp == NULL) {
359*03f9172cSAndroid Build Coastguard Worker 		eloop_trace_sock_add_ref(table);
360*03f9172cSAndroid Build Coastguard Worker 		return -1;
361*03f9172cSAndroid Build Coastguard Worker 	}
362*03f9172cSAndroid Build Coastguard Worker 
363*03f9172cSAndroid Build Coastguard Worker 	tmp[table->count].sock = sock;
364*03f9172cSAndroid Build Coastguard Worker 	tmp[table->count].eloop_data = eloop_data;
365*03f9172cSAndroid Build Coastguard Worker 	tmp[table->count].user_data = user_data;
366*03f9172cSAndroid Build Coastguard Worker 	tmp[table->count].handler = handler;
367*03f9172cSAndroid Build Coastguard Worker 	wpa_trace_record(&tmp[table->count]);
368*03f9172cSAndroid Build Coastguard Worker 	table->count++;
369*03f9172cSAndroid Build Coastguard Worker 	table->table = tmp;
370*03f9172cSAndroid Build Coastguard Worker 	eloop.max_sock = new_max_sock;
371*03f9172cSAndroid Build Coastguard Worker 	eloop.count++;
372*03f9172cSAndroid Build Coastguard Worker 	table->changed = 1;
373*03f9172cSAndroid Build Coastguard Worker 	eloop_trace_sock_add_ref(table);
374*03f9172cSAndroid Build Coastguard Worker 
375*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
376*03f9172cSAndroid Build Coastguard Worker 	if (eloop_sock_queue(sock, table->type) < 0)
377*03f9172cSAndroid Build Coastguard Worker 		return -1;
378*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(&eloop.fd_table[sock], &table->table[table->count - 1],
379*03f9172cSAndroid Build Coastguard Worker 		  sizeof(struct eloop_sock));
380*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
381*03f9172cSAndroid Build Coastguard Worker 	return 0;
382*03f9172cSAndroid Build Coastguard Worker }
383*03f9172cSAndroid Build Coastguard Worker 
384*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_remove_sock(struct eloop_sock_table * table,int sock)385*03f9172cSAndroid Build Coastguard Worker static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
386*03f9172cSAndroid Build Coastguard Worker                                          int sock)
387*03f9172cSAndroid Build Coastguard Worker {
388*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
389*03f9172cSAndroid Build Coastguard Worker 	struct kevent ke;
390*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
391*03f9172cSAndroid Build Coastguard Worker 	size_t i;
392*03f9172cSAndroid Build Coastguard Worker 
393*03f9172cSAndroid Build Coastguard Worker 	if (table == NULL || table->table == NULL || table->count == 0)
394*03f9172cSAndroid Build Coastguard Worker 		return;
395*03f9172cSAndroid Build Coastguard Worker 
396*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < table->count; i++) {
397*03f9172cSAndroid Build Coastguard Worker 		if (table->table[i].sock == sock)
398*03f9172cSAndroid Build Coastguard Worker 			break;
399*03f9172cSAndroid Build Coastguard Worker 	}
400*03f9172cSAndroid Build Coastguard Worker 	if (i == table->count)
401*03f9172cSAndroid Build Coastguard Worker 		return;
402*03f9172cSAndroid Build Coastguard Worker 	eloop_trace_sock_remove_ref(table);
403*03f9172cSAndroid Build Coastguard Worker 	if (i != table->count - 1) {
404*03f9172cSAndroid Build Coastguard Worker 		os_memmove(&table->table[i], &table->table[i + 1],
405*03f9172cSAndroid Build Coastguard Worker 			   (table->count - i - 1) *
406*03f9172cSAndroid Build Coastguard Worker 			   sizeof(struct eloop_sock));
407*03f9172cSAndroid Build Coastguard Worker 	}
408*03f9172cSAndroid Build Coastguard Worker 	table->count--;
409*03f9172cSAndroid Build Coastguard Worker 	eloop.count--;
410*03f9172cSAndroid Build Coastguard Worker 	table->changed = 1;
411*03f9172cSAndroid Build Coastguard Worker 	eloop_trace_sock_add_ref(table);
412*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
413*03f9172cSAndroid Build Coastguard Worker 	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
414*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d failed: %s",
415*03f9172cSAndroid Build Coastguard Worker 			   __func__, sock, strerror(errno));
416*03f9172cSAndroid Build Coastguard Worker 		return;
417*03f9172cSAndroid Build Coastguard Worker 	}
418*03f9172cSAndroid Build Coastguard Worker 	os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock));
419*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
420*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
421*03f9172cSAndroid Build Coastguard Worker 	EV_SET(&ke, sock, event_type_kevent_filter(table->type), EV_DELETE, 0,
422*03f9172cSAndroid Build Coastguard Worker 	       0, 0);
423*03f9172cSAndroid Build Coastguard Worker 	if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) < 0) {
424*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "%s: kevent(DEL) for fd=%d failed: %s",
425*03f9172cSAndroid Build Coastguard Worker 			   __func__, sock, strerror(errno));
426*03f9172cSAndroid Build Coastguard Worker 		return;
427*03f9172cSAndroid Build Coastguard Worker 	}
428*03f9172cSAndroid Build Coastguard Worker 	os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock));
429*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
430*03f9172cSAndroid Build Coastguard Worker }
431*03f9172cSAndroid Build Coastguard Worker 
432*03f9172cSAndroid Build Coastguard Worker 
433*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
434*03f9172cSAndroid Build Coastguard Worker 
find_pollfd(struct pollfd ** pollfds_map,int fd,int mx)435*03f9172cSAndroid Build Coastguard Worker static struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx)
436*03f9172cSAndroid Build Coastguard Worker {
437*03f9172cSAndroid Build Coastguard Worker 	if (fd < mx && fd >= 0)
438*03f9172cSAndroid Build Coastguard Worker 		return pollfds_map[fd];
439*03f9172cSAndroid Build Coastguard Worker 	return NULL;
440*03f9172cSAndroid Build Coastguard Worker }
441*03f9172cSAndroid Build Coastguard Worker 
442*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_set_fds(struct eloop_sock_table * readers,struct eloop_sock_table * writers,struct eloop_sock_table * exceptions,struct pollfd * pollfds,struct pollfd ** pollfds_map,int max_pollfd_map)443*03f9172cSAndroid Build Coastguard Worker static int eloop_sock_table_set_fds(struct eloop_sock_table *readers,
444*03f9172cSAndroid Build Coastguard Worker 				    struct eloop_sock_table *writers,
445*03f9172cSAndroid Build Coastguard Worker 				    struct eloop_sock_table *exceptions,
446*03f9172cSAndroid Build Coastguard Worker 				    struct pollfd *pollfds,
447*03f9172cSAndroid Build Coastguard Worker 				    struct pollfd **pollfds_map,
448*03f9172cSAndroid Build Coastguard Worker 				    int max_pollfd_map)
449*03f9172cSAndroid Build Coastguard Worker {
450*03f9172cSAndroid Build Coastguard Worker 	size_t i;
451*03f9172cSAndroid Build Coastguard Worker 	int nxt = 0;
452*03f9172cSAndroid Build Coastguard Worker 	int fd;
453*03f9172cSAndroid Build Coastguard Worker 	struct pollfd *pfd;
454*03f9172cSAndroid Build Coastguard Worker 
455*03f9172cSAndroid Build Coastguard Worker 	/* Clear pollfd lookup map. It will be re-populated below. */
456*03f9172cSAndroid Build Coastguard Worker 	os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map);
457*03f9172cSAndroid Build Coastguard Worker 
458*03f9172cSAndroid Build Coastguard Worker 	if (readers && readers->table) {
459*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; i < readers->count; i++) {
460*03f9172cSAndroid Build Coastguard Worker 			fd = readers->table[i].sock;
461*03f9172cSAndroid Build Coastguard Worker 			assert(fd >= 0 && fd < max_pollfd_map);
462*03f9172cSAndroid Build Coastguard Worker 			pollfds[nxt].fd = fd;
463*03f9172cSAndroid Build Coastguard Worker 			pollfds[nxt].events = POLLIN;
464*03f9172cSAndroid Build Coastguard Worker 			pollfds[nxt].revents = 0;
465*03f9172cSAndroid Build Coastguard Worker 			pollfds_map[fd] = &(pollfds[nxt]);
466*03f9172cSAndroid Build Coastguard Worker 			nxt++;
467*03f9172cSAndroid Build Coastguard Worker 		}
468*03f9172cSAndroid Build Coastguard Worker 	}
469*03f9172cSAndroid Build Coastguard Worker 
470*03f9172cSAndroid Build Coastguard Worker 	if (writers && writers->table) {
471*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; i < writers->count; i++) {
472*03f9172cSAndroid Build Coastguard Worker 			/*
473*03f9172cSAndroid Build Coastguard Worker 			 * See if we already added this descriptor, update it
474*03f9172cSAndroid Build Coastguard Worker 			 * if so.
475*03f9172cSAndroid Build Coastguard Worker 			 */
476*03f9172cSAndroid Build Coastguard Worker 			fd = writers->table[i].sock;
477*03f9172cSAndroid Build Coastguard Worker 			assert(fd >= 0 && fd < max_pollfd_map);
478*03f9172cSAndroid Build Coastguard Worker 			pfd = pollfds_map[fd];
479*03f9172cSAndroid Build Coastguard Worker 			if (!pfd) {
480*03f9172cSAndroid Build Coastguard Worker 				pfd = &(pollfds[nxt]);
481*03f9172cSAndroid Build Coastguard Worker 				pfd->events = 0;
482*03f9172cSAndroid Build Coastguard Worker 				pfd->fd = fd;
483*03f9172cSAndroid Build Coastguard Worker 				pollfds[i].revents = 0;
484*03f9172cSAndroid Build Coastguard Worker 				pollfds_map[fd] = pfd;
485*03f9172cSAndroid Build Coastguard Worker 				nxt++;
486*03f9172cSAndroid Build Coastguard Worker 			}
487*03f9172cSAndroid Build Coastguard Worker 			pfd->events |= POLLOUT;
488*03f9172cSAndroid Build Coastguard Worker 		}
489*03f9172cSAndroid Build Coastguard Worker 	}
490*03f9172cSAndroid Build Coastguard Worker 
491*03f9172cSAndroid Build Coastguard Worker 	/*
492*03f9172cSAndroid Build Coastguard Worker 	 * Exceptions are always checked when using poll, but I suppose it's
493*03f9172cSAndroid Build Coastguard Worker 	 * possible that someone registered a socket *only* for exception
494*03f9172cSAndroid Build Coastguard Worker 	 * handling. Set the POLLIN bit in this case.
495*03f9172cSAndroid Build Coastguard Worker 	 */
496*03f9172cSAndroid Build Coastguard Worker 	if (exceptions && exceptions->table) {
497*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; i < exceptions->count; i++) {
498*03f9172cSAndroid Build Coastguard Worker 			/*
499*03f9172cSAndroid Build Coastguard Worker 			 * See if we already added this descriptor, just use it
500*03f9172cSAndroid Build Coastguard Worker 			 * if so.
501*03f9172cSAndroid Build Coastguard Worker 			 */
502*03f9172cSAndroid Build Coastguard Worker 			fd = exceptions->table[i].sock;
503*03f9172cSAndroid Build Coastguard Worker 			assert(fd >= 0 && fd < max_pollfd_map);
504*03f9172cSAndroid Build Coastguard Worker 			pfd = pollfds_map[fd];
505*03f9172cSAndroid Build Coastguard Worker 			if (!pfd) {
506*03f9172cSAndroid Build Coastguard Worker 				pfd = &(pollfds[nxt]);
507*03f9172cSAndroid Build Coastguard Worker 				pfd->events = POLLIN;
508*03f9172cSAndroid Build Coastguard Worker 				pfd->fd = fd;
509*03f9172cSAndroid Build Coastguard Worker 				pollfds[i].revents = 0;
510*03f9172cSAndroid Build Coastguard Worker 				pollfds_map[fd] = pfd;
511*03f9172cSAndroid Build Coastguard Worker 				nxt++;
512*03f9172cSAndroid Build Coastguard Worker 			}
513*03f9172cSAndroid Build Coastguard Worker 		}
514*03f9172cSAndroid Build Coastguard Worker 	}
515*03f9172cSAndroid Build Coastguard Worker 
516*03f9172cSAndroid Build Coastguard Worker 	return nxt;
517*03f9172cSAndroid Build Coastguard Worker }
518*03f9172cSAndroid Build Coastguard Worker 
519*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_dispatch_table(struct eloop_sock_table * table,struct pollfd ** pollfds_map,int max_pollfd_map,short int revents)520*03f9172cSAndroid Build Coastguard Worker static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table,
521*03f9172cSAndroid Build Coastguard Worker 					   struct pollfd **pollfds_map,
522*03f9172cSAndroid Build Coastguard Worker 					   int max_pollfd_map,
523*03f9172cSAndroid Build Coastguard Worker 					   short int revents)
524*03f9172cSAndroid Build Coastguard Worker {
525*03f9172cSAndroid Build Coastguard Worker 	size_t i;
526*03f9172cSAndroid Build Coastguard Worker 	struct pollfd *pfd;
527*03f9172cSAndroid Build Coastguard Worker 
528*03f9172cSAndroid Build Coastguard Worker 	if (!table || !table->table)
529*03f9172cSAndroid Build Coastguard Worker 		return 0;
530*03f9172cSAndroid Build Coastguard Worker 
531*03f9172cSAndroid Build Coastguard Worker 	table->changed = 0;
532*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < table->count; i++) {
533*03f9172cSAndroid Build Coastguard Worker 		pfd = find_pollfd(pollfds_map, table->table[i].sock,
534*03f9172cSAndroid Build Coastguard Worker 				  max_pollfd_map);
535*03f9172cSAndroid Build Coastguard Worker 		if (!pfd)
536*03f9172cSAndroid Build Coastguard Worker 			continue;
537*03f9172cSAndroid Build Coastguard Worker 
538*03f9172cSAndroid Build Coastguard Worker 		if (!(pfd->revents & revents))
539*03f9172cSAndroid Build Coastguard Worker 			continue;
540*03f9172cSAndroid Build Coastguard Worker 
541*03f9172cSAndroid Build Coastguard Worker 		table->table[i].handler(table->table[i].sock,
542*03f9172cSAndroid Build Coastguard Worker 					table->table[i].eloop_data,
543*03f9172cSAndroid Build Coastguard Worker 					table->table[i].user_data);
544*03f9172cSAndroid Build Coastguard Worker 		if (table->changed)
545*03f9172cSAndroid Build Coastguard Worker 			return 1;
546*03f9172cSAndroid Build Coastguard Worker 	}
547*03f9172cSAndroid Build Coastguard Worker 
548*03f9172cSAndroid Build Coastguard Worker 	return 0;
549*03f9172cSAndroid Build Coastguard Worker }
550*03f9172cSAndroid Build Coastguard Worker 
551*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_dispatch(struct eloop_sock_table * readers,struct eloop_sock_table * writers,struct eloop_sock_table * exceptions,struct pollfd ** pollfds_map,int max_pollfd_map)552*03f9172cSAndroid Build Coastguard Worker static void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
553*03f9172cSAndroid Build Coastguard Worker 				      struct eloop_sock_table *writers,
554*03f9172cSAndroid Build Coastguard Worker 				      struct eloop_sock_table *exceptions,
555*03f9172cSAndroid Build Coastguard Worker 				      struct pollfd **pollfds_map,
556*03f9172cSAndroid Build Coastguard Worker 				      int max_pollfd_map)
557*03f9172cSAndroid Build Coastguard Worker {
558*03f9172cSAndroid Build Coastguard Worker 	if (eloop_sock_table_dispatch_table(readers, pollfds_map,
559*03f9172cSAndroid Build Coastguard Worker 					    max_pollfd_map, POLLIN | POLLERR |
560*03f9172cSAndroid Build Coastguard Worker 					    POLLHUP))
561*03f9172cSAndroid Build Coastguard Worker 		return; /* pollfds may be invalid at this point */
562*03f9172cSAndroid Build Coastguard Worker 
563*03f9172cSAndroid Build Coastguard Worker 	if (eloop_sock_table_dispatch_table(writers, pollfds_map,
564*03f9172cSAndroid Build Coastguard Worker 					    max_pollfd_map, POLLOUT))
565*03f9172cSAndroid Build Coastguard Worker 		return; /* pollfds may be invalid at this point */
566*03f9172cSAndroid Build Coastguard Worker 
567*03f9172cSAndroid Build Coastguard Worker 	eloop_sock_table_dispatch_table(exceptions, pollfds_map,
568*03f9172cSAndroid Build Coastguard Worker 					max_pollfd_map, POLLERR | POLLHUP);
569*03f9172cSAndroid Build Coastguard Worker }
570*03f9172cSAndroid Build Coastguard Worker 
571*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
572*03f9172cSAndroid Build Coastguard Worker 
573*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
574*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_set_fds(struct eloop_sock_table * table,fd_set * fds)575*03f9172cSAndroid Build Coastguard Worker static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
576*03f9172cSAndroid Build Coastguard Worker 				     fd_set *fds)
577*03f9172cSAndroid Build Coastguard Worker {
578*03f9172cSAndroid Build Coastguard Worker 	size_t i;
579*03f9172cSAndroid Build Coastguard Worker 
580*03f9172cSAndroid Build Coastguard Worker 	FD_ZERO(fds);
581*03f9172cSAndroid Build Coastguard Worker 
582*03f9172cSAndroid Build Coastguard Worker 	if (table->table == NULL)
583*03f9172cSAndroid Build Coastguard Worker 		return;
584*03f9172cSAndroid Build Coastguard Worker 
585*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < table->count; i++) {
586*03f9172cSAndroid Build Coastguard Worker 		assert(table->table[i].sock >= 0);
587*03f9172cSAndroid Build Coastguard Worker 		FD_SET(table->table[i].sock, fds);
588*03f9172cSAndroid Build Coastguard Worker 	}
589*03f9172cSAndroid Build Coastguard Worker }
590*03f9172cSAndroid Build Coastguard Worker 
591*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_dispatch(struct eloop_sock_table * table,fd_set * fds)592*03f9172cSAndroid Build Coastguard Worker static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
593*03f9172cSAndroid Build Coastguard Worker 				      fd_set *fds)
594*03f9172cSAndroid Build Coastguard Worker {
595*03f9172cSAndroid Build Coastguard Worker 	size_t i;
596*03f9172cSAndroid Build Coastguard Worker 
597*03f9172cSAndroid Build Coastguard Worker 	if (table == NULL || table->table == NULL)
598*03f9172cSAndroid Build Coastguard Worker 		return;
599*03f9172cSAndroid Build Coastguard Worker 
600*03f9172cSAndroid Build Coastguard Worker 	table->changed = 0;
601*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < table->count; i++) {
602*03f9172cSAndroid Build Coastguard Worker 		if (FD_ISSET(table->table[i].sock, fds)) {
603*03f9172cSAndroid Build Coastguard Worker 			table->table[i].handler(table->table[i].sock,
604*03f9172cSAndroid Build Coastguard Worker 						table->table[i].eloop_data,
605*03f9172cSAndroid Build Coastguard Worker 						table->table[i].user_data);
606*03f9172cSAndroid Build Coastguard Worker 			if (table->changed)
607*03f9172cSAndroid Build Coastguard Worker 				break;
608*03f9172cSAndroid Build Coastguard Worker 		}
609*03f9172cSAndroid Build Coastguard Worker 	}
610*03f9172cSAndroid Build Coastguard Worker }
611*03f9172cSAndroid Build Coastguard Worker 
612*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
613*03f9172cSAndroid Build Coastguard Worker 
614*03f9172cSAndroid Build Coastguard Worker 
615*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
eloop_sock_table_dispatch(struct epoll_event * events,int nfds)616*03f9172cSAndroid Build Coastguard Worker static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
617*03f9172cSAndroid Build Coastguard Worker {
618*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock *table;
619*03f9172cSAndroid Build Coastguard Worker 	int i;
620*03f9172cSAndroid Build Coastguard Worker 
621*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < nfds; i++) {
622*03f9172cSAndroid Build Coastguard Worker 		table = &eloop.fd_table[events[i].data.fd];
623*03f9172cSAndroid Build Coastguard Worker 		if (table->handler == NULL)
624*03f9172cSAndroid Build Coastguard Worker 			continue;
625*03f9172cSAndroid Build Coastguard Worker 		table->handler(table->sock, table->eloop_data,
626*03f9172cSAndroid Build Coastguard Worker 			       table->user_data);
627*03f9172cSAndroid Build Coastguard Worker 		if (eloop.readers.changed ||
628*03f9172cSAndroid Build Coastguard Worker 		    eloop.writers.changed ||
629*03f9172cSAndroid Build Coastguard Worker 		    eloop.exceptions.changed)
630*03f9172cSAndroid Build Coastguard Worker 			break;
631*03f9172cSAndroid Build Coastguard Worker 	}
632*03f9172cSAndroid Build Coastguard Worker }
633*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
634*03f9172cSAndroid Build Coastguard Worker 
635*03f9172cSAndroid Build Coastguard Worker 
636*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
637*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_dispatch(struct kevent * events,int nfds)638*03f9172cSAndroid Build Coastguard Worker static void eloop_sock_table_dispatch(struct kevent *events, int nfds)
639*03f9172cSAndroid Build Coastguard Worker {
640*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock *table;
641*03f9172cSAndroid Build Coastguard Worker 	int i;
642*03f9172cSAndroid Build Coastguard Worker 
643*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < nfds; i++) {
644*03f9172cSAndroid Build Coastguard Worker 		table = &eloop.fd_table[events[i].ident];
645*03f9172cSAndroid Build Coastguard Worker 		if (table->handler == NULL)
646*03f9172cSAndroid Build Coastguard Worker 			continue;
647*03f9172cSAndroid Build Coastguard Worker 		table->handler(table->sock, table->eloop_data,
648*03f9172cSAndroid Build Coastguard Worker 			       table->user_data);
649*03f9172cSAndroid Build Coastguard Worker 		if (eloop.readers.changed ||
650*03f9172cSAndroid Build Coastguard Worker 		    eloop.writers.changed ||
651*03f9172cSAndroid Build Coastguard Worker 		    eloop.exceptions.changed)
652*03f9172cSAndroid Build Coastguard Worker 			break;
653*03f9172cSAndroid Build Coastguard Worker 	}
654*03f9172cSAndroid Build Coastguard Worker }
655*03f9172cSAndroid Build Coastguard Worker 
656*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_requeue(struct eloop_sock_table * table)657*03f9172cSAndroid Build Coastguard Worker static int eloop_sock_table_requeue(struct eloop_sock_table *table)
658*03f9172cSAndroid Build Coastguard Worker {
659*03f9172cSAndroid Build Coastguard Worker 	size_t i;
660*03f9172cSAndroid Build Coastguard Worker 	int r;
661*03f9172cSAndroid Build Coastguard Worker 
662*03f9172cSAndroid Build Coastguard Worker 	r = 0;
663*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < table->count && table->table; i++) {
664*03f9172cSAndroid Build Coastguard Worker 		if (eloop_sock_queue(table->table[i].sock, table->type) == -1)
665*03f9172cSAndroid Build Coastguard Worker 			r = -1;
666*03f9172cSAndroid Build Coastguard Worker 	}
667*03f9172cSAndroid Build Coastguard Worker 	return r;
668*03f9172cSAndroid Build Coastguard Worker }
669*03f9172cSAndroid Build Coastguard Worker 
670*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
671*03f9172cSAndroid Build Coastguard Worker 
672*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_requeue(void)673*03f9172cSAndroid Build Coastguard Worker int eloop_sock_requeue(void)
674*03f9172cSAndroid Build Coastguard Worker {
675*03f9172cSAndroid Build Coastguard Worker 	int r = 0;
676*03f9172cSAndroid Build Coastguard Worker 
677*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
678*03f9172cSAndroid Build Coastguard Worker 	close(eloop.kqueuefd);
679*03f9172cSAndroid Build Coastguard Worker 	eloop.kqueuefd = kqueue();
680*03f9172cSAndroid Build Coastguard Worker 	if (eloop.kqueuefd < 0) {
681*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_ERROR, "%s: kqueue failed: %s",
682*03f9172cSAndroid Build Coastguard Worker 			   __func__, strerror(errno));
683*03f9172cSAndroid Build Coastguard Worker 		return -1;
684*03f9172cSAndroid Build Coastguard Worker 	}
685*03f9172cSAndroid Build Coastguard Worker 
686*03f9172cSAndroid Build Coastguard Worker 	if (eloop_sock_table_requeue(&eloop.readers) < 0)
687*03f9172cSAndroid Build Coastguard Worker 		r = -1;
688*03f9172cSAndroid Build Coastguard Worker 	if (eloop_sock_table_requeue(&eloop.writers) < 0)
689*03f9172cSAndroid Build Coastguard Worker 		r = -1;
690*03f9172cSAndroid Build Coastguard Worker 	if (eloop_sock_table_requeue(&eloop.exceptions) < 0)
691*03f9172cSAndroid Build Coastguard Worker 		r = -1;
692*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
693*03f9172cSAndroid Build Coastguard Worker 
694*03f9172cSAndroid Build Coastguard Worker 	return r;
695*03f9172cSAndroid Build Coastguard Worker }
696*03f9172cSAndroid Build Coastguard Worker 
697*03f9172cSAndroid Build Coastguard Worker 
eloop_sock_table_destroy(struct eloop_sock_table * table)698*03f9172cSAndroid Build Coastguard Worker static void eloop_sock_table_destroy(struct eloop_sock_table *table)
699*03f9172cSAndroid Build Coastguard Worker {
700*03f9172cSAndroid Build Coastguard Worker 	if (table) {
701*03f9172cSAndroid Build Coastguard Worker 		size_t i;
702*03f9172cSAndroid Build Coastguard Worker 
703*03f9172cSAndroid Build Coastguard Worker 		for (i = 0; i < table->count && table->table; i++) {
704*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
705*03f9172cSAndroid Build Coastguard Worker 				   "sock=%d eloop_data=%p user_data=%p "
706*03f9172cSAndroid Build Coastguard Worker 				   "handler=%p",
707*03f9172cSAndroid Build Coastguard Worker 				   table->table[i].sock,
708*03f9172cSAndroid Build Coastguard Worker 				   table->table[i].eloop_data,
709*03f9172cSAndroid Build Coastguard Worker 				   table->table[i].user_data,
710*03f9172cSAndroid Build Coastguard Worker 				   table->table[i].handler);
711*03f9172cSAndroid Build Coastguard Worker 			wpa_trace_dump_funcname("eloop unregistered socket "
712*03f9172cSAndroid Build Coastguard Worker 						"handler",
713*03f9172cSAndroid Build Coastguard Worker 						table->table[i].handler);
714*03f9172cSAndroid Build Coastguard Worker 			wpa_trace_dump("eloop sock", &table->table[i]);
715*03f9172cSAndroid Build Coastguard Worker 		}
716*03f9172cSAndroid Build Coastguard Worker 		os_free(table->table);
717*03f9172cSAndroid Build Coastguard Worker 	}
718*03f9172cSAndroid Build Coastguard Worker }
719*03f9172cSAndroid Build Coastguard Worker 
720*03f9172cSAndroid Build Coastguard Worker 
eloop_register_read_sock(int sock,eloop_sock_handler handler,void * eloop_data,void * user_data)721*03f9172cSAndroid Build Coastguard Worker int eloop_register_read_sock(int sock, eloop_sock_handler handler,
722*03f9172cSAndroid Build Coastguard Worker 			     void *eloop_data, void *user_data)
723*03f9172cSAndroid Build Coastguard Worker {
724*03f9172cSAndroid Build Coastguard Worker 	return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
725*03f9172cSAndroid Build Coastguard Worker 				   eloop_data, user_data);
726*03f9172cSAndroid Build Coastguard Worker }
727*03f9172cSAndroid Build Coastguard Worker 
728*03f9172cSAndroid Build Coastguard Worker 
eloop_unregister_read_sock(int sock)729*03f9172cSAndroid Build Coastguard Worker void eloop_unregister_read_sock(int sock)
730*03f9172cSAndroid Build Coastguard Worker {
731*03f9172cSAndroid Build Coastguard Worker 	eloop_unregister_sock(sock, EVENT_TYPE_READ);
732*03f9172cSAndroid Build Coastguard Worker }
733*03f9172cSAndroid Build Coastguard Worker 
734*03f9172cSAndroid Build Coastguard Worker 
eloop_get_sock_table(eloop_event_type type)735*03f9172cSAndroid Build Coastguard Worker static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
736*03f9172cSAndroid Build Coastguard Worker {
737*03f9172cSAndroid Build Coastguard Worker 	switch (type) {
738*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_READ:
739*03f9172cSAndroid Build Coastguard Worker 		return &eloop.readers;
740*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_WRITE:
741*03f9172cSAndroid Build Coastguard Worker 		return &eloop.writers;
742*03f9172cSAndroid Build Coastguard Worker 	case EVENT_TYPE_EXCEPTION:
743*03f9172cSAndroid Build Coastguard Worker 		return &eloop.exceptions;
744*03f9172cSAndroid Build Coastguard Worker 	}
745*03f9172cSAndroid Build Coastguard Worker 
746*03f9172cSAndroid Build Coastguard Worker 	return NULL;
747*03f9172cSAndroid Build Coastguard Worker }
748*03f9172cSAndroid Build Coastguard Worker 
749*03f9172cSAndroid Build Coastguard Worker 
eloop_register_sock(int sock,eloop_event_type type,eloop_sock_handler handler,void * eloop_data,void * user_data)750*03f9172cSAndroid Build Coastguard Worker int eloop_register_sock(int sock, eloop_event_type type,
751*03f9172cSAndroid Build Coastguard Worker 			eloop_sock_handler handler,
752*03f9172cSAndroid Build Coastguard Worker 			void *eloop_data, void *user_data)
753*03f9172cSAndroid Build Coastguard Worker {
754*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock_table *table;
755*03f9172cSAndroid Build Coastguard Worker 
756*03f9172cSAndroid Build Coastguard Worker 	assert(sock >= 0);
757*03f9172cSAndroid Build Coastguard Worker 	table = eloop_get_sock_table(type);
758*03f9172cSAndroid Build Coastguard Worker 	return eloop_sock_table_add_sock(table, sock, handler,
759*03f9172cSAndroid Build Coastguard Worker 					 eloop_data, user_data);
760*03f9172cSAndroid Build Coastguard Worker }
761*03f9172cSAndroid Build Coastguard Worker 
762*03f9172cSAndroid Build Coastguard Worker 
eloop_unregister_sock(int sock,eloop_event_type type)763*03f9172cSAndroid Build Coastguard Worker void eloop_unregister_sock(int sock, eloop_event_type type)
764*03f9172cSAndroid Build Coastguard Worker {
765*03f9172cSAndroid Build Coastguard Worker 	struct eloop_sock_table *table;
766*03f9172cSAndroid Build Coastguard Worker 
767*03f9172cSAndroid Build Coastguard Worker 	table = eloop_get_sock_table(type);
768*03f9172cSAndroid Build Coastguard Worker 	eloop_sock_table_remove_sock(table, sock);
769*03f9172cSAndroid Build Coastguard Worker }
770*03f9172cSAndroid Build Coastguard Worker 
771*03f9172cSAndroid Build Coastguard Worker 
eloop_register_timeout(unsigned int secs,unsigned int usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)772*03f9172cSAndroid Build Coastguard Worker int eloop_register_timeout(unsigned int secs, unsigned int usecs,
773*03f9172cSAndroid Build Coastguard Worker 			   eloop_timeout_handler handler,
774*03f9172cSAndroid Build Coastguard Worker 			   void *eloop_data, void *user_data)
775*03f9172cSAndroid Build Coastguard Worker {
776*03f9172cSAndroid Build Coastguard Worker 	struct eloop_timeout *timeout, *tmp;
777*03f9172cSAndroid Build Coastguard Worker 	os_time_t now_sec;
778*03f9172cSAndroid Build Coastguard Worker 
779*03f9172cSAndroid Build Coastguard Worker 	timeout = os_zalloc(sizeof(*timeout));
780*03f9172cSAndroid Build Coastguard Worker 	if (timeout == NULL)
781*03f9172cSAndroid Build Coastguard Worker 		return -1;
782*03f9172cSAndroid Build Coastguard Worker 	if (os_get_reltime(&timeout->time) < 0) {
783*03f9172cSAndroid Build Coastguard Worker 		os_free(timeout);
784*03f9172cSAndroid Build Coastguard Worker 		return -1;
785*03f9172cSAndroid Build Coastguard Worker 	}
786*03f9172cSAndroid Build Coastguard Worker 	now_sec = timeout->time.sec;
787*03f9172cSAndroid Build Coastguard Worker 	timeout->time.sec += secs;
788*03f9172cSAndroid Build Coastguard Worker 	if (timeout->time.sec < now_sec)
789*03f9172cSAndroid Build Coastguard Worker 		goto overflow;
790*03f9172cSAndroid Build Coastguard Worker 	timeout->time.usec += usecs;
791*03f9172cSAndroid Build Coastguard Worker 	while (timeout->time.usec >= 1000000) {
792*03f9172cSAndroid Build Coastguard Worker 		timeout->time.sec++;
793*03f9172cSAndroid Build Coastguard Worker 		timeout->time.usec -= 1000000;
794*03f9172cSAndroid Build Coastguard Worker 	}
795*03f9172cSAndroid Build Coastguard Worker 	if (timeout->time.sec < now_sec)
796*03f9172cSAndroid Build Coastguard Worker 		goto overflow;
797*03f9172cSAndroid Build Coastguard Worker 	timeout->eloop_data = eloop_data;
798*03f9172cSAndroid Build Coastguard Worker 	timeout->user_data = user_data;
799*03f9172cSAndroid Build Coastguard Worker 	timeout->handler = handler;
800*03f9172cSAndroid Build Coastguard Worker 	wpa_trace_add_ref(timeout, eloop, eloop_data);
801*03f9172cSAndroid Build Coastguard Worker 	wpa_trace_add_ref(timeout, user, user_data);
802*03f9172cSAndroid Build Coastguard Worker 	wpa_trace_record(timeout);
803*03f9172cSAndroid Build Coastguard Worker 
804*03f9172cSAndroid Build Coastguard Worker 	/* Maintain timeouts in order of increasing time */
805*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
806*03f9172cSAndroid Build Coastguard Worker 		if (os_reltime_before(&timeout->time, &tmp->time)) {
807*03f9172cSAndroid Build Coastguard Worker 			dl_list_add(tmp->list.prev, &timeout->list);
808*03f9172cSAndroid Build Coastguard Worker 			return 0;
809*03f9172cSAndroid Build Coastguard Worker 		}
810*03f9172cSAndroid Build Coastguard Worker 	}
811*03f9172cSAndroid Build Coastguard Worker 	dl_list_add_tail(&eloop.timeout, &timeout->list);
812*03f9172cSAndroid Build Coastguard Worker 
813*03f9172cSAndroid Build Coastguard Worker 	return 0;
814*03f9172cSAndroid Build Coastguard Worker 
815*03f9172cSAndroid Build Coastguard Worker overflow:
816*03f9172cSAndroid Build Coastguard Worker 	/*
817*03f9172cSAndroid Build Coastguard Worker 	 * Integer overflow - assume long enough timeout to be assumed
818*03f9172cSAndroid Build Coastguard Worker 	 * to be infinite, i.e., the timeout would never happen.
819*03f9172cSAndroid Build Coastguard Worker 	 */
820*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_DEBUG,
821*03f9172cSAndroid Build Coastguard Worker 		   "ELOOP: Too long timeout (secs=%u usecs=%u) to ever happen - ignore it",
822*03f9172cSAndroid Build Coastguard Worker 		   secs,usecs);
823*03f9172cSAndroid Build Coastguard Worker 	os_free(timeout);
824*03f9172cSAndroid Build Coastguard Worker 	return 0;
825*03f9172cSAndroid Build Coastguard Worker }
826*03f9172cSAndroid Build Coastguard Worker 
827*03f9172cSAndroid Build Coastguard Worker 
eloop_remove_timeout(struct eloop_timeout * timeout)828*03f9172cSAndroid Build Coastguard Worker static void eloop_remove_timeout(struct eloop_timeout *timeout)
829*03f9172cSAndroid Build Coastguard Worker {
830*03f9172cSAndroid Build Coastguard Worker 	dl_list_del(&timeout->list);
831*03f9172cSAndroid Build Coastguard Worker 	wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
832*03f9172cSAndroid Build Coastguard Worker 	wpa_trace_remove_ref(timeout, user, timeout->user_data);
833*03f9172cSAndroid Build Coastguard Worker 	os_free(timeout);
834*03f9172cSAndroid Build Coastguard Worker }
835*03f9172cSAndroid Build Coastguard Worker 
836*03f9172cSAndroid Build Coastguard Worker 
eloop_cancel_timeout(eloop_timeout_handler handler,void * eloop_data,void * user_data)837*03f9172cSAndroid Build Coastguard Worker int eloop_cancel_timeout(eloop_timeout_handler handler,
838*03f9172cSAndroid Build Coastguard Worker 			 void *eloop_data, void *user_data)
839*03f9172cSAndroid Build Coastguard Worker {
840*03f9172cSAndroid Build Coastguard Worker 	struct eloop_timeout *timeout, *prev;
841*03f9172cSAndroid Build Coastguard Worker 	int removed = 0;
842*03f9172cSAndroid Build Coastguard Worker 
843*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
844*03f9172cSAndroid Build Coastguard Worker 			      struct eloop_timeout, list) {
845*03f9172cSAndroid Build Coastguard Worker 		if (timeout->handler == handler &&
846*03f9172cSAndroid Build Coastguard Worker 		    (timeout->eloop_data == eloop_data ||
847*03f9172cSAndroid Build Coastguard Worker 		     eloop_data == ELOOP_ALL_CTX) &&
848*03f9172cSAndroid Build Coastguard Worker 		    (timeout->user_data == user_data ||
849*03f9172cSAndroid Build Coastguard Worker 		     user_data == ELOOP_ALL_CTX)) {
850*03f9172cSAndroid Build Coastguard Worker 			eloop_remove_timeout(timeout);
851*03f9172cSAndroid Build Coastguard Worker 			removed++;
852*03f9172cSAndroid Build Coastguard Worker 		}
853*03f9172cSAndroid Build Coastguard Worker 	}
854*03f9172cSAndroid Build Coastguard Worker 
855*03f9172cSAndroid Build Coastguard Worker 	return removed;
856*03f9172cSAndroid Build Coastguard Worker }
857*03f9172cSAndroid Build Coastguard Worker 
858*03f9172cSAndroid Build Coastguard Worker 
eloop_cancel_timeout_one(eloop_timeout_handler handler,void * eloop_data,void * user_data,struct os_reltime * remaining)859*03f9172cSAndroid Build Coastguard Worker int eloop_cancel_timeout_one(eloop_timeout_handler handler,
860*03f9172cSAndroid Build Coastguard Worker 			     void *eloop_data, void *user_data,
861*03f9172cSAndroid Build Coastguard Worker 			     struct os_reltime *remaining)
862*03f9172cSAndroid Build Coastguard Worker {
863*03f9172cSAndroid Build Coastguard Worker 	struct eloop_timeout *timeout, *prev;
864*03f9172cSAndroid Build Coastguard Worker 	int removed = 0;
865*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime now;
866*03f9172cSAndroid Build Coastguard Worker 
867*03f9172cSAndroid Build Coastguard Worker 	os_get_reltime(&now);
868*03f9172cSAndroid Build Coastguard Worker 	remaining->sec = remaining->usec = 0;
869*03f9172cSAndroid Build Coastguard Worker 
870*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
871*03f9172cSAndroid Build Coastguard Worker 			      struct eloop_timeout, list) {
872*03f9172cSAndroid Build Coastguard Worker 		if (timeout->handler == handler &&
873*03f9172cSAndroid Build Coastguard Worker 		    (timeout->eloop_data == eloop_data) &&
874*03f9172cSAndroid Build Coastguard Worker 		    (timeout->user_data == user_data)) {
875*03f9172cSAndroid Build Coastguard Worker 			removed = 1;
876*03f9172cSAndroid Build Coastguard Worker 			if (os_reltime_before(&now, &timeout->time))
877*03f9172cSAndroid Build Coastguard Worker 				os_reltime_sub(&timeout->time, &now, remaining);
878*03f9172cSAndroid Build Coastguard Worker 			eloop_remove_timeout(timeout);
879*03f9172cSAndroid Build Coastguard Worker 			break;
880*03f9172cSAndroid Build Coastguard Worker 		}
881*03f9172cSAndroid Build Coastguard Worker 	}
882*03f9172cSAndroid Build Coastguard Worker 	return removed;
883*03f9172cSAndroid Build Coastguard Worker }
884*03f9172cSAndroid Build Coastguard Worker 
885*03f9172cSAndroid Build Coastguard Worker 
eloop_is_timeout_registered(eloop_timeout_handler handler,void * eloop_data,void * user_data)886*03f9172cSAndroid Build Coastguard Worker int eloop_is_timeout_registered(eloop_timeout_handler handler,
887*03f9172cSAndroid Build Coastguard Worker 				void *eloop_data, void *user_data)
888*03f9172cSAndroid Build Coastguard Worker {
889*03f9172cSAndroid Build Coastguard Worker 	struct eloop_timeout *tmp;
890*03f9172cSAndroid Build Coastguard Worker 
891*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
892*03f9172cSAndroid Build Coastguard Worker 		if (tmp->handler == handler &&
893*03f9172cSAndroid Build Coastguard Worker 		    tmp->eloop_data == eloop_data &&
894*03f9172cSAndroid Build Coastguard Worker 		    tmp->user_data == user_data)
895*03f9172cSAndroid Build Coastguard Worker 			return 1;
896*03f9172cSAndroid Build Coastguard Worker 	}
897*03f9172cSAndroid Build Coastguard Worker 
898*03f9172cSAndroid Build Coastguard Worker 	return 0;
899*03f9172cSAndroid Build Coastguard Worker }
900*03f9172cSAndroid Build Coastguard Worker 
901*03f9172cSAndroid Build Coastguard Worker 
eloop_deplete_timeout(unsigned int req_secs,unsigned int req_usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)902*03f9172cSAndroid Build Coastguard Worker int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
903*03f9172cSAndroid Build Coastguard Worker 			  eloop_timeout_handler handler, void *eloop_data,
904*03f9172cSAndroid Build Coastguard Worker 			  void *user_data)
905*03f9172cSAndroid Build Coastguard Worker {
906*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime now, requested, remaining;
907*03f9172cSAndroid Build Coastguard Worker 	struct eloop_timeout *tmp;
908*03f9172cSAndroid Build Coastguard Worker 
909*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
910*03f9172cSAndroid Build Coastguard Worker 		if (tmp->handler == handler &&
911*03f9172cSAndroid Build Coastguard Worker 		    tmp->eloop_data == eloop_data &&
912*03f9172cSAndroid Build Coastguard Worker 		    tmp->user_data == user_data) {
913*03f9172cSAndroid Build Coastguard Worker 			requested.sec = req_secs;
914*03f9172cSAndroid Build Coastguard Worker 			requested.usec = req_usecs;
915*03f9172cSAndroid Build Coastguard Worker 			os_get_reltime(&now);
916*03f9172cSAndroid Build Coastguard Worker 			os_reltime_sub(&tmp->time, &now, &remaining);
917*03f9172cSAndroid Build Coastguard Worker 			if (os_reltime_before(&requested, &remaining)) {
918*03f9172cSAndroid Build Coastguard Worker 				eloop_cancel_timeout(handler, eloop_data,
919*03f9172cSAndroid Build Coastguard Worker 						     user_data);
920*03f9172cSAndroid Build Coastguard Worker 				eloop_register_timeout(requested.sec,
921*03f9172cSAndroid Build Coastguard Worker 						       requested.usec,
922*03f9172cSAndroid Build Coastguard Worker 						       handler, eloop_data,
923*03f9172cSAndroid Build Coastguard Worker 						       user_data);
924*03f9172cSAndroid Build Coastguard Worker 				return 1;
925*03f9172cSAndroid Build Coastguard Worker 			}
926*03f9172cSAndroid Build Coastguard Worker 			return 0;
927*03f9172cSAndroid Build Coastguard Worker 		}
928*03f9172cSAndroid Build Coastguard Worker 	}
929*03f9172cSAndroid Build Coastguard Worker 
930*03f9172cSAndroid Build Coastguard Worker 	return -1;
931*03f9172cSAndroid Build Coastguard Worker }
932*03f9172cSAndroid Build Coastguard Worker 
933*03f9172cSAndroid Build Coastguard Worker 
eloop_replenish_timeout(unsigned int req_secs,unsigned int req_usecs,eloop_timeout_handler handler,void * eloop_data,void * user_data)934*03f9172cSAndroid Build Coastguard Worker int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
935*03f9172cSAndroid Build Coastguard Worker 			    eloop_timeout_handler handler, void *eloop_data,
936*03f9172cSAndroid Build Coastguard Worker 			    void *user_data)
937*03f9172cSAndroid Build Coastguard Worker {
938*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime now, requested, remaining;
939*03f9172cSAndroid Build Coastguard Worker 	struct eloop_timeout *tmp;
940*03f9172cSAndroid Build Coastguard Worker 
941*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
942*03f9172cSAndroid Build Coastguard Worker 		if (tmp->handler == handler &&
943*03f9172cSAndroid Build Coastguard Worker 		    tmp->eloop_data == eloop_data &&
944*03f9172cSAndroid Build Coastguard Worker 		    tmp->user_data == user_data) {
945*03f9172cSAndroid Build Coastguard Worker 			requested.sec = req_secs;
946*03f9172cSAndroid Build Coastguard Worker 			requested.usec = req_usecs;
947*03f9172cSAndroid Build Coastguard Worker 			os_get_reltime(&now);
948*03f9172cSAndroid Build Coastguard Worker 			os_reltime_sub(&tmp->time, &now, &remaining);
949*03f9172cSAndroid Build Coastguard Worker 			if (os_reltime_before(&remaining, &requested)) {
950*03f9172cSAndroid Build Coastguard Worker 				eloop_cancel_timeout(handler, eloop_data,
951*03f9172cSAndroid Build Coastguard Worker 						     user_data);
952*03f9172cSAndroid Build Coastguard Worker 				eloop_register_timeout(requested.sec,
953*03f9172cSAndroid Build Coastguard Worker 						       requested.usec,
954*03f9172cSAndroid Build Coastguard Worker 						       handler, eloop_data,
955*03f9172cSAndroid Build Coastguard Worker 						       user_data);
956*03f9172cSAndroid Build Coastguard Worker 				return 1;
957*03f9172cSAndroid Build Coastguard Worker 			}
958*03f9172cSAndroid Build Coastguard Worker 			return 0;
959*03f9172cSAndroid Build Coastguard Worker 		}
960*03f9172cSAndroid Build Coastguard Worker 	}
961*03f9172cSAndroid Build Coastguard Worker 
962*03f9172cSAndroid Build Coastguard Worker 	return -1;
963*03f9172cSAndroid Build Coastguard Worker }
964*03f9172cSAndroid Build Coastguard Worker 
965*03f9172cSAndroid Build Coastguard Worker 
966*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_NATIVE_WINDOWS
eloop_handle_alarm(int sig)967*03f9172cSAndroid Build Coastguard Worker static void eloop_handle_alarm(int sig)
968*03f9172cSAndroid Build Coastguard Worker {
969*03f9172cSAndroid Build Coastguard Worker 	wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
970*03f9172cSAndroid Build Coastguard Worker 		   "two seconds. Looks like there\n"
971*03f9172cSAndroid Build Coastguard Worker 		   "is a bug that ends up in a busy loop that "
972*03f9172cSAndroid Build Coastguard Worker 		   "prevents clean shutdown.\n"
973*03f9172cSAndroid Build Coastguard Worker 		   "Killing program forcefully.\n");
974*03f9172cSAndroid Build Coastguard Worker 	exit(1);
975*03f9172cSAndroid Build Coastguard Worker }
976*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NATIVE_WINDOWS */
977*03f9172cSAndroid Build Coastguard Worker 
978*03f9172cSAndroid Build Coastguard Worker 
eloop_handle_signal(int sig)979*03f9172cSAndroid Build Coastguard Worker static void eloop_handle_signal(int sig)
980*03f9172cSAndroid Build Coastguard Worker {
981*03f9172cSAndroid Build Coastguard Worker 	size_t i;
982*03f9172cSAndroid Build Coastguard Worker 
983*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_NATIVE_WINDOWS
984*03f9172cSAndroid Build Coastguard Worker 	if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
985*03f9172cSAndroid Build Coastguard Worker 		/* Use SIGALRM to break out from potential busy loops that
986*03f9172cSAndroid Build Coastguard Worker 		 * would not allow the program to be killed. */
987*03f9172cSAndroid Build Coastguard Worker 		eloop.pending_terminate = 1;
988*03f9172cSAndroid Build Coastguard Worker 		signal(SIGALRM, eloop_handle_alarm);
989*03f9172cSAndroid Build Coastguard Worker 		alarm(2);
990*03f9172cSAndroid Build Coastguard Worker 	}
991*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NATIVE_WINDOWS */
992*03f9172cSAndroid Build Coastguard Worker 
993*03f9172cSAndroid Build Coastguard Worker 	eloop.signaled++;
994*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < eloop.signal_count; i++) {
995*03f9172cSAndroid Build Coastguard Worker 		if (eloop.signals[i].sig == sig) {
996*03f9172cSAndroid Build Coastguard Worker 			eloop.signals[i].signaled++;
997*03f9172cSAndroid Build Coastguard Worker 			break;
998*03f9172cSAndroid Build Coastguard Worker 		}
999*03f9172cSAndroid Build Coastguard Worker 	}
1000*03f9172cSAndroid Build Coastguard Worker }
1001*03f9172cSAndroid Build Coastguard Worker 
1002*03f9172cSAndroid Build Coastguard Worker 
eloop_process_pending_signals(void)1003*03f9172cSAndroid Build Coastguard Worker static void eloop_process_pending_signals(void)
1004*03f9172cSAndroid Build Coastguard Worker {
1005*03f9172cSAndroid Build Coastguard Worker 	size_t i;
1006*03f9172cSAndroid Build Coastguard Worker 
1007*03f9172cSAndroid Build Coastguard Worker 	if (eloop.signaled == 0)
1008*03f9172cSAndroid Build Coastguard Worker 		return;
1009*03f9172cSAndroid Build Coastguard Worker 	eloop.signaled = 0;
1010*03f9172cSAndroid Build Coastguard Worker 
1011*03f9172cSAndroid Build Coastguard Worker 	if (eloop.pending_terminate) {
1012*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_NATIVE_WINDOWS
1013*03f9172cSAndroid Build Coastguard Worker 		alarm(0);
1014*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NATIVE_WINDOWS */
1015*03f9172cSAndroid Build Coastguard Worker 		eloop.pending_terminate = 0;
1016*03f9172cSAndroid Build Coastguard Worker 	}
1017*03f9172cSAndroid Build Coastguard Worker 
1018*03f9172cSAndroid Build Coastguard Worker 	for (i = 0; i < eloop.signal_count; i++) {
1019*03f9172cSAndroid Build Coastguard Worker 		if (eloop.signals[i].signaled) {
1020*03f9172cSAndroid Build Coastguard Worker 			eloop.signals[i].signaled = 0;
1021*03f9172cSAndroid Build Coastguard Worker 			eloop.signals[i].handler(eloop.signals[i].sig,
1022*03f9172cSAndroid Build Coastguard Worker 						 eloop.signals[i].user_data);
1023*03f9172cSAndroid Build Coastguard Worker 		}
1024*03f9172cSAndroid Build Coastguard Worker 	}
1025*03f9172cSAndroid Build Coastguard Worker }
1026*03f9172cSAndroid Build Coastguard Worker 
1027*03f9172cSAndroid Build Coastguard Worker 
eloop_register_signal(int sig,eloop_signal_handler handler,void * user_data)1028*03f9172cSAndroid Build Coastguard Worker int eloop_register_signal(int sig, eloop_signal_handler handler,
1029*03f9172cSAndroid Build Coastguard Worker 			  void *user_data)
1030*03f9172cSAndroid Build Coastguard Worker {
1031*03f9172cSAndroid Build Coastguard Worker 	struct eloop_signal *tmp;
1032*03f9172cSAndroid Build Coastguard Worker 
1033*03f9172cSAndroid Build Coastguard Worker 	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
1034*03f9172cSAndroid Build Coastguard Worker 			       sizeof(struct eloop_signal));
1035*03f9172cSAndroid Build Coastguard Worker 	if (tmp == NULL)
1036*03f9172cSAndroid Build Coastguard Worker 		return -1;
1037*03f9172cSAndroid Build Coastguard Worker 
1038*03f9172cSAndroid Build Coastguard Worker 	tmp[eloop.signal_count].sig = sig;
1039*03f9172cSAndroid Build Coastguard Worker 	tmp[eloop.signal_count].user_data = user_data;
1040*03f9172cSAndroid Build Coastguard Worker 	tmp[eloop.signal_count].handler = handler;
1041*03f9172cSAndroid Build Coastguard Worker 	tmp[eloop.signal_count].signaled = 0;
1042*03f9172cSAndroid Build Coastguard Worker 	eloop.signal_count++;
1043*03f9172cSAndroid Build Coastguard Worker 	eloop.signals = tmp;
1044*03f9172cSAndroid Build Coastguard Worker 	signal(sig, eloop_handle_signal);
1045*03f9172cSAndroid Build Coastguard Worker 
1046*03f9172cSAndroid Build Coastguard Worker 	return 0;
1047*03f9172cSAndroid Build Coastguard Worker }
1048*03f9172cSAndroid Build Coastguard Worker 
1049*03f9172cSAndroid Build Coastguard Worker 
eloop_register_signal_terminate(eloop_signal_handler handler,void * user_data)1050*03f9172cSAndroid Build Coastguard Worker int eloop_register_signal_terminate(eloop_signal_handler handler,
1051*03f9172cSAndroid Build Coastguard Worker 				    void *user_data)
1052*03f9172cSAndroid Build Coastguard Worker {
1053*03f9172cSAndroid Build Coastguard Worker 	int ret = eloop_register_signal(SIGINT, handler, user_data);
1054*03f9172cSAndroid Build Coastguard Worker 	if (ret == 0)
1055*03f9172cSAndroid Build Coastguard Worker 		ret = eloop_register_signal(SIGTERM, handler, user_data);
1056*03f9172cSAndroid Build Coastguard Worker 	return ret;
1057*03f9172cSAndroid Build Coastguard Worker }
1058*03f9172cSAndroid Build Coastguard Worker 
1059*03f9172cSAndroid Build Coastguard Worker 
eloop_register_signal_reconfig(eloop_signal_handler handler,void * user_data)1060*03f9172cSAndroid Build Coastguard Worker int eloop_register_signal_reconfig(eloop_signal_handler handler,
1061*03f9172cSAndroid Build Coastguard Worker 				   void *user_data)
1062*03f9172cSAndroid Build Coastguard Worker {
1063*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_NATIVE_WINDOWS
1064*03f9172cSAndroid Build Coastguard Worker 	return 0;
1065*03f9172cSAndroid Build Coastguard Worker #else /* CONFIG_NATIVE_WINDOWS */
1066*03f9172cSAndroid Build Coastguard Worker 	return eloop_register_signal(SIGHUP, handler, user_data);
1067*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NATIVE_WINDOWS */
1068*03f9172cSAndroid Build Coastguard Worker }
1069*03f9172cSAndroid Build Coastguard Worker 
1070*03f9172cSAndroid Build Coastguard Worker 
eloop_run(void)1071*03f9172cSAndroid Build Coastguard Worker void eloop_run(void)
1072*03f9172cSAndroid Build Coastguard Worker {
1073*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
1074*03f9172cSAndroid Build Coastguard Worker 	int num_poll_fds;
1075*03f9172cSAndroid Build Coastguard Worker 	int timeout_ms = 0;
1076*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
1077*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1078*03f9172cSAndroid Build Coastguard Worker 	fd_set *rfds, *wfds, *efds;
1079*03f9172cSAndroid Build Coastguard Worker 	struct timeval _tv;
1080*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1081*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
1082*03f9172cSAndroid Build Coastguard Worker 	int timeout_ms = -1;
1083*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
1084*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
1085*03f9172cSAndroid Build Coastguard Worker 	struct timespec ts;
1086*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
1087*03f9172cSAndroid Build Coastguard Worker 	int res;
1088*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime tv, now;
1089*03f9172cSAndroid Build Coastguard Worker 
1090*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1091*03f9172cSAndroid Build Coastguard Worker 	rfds = os_malloc(sizeof(*rfds));
1092*03f9172cSAndroid Build Coastguard Worker 	wfds = os_malloc(sizeof(*wfds));
1093*03f9172cSAndroid Build Coastguard Worker 	efds = os_malloc(sizeof(*efds));
1094*03f9172cSAndroid Build Coastguard Worker 	if (rfds == NULL || wfds == NULL || efds == NULL)
1095*03f9172cSAndroid Build Coastguard Worker 		goto out;
1096*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1097*03f9172cSAndroid Build Coastguard Worker 
1098*03f9172cSAndroid Build Coastguard Worker 	while (!eloop.terminate &&
1099*03f9172cSAndroid Build Coastguard Worker 	       (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
1100*03f9172cSAndroid Build Coastguard Worker 		eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
1101*03f9172cSAndroid Build Coastguard Worker 		struct eloop_timeout *timeout;
1102*03f9172cSAndroid Build Coastguard Worker 
1103*03f9172cSAndroid Build Coastguard Worker 		if (eloop.pending_terminate) {
1104*03f9172cSAndroid Build Coastguard Worker 			/*
1105*03f9172cSAndroid Build Coastguard Worker 			 * This may happen in some corner cases where a signal
1106*03f9172cSAndroid Build Coastguard Worker 			 * is received during a blocking operation. We need to
1107*03f9172cSAndroid Build Coastguard Worker 			 * process the pending signals and exit if requested to
1108*03f9172cSAndroid Build Coastguard Worker 			 * avoid hitting the SIGALRM limit if the blocking
1109*03f9172cSAndroid Build Coastguard Worker 			 * operation took more than two seconds.
1110*03f9172cSAndroid Build Coastguard Worker 			 */
1111*03f9172cSAndroid Build Coastguard Worker 			eloop_process_pending_signals();
1112*03f9172cSAndroid Build Coastguard Worker 			if (eloop.terminate)
1113*03f9172cSAndroid Build Coastguard Worker 				break;
1114*03f9172cSAndroid Build Coastguard Worker 		}
1115*03f9172cSAndroid Build Coastguard Worker 
1116*03f9172cSAndroid Build Coastguard Worker 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
1117*03f9172cSAndroid Build Coastguard Worker 					list);
1118*03f9172cSAndroid Build Coastguard Worker 		if (timeout) {
1119*03f9172cSAndroid Build Coastguard Worker 			os_get_reltime(&now);
1120*03f9172cSAndroid Build Coastguard Worker 			if (os_reltime_before(&now, &timeout->time))
1121*03f9172cSAndroid Build Coastguard Worker 				os_reltime_sub(&timeout->time, &now, &tv);
1122*03f9172cSAndroid Build Coastguard Worker 			else
1123*03f9172cSAndroid Build Coastguard Worker 				tv.sec = tv.usec = 0;
1124*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
1125*03f9172cSAndroid Build Coastguard Worker 			timeout_ms = tv.sec * 1000 + tv.usec / 1000;
1126*03f9172cSAndroid Build Coastguard Worker #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
1127*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1128*03f9172cSAndroid Build Coastguard Worker 			_tv.tv_sec = tv.sec;
1129*03f9172cSAndroid Build Coastguard Worker 			_tv.tv_usec = tv.usec;
1130*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1131*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
1132*03f9172cSAndroid Build Coastguard Worker 			ts.tv_sec = tv.sec;
1133*03f9172cSAndroid Build Coastguard Worker 			ts.tv_nsec = tv.usec * 1000L;
1134*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
1135*03f9172cSAndroid Build Coastguard Worker 		}
1136*03f9172cSAndroid Build Coastguard Worker 
1137*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
1138*03f9172cSAndroid Build Coastguard Worker 		num_poll_fds = eloop_sock_table_set_fds(
1139*03f9172cSAndroid Build Coastguard Worker 			&eloop.readers, &eloop.writers, &eloop.exceptions,
1140*03f9172cSAndroid Build Coastguard Worker 			eloop.pollfds, eloop.pollfds_map,
1141*03f9172cSAndroid Build Coastguard Worker 			eloop.max_pollfd_map);
1142*03f9172cSAndroid Build Coastguard Worker 		res = poll(eloop.pollfds, num_poll_fds,
1143*03f9172cSAndroid Build Coastguard Worker 			   timeout ? timeout_ms : -1);
1144*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
1145*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1146*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_set_fds(&eloop.readers, rfds);
1147*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_set_fds(&eloop.writers, wfds);
1148*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_set_fds(&eloop.exceptions, efds);
1149*03f9172cSAndroid Build Coastguard Worker 		res = select(eloop.max_sock + 1, rfds, wfds, efds,
1150*03f9172cSAndroid Build Coastguard Worker 			     timeout ? &_tv : NULL);
1151*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1152*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
1153*03f9172cSAndroid Build Coastguard Worker 		if (eloop.count == 0) {
1154*03f9172cSAndroid Build Coastguard Worker 			res = 0;
1155*03f9172cSAndroid Build Coastguard Worker 		} else {
1156*03f9172cSAndroid Build Coastguard Worker 			res = epoll_wait(eloop.epollfd, eloop.epoll_events,
1157*03f9172cSAndroid Build Coastguard Worker 					 eloop.count, timeout_ms);
1158*03f9172cSAndroid Build Coastguard Worker 		}
1159*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
1160*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
1161*03f9172cSAndroid Build Coastguard Worker 		if (eloop.count == 0) {
1162*03f9172cSAndroid Build Coastguard Worker 			res = 0;
1163*03f9172cSAndroid Build Coastguard Worker 		} else {
1164*03f9172cSAndroid Build Coastguard Worker 			res = kevent(eloop.kqueuefd, NULL, 0,
1165*03f9172cSAndroid Build Coastguard Worker 				     eloop.kqueue_events, eloop.kqueue_nevents,
1166*03f9172cSAndroid Build Coastguard Worker 				     timeout ? &ts : NULL);
1167*03f9172cSAndroid Build Coastguard Worker 		}
1168*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
1169*03f9172cSAndroid Build Coastguard Worker 		if (res < 0 && errno != EINTR && errno != 0) {
1170*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_ERROR, "eloop: %s: %s",
1171*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
1172*03f9172cSAndroid Build Coastguard Worker 				   "poll"
1173*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
1174*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1175*03f9172cSAndroid Build Coastguard Worker 				   "select"
1176*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1177*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
1178*03f9172cSAndroid Build Coastguard Worker 				   "epoll"
1179*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
1180*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
1181*03f9172cSAndroid Build Coastguard Worker 				   "kqueue"
1182*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EKQUEUE */
1183*03f9172cSAndroid Build Coastguard Worker 
1184*03f9172cSAndroid Build Coastguard Worker 				   , strerror(errno));
1185*03f9172cSAndroid Build Coastguard Worker 			goto out;
1186*03f9172cSAndroid Build Coastguard Worker 		}
1187*03f9172cSAndroid Build Coastguard Worker 
1188*03f9172cSAndroid Build Coastguard Worker 		eloop.readers.changed = 0;
1189*03f9172cSAndroid Build Coastguard Worker 		eloop.writers.changed = 0;
1190*03f9172cSAndroid Build Coastguard Worker 		eloop.exceptions.changed = 0;
1191*03f9172cSAndroid Build Coastguard Worker 
1192*03f9172cSAndroid Build Coastguard Worker 		eloop_process_pending_signals();
1193*03f9172cSAndroid Build Coastguard Worker 
1194*03f9172cSAndroid Build Coastguard Worker 
1195*03f9172cSAndroid Build Coastguard Worker 		/* check if some registered timeouts have occurred */
1196*03f9172cSAndroid Build Coastguard Worker 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
1197*03f9172cSAndroid Build Coastguard Worker 					list);
1198*03f9172cSAndroid Build Coastguard Worker 		if (timeout) {
1199*03f9172cSAndroid Build Coastguard Worker 			os_get_reltime(&now);
1200*03f9172cSAndroid Build Coastguard Worker 			if (!os_reltime_before(&now, &timeout->time)) {
1201*03f9172cSAndroid Build Coastguard Worker 				void *eloop_data = timeout->eloop_data;
1202*03f9172cSAndroid Build Coastguard Worker 				void *user_data = timeout->user_data;
1203*03f9172cSAndroid Build Coastguard Worker 				eloop_timeout_handler handler =
1204*03f9172cSAndroid Build Coastguard Worker 					timeout->handler;
1205*03f9172cSAndroid Build Coastguard Worker 				eloop_remove_timeout(timeout);
1206*03f9172cSAndroid Build Coastguard Worker 				handler(eloop_data, user_data);
1207*03f9172cSAndroid Build Coastguard Worker 			}
1208*03f9172cSAndroid Build Coastguard Worker 
1209*03f9172cSAndroid Build Coastguard Worker 		}
1210*03f9172cSAndroid Build Coastguard Worker 
1211*03f9172cSAndroid Build Coastguard Worker 		if (res <= 0)
1212*03f9172cSAndroid Build Coastguard Worker 			continue;
1213*03f9172cSAndroid Build Coastguard Worker 
1214*03f9172cSAndroid Build Coastguard Worker 		if (eloop.readers.changed ||
1215*03f9172cSAndroid Build Coastguard Worker 		    eloop.writers.changed ||
1216*03f9172cSAndroid Build Coastguard Worker 		    eloop.exceptions.changed) {
1217*03f9172cSAndroid Build Coastguard Worker 			 /*
1218*03f9172cSAndroid Build Coastguard Worker 			  * Sockets may have been closed and reopened with the
1219*03f9172cSAndroid Build Coastguard Worker 			  * same FD in the signal or timeout handlers, so we
1220*03f9172cSAndroid Build Coastguard Worker 			  * must skip the previous results and check again
1221*03f9172cSAndroid Build Coastguard Worker 			  * whether any of the currently registered sockets have
1222*03f9172cSAndroid Build Coastguard Worker 			  * events.
1223*03f9172cSAndroid Build Coastguard Worker 			  */
1224*03f9172cSAndroid Build Coastguard Worker 			continue;
1225*03f9172cSAndroid Build Coastguard Worker 		}
1226*03f9172cSAndroid Build Coastguard Worker 
1227*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
1228*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
1229*03f9172cSAndroid Build Coastguard Worker 					  &eloop.exceptions, eloop.pollfds_map,
1230*03f9172cSAndroid Build Coastguard Worker 					  eloop.max_pollfd_map);
1231*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
1232*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1233*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_dispatch(&eloop.readers, rfds);
1234*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_dispatch(&eloop.writers, wfds);
1235*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_dispatch(&eloop.exceptions, efds);
1236*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1237*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
1238*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_dispatch(eloop.epoll_events, res);
1239*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
1240*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
1241*03f9172cSAndroid Build Coastguard Worker 		eloop_sock_table_dispatch(eloop.kqueue_events, res);
1242*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
1243*03f9172cSAndroid Build Coastguard Worker 	}
1244*03f9172cSAndroid Build Coastguard Worker 
1245*03f9172cSAndroid Build Coastguard Worker 	eloop.terminate = 0;
1246*03f9172cSAndroid Build Coastguard Worker out:
1247*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1248*03f9172cSAndroid Build Coastguard Worker 	os_free(rfds);
1249*03f9172cSAndroid Build Coastguard Worker 	os_free(wfds);
1250*03f9172cSAndroid Build Coastguard Worker 	os_free(efds);
1251*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1252*03f9172cSAndroid Build Coastguard Worker 	return;
1253*03f9172cSAndroid Build Coastguard Worker }
1254*03f9172cSAndroid Build Coastguard Worker 
1255*03f9172cSAndroid Build Coastguard Worker 
eloop_terminate(void)1256*03f9172cSAndroid Build Coastguard Worker void eloop_terminate(void)
1257*03f9172cSAndroid Build Coastguard Worker {
1258*03f9172cSAndroid Build Coastguard Worker 	eloop.terminate = 1;
1259*03f9172cSAndroid Build Coastguard Worker }
1260*03f9172cSAndroid Build Coastguard Worker 
1261*03f9172cSAndroid Build Coastguard Worker 
eloop_destroy(void)1262*03f9172cSAndroid Build Coastguard Worker void eloop_destroy(void)
1263*03f9172cSAndroid Build Coastguard Worker {
1264*03f9172cSAndroid Build Coastguard Worker 	struct eloop_timeout *timeout, *prev;
1265*03f9172cSAndroid Build Coastguard Worker 	struct os_reltime now;
1266*03f9172cSAndroid Build Coastguard Worker 
1267*03f9172cSAndroid Build Coastguard Worker 	os_get_reltime(&now);
1268*03f9172cSAndroid Build Coastguard Worker 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
1269*03f9172cSAndroid Build Coastguard Worker 			      struct eloop_timeout, list) {
1270*03f9172cSAndroid Build Coastguard Worker 		int sec, usec;
1271*03f9172cSAndroid Build Coastguard Worker 		sec = timeout->time.sec - now.sec;
1272*03f9172cSAndroid Build Coastguard Worker 		usec = timeout->time.usec - now.usec;
1273*03f9172cSAndroid Build Coastguard Worker 		if (timeout->time.usec < now.usec) {
1274*03f9172cSAndroid Build Coastguard Worker 			sec--;
1275*03f9172cSAndroid Build Coastguard Worker 			usec += 1000000;
1276*03f9172cSAndroid Build Coastguard Worker 		}
1277*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
1278*03f9172cSAndroid Build Coastguard Worker 			   "eloop_data=%p user_data=%p handler=%p",
1279*03f9172cSAndroid Build Coastguard Worker 			   sec, usec, timeout->eloop_data, timeout->user_data,
1280*03f9172cSAndroid Build Coastguard Worker 			   timeout->handler);
1281*03f9172cSAndroid Build Coastguard Worker 		wpa_trace_dump_funcname("eloop unregistered timeout handler",
1282*03f9172cSAndroid Build Coastguard Worker 					timeout->handler);
1283*03f9172cSAndroid Build Coastguard Worker 		wpa_trace_dump("eloop timeout", timeout);
1284*03f9172cSAndroid Build Coastguard Worker 		eloop_remove_timeout(timeout);
1285*03f9172cSAndroid Build Coastguard Worker 	}
1286*03f9172cSAndroid Build Coastguard Worker 	eloop_sock_table_destroy(&eloop.readers);
1287*03f9172cSAndroid Build Coastguard Worker 	eloop_sock_table_destroy(&eloop.writers);
1288*03f9172cSAndroid Build Coastguard Worker 	eloop_sock_table_destroy(&eloop.exceptions);
1289*03f9172cSAndroid Build Coastguard Worker 	os_free(eloop.signals);
1290*03f9172cSAndroid Build Coastguard Worker 
1291*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
1292*03f9172cSAndroid Build Coastguard Worker 	os_free(eloop.pollfds);
1293*03f9172cSAndroid Build Coastguard Worker 	os_free(eloop.pollfds_map);
1294*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
1295*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
1296*03f9172cSAndroid Build Coastguard Worker 	os_free(eloop.fd_table);
1297*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
1298*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_EPOLL
1299*03f9172cSAndroid Build Coastguard Worker 	os_free(eloop.epoll_events);
1300*03f9172cSAndroid Build Coastguard Worker 	close(eloop.epollfd);
1301*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_EPOLL */
1302*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
1303*03f9172cSAndroid Build Coastguard Worker 	os_free(eloop.kqueue_events);
1304*03f9172cSAndroid Build Coastguard Worker 	close(eloop.kqueuefd);
1305*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
1306*03f9172cSAndroid Build Coastguard Worker }
1307*03f9172cSAndroid Build Coastguard Worker 
1308*03f9172cSAndroid Build Coastguard Worker 
eloop_terminated(void)1309*03f9172cSAndroid Build Coastguard Worker int eloop_terminated(void)
1310*03f9172cSAndroid Build Coastguard Worker {
1311*03f9172cSAndroid Build Coastguard Worker 	return eloop.terminate || eloop.pending_terminate;
1312*03f9172cSAndroid Build Coastguard Worker }
1313*03f9172cSAndroid Build Coastguard Worker 
1314*03f9172cSAndroid Build Coastguard Worker 
eloop_wait_for_read_sock(int sock)1315*03f9172cSAndroid Build Coastguard Worker void eloop_wait_for_read_sock(int sock)
1316*03f9172cSAndroid Build Coastguard Worker {
1317*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_POLL
1318*03f9172cSAndroid Build Coastguard Worker 	struct pollfd pfd;
1319*03f9172cSAndroid Build Coastguard Worker 
1320*03f9172cSAndroid Build Coastguard Worker 	if (sock < 0)
1321*03f9172cSAndroid Build Coastguard Worker 		return;
1322*03f9172cSAndroid Build Coastguard Worker 
1323*03f9172cSAndroid Build Coastguard Worker 	os_memset(&pfd, 0, sizeof(pfd));
1324*03f9172cSAndroid Build Coastguard Worker 	pfd.fd = sock;
1325*03f9172cSAndroid Build Coastguard Worker 	pfd.events = POLLIN;
1326*03f9172cSAndroid Build Coastguard Worker 
1327*03f9172cSAndroid Build Coastguard Worker 	poll(&pfd, 1, -1);
1328*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_POLL */
1329*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL)
1330*03f9172cSAndroid Build Coastguard Worker 	/*
1331*03f9172cSAndroid Build Coastguard Worker 	 * We can use epoll() here. But epoll() requres 4 system calls.
1332*03f9172cSAndroid Build Coastguard Worker 	 * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for
1333*03f9172cSAndroid Build Coastguard Worker 	 * epoll fd. So select() is better for performance here.
1334*03f9172cSAndroid Build Coastguard Worker 	 */
1335*03f9172cSAndroid Build Coastguard Worker 	fd_set rfds;
1336*03f9172cSAndroid Build Coastguard Worker 
1337*03f9172cSAndroid Build Coastguard Worker 	if (sock < 0)
1338*03f9172cSAndroid Build Coastguard Worker 		return;
1339*03f9172cSAndroid Build Coastguard Worker 
1340*03f9172cSAndroid Build Coastguard Worker 	FD_ZERO(&rfds);
1341*03f9172cSAndroid Build Coastguard Worker 	FD_SET(sock, &rfds);
1342*03f9172cSAndroid Build Coastguard Worker 	select(sock + 1, &rfds, NULL, NULL, NULL);
1343*03f9172cSAndroid Build Coastguard Worker #endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
1344*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_KQUEUE
1345*03f9172cSAndroid Build Coastguard Worker 	int kfd;
1346*03f9172cSAndroid Build Coastguard Worker 	struct kevent ke1, ke2;
1347*03f9172cSAndroid Build Coastguard Worker 
1348*03f9172cSAndroid Build Coastguard Worker 	kfd = kqueue();
1349*03f9172cSAndroid Build Coastguard Worker 	if (kfd == -1)
1350*03f9172cSAndroid Build Coastguard Worker 		return;
1351*03f9172cSAndroid Build Coastguard Worker 	EV_SET(&ke1, sock, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0);
1352*03f9172cSAndroid Build Coastguard Worker 	kevent(kfd, &ke1, 1, &ke2, 1, NULL);
1353*03f9172cSAndroid Build Coastguard Worker 	close(kfd);
1354*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_KQUEUE */
1355*03f9172cSAndroid Build Coastguard Worker }
1356*03f9172cSAndroid Build Coastguard Worker 
1357*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_ELOOP_SELECT
1358*03f9172cSAndroid Build Coastguard Worker #undef CONFIG_ELOOP_SELECT
1359*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_ELOOP_SELECT */
1360