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