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