18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Event loop based on select() loop
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
10df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt#include <assert.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "trace.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "list.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL)
1850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#error Do not define both of poll and epoll
1950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif
2050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
2150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL)
2250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#define CONFIG_ELOOP_SELECT
2350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif
2450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
25c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
26c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#include <poll.h>
27c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
28c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
3050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#include <sys/epoll.h>
3150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_sock {
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int sock;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *eloop_data;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *user_data;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_sock_handler handler;
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_TRACE_REF(eloop);
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_TRACE_REF(user);
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_TRACE_INFO
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_timeout {
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list list;
45fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	struct os_reltime time;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *eloop_data;
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *user_data;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_timeout_handler handler;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_TRACE_REF(eloop);
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_TRACE_REF(user);
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_TRACE_INFO
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_signal {
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int sig;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *user_data;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_signal_handler handler;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int signaled;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_sock_table {
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int count;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_sock *table;
6450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
6550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	eloop_event_type type;
6650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#else /* CONFIG_ELOOP_EPOLL */
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int changed;
6850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_data {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int max_sock;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
74c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int count; /* sum of all table counts */
75c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
76c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int max_pollfd_map; /* number of pollfds_map currently allocated */
77c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int max_poll_fds; /* number of pollfds currently allocated */
78c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct pollfd *pollfds;
79c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct pollfd **pollfds_map;
80c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
8150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
8250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	int epollfd;
8350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	int epoll_max_event_num;
8450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	int epoll_max_fd;
8550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	struct eloop_sock *epoll_table;
8650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	struct epoll_event *epoll_events;
8750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_sock_table readers;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_sock_table writers;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_sock_table exceptions;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list timeout;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int signal_count;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_signal *signals;
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int signaled;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int pending_terminate;
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int terminate;
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eloop_data eloop;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sigsegv_handler(int sig)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_show("eloop SIGSEGV");
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	abort();
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (table == NULL || table->table == NULL)
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < table->count; i++) {
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_add_ref(&table->table[i], eloop,
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  table->table[i].eloop_data);
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_add_ref(&table->table[i], user,
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  table->table[i].user_data);
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (table == NULL || table->table == NULL)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < table->count; i++) {
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_remove_ref(&table->table[i], eloop,
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     table->table[i].eloop_data);
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_remove_ref(&table->table[i], user,
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     table->table[i].user_data);
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE */
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define eloop_trace_sock_add_ref(table) do { } while (0)
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define eloop_trace_sock_remove_ref(table) do { } while (0)
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_init(void)
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(&eloop, 0, sizeof(eloop));
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&eloop.timeout);
15250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
15350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	eloop.epollfd = epoll_create1(0);
15450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (eloop.epollfd < 0) {
15550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
15650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   __func__, strerror(errno));
15750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
15850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
15950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	eloop.readers.type = EVENT_TYPE_READ;
16050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	eloop.writers.type = EVENT_TYPE_WRITE;
16150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
16250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	signal(SIGSEGV, eloop_sigsegv_handler);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eloop_sock_table_add_sock(struct eloop_sock_table *table,
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                                     int sock, eloop_sock_handler handler,
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                                     void *eloop_data, void *user_data)
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
17450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
17550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	struct eloop_sock *temp_table;
17650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	struct epoll_event ev, *temp_events;
17750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	int next;
17850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_sock *tmp;
180c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int new_max_sock;
181c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
182c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (sock > eloop.max_sock)
183c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		new_max_sock = sock;
184c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	else
185c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		new_max_sock = eloop.max_sock;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (table == NULL)
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
190c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
191c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (new_max_sock >= eloop.max_pollfd_map) {
192c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		struct pollfd **nmap;
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50,
19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					sizeof(struct pollfd *));
195c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (nmap == NULL)
196c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return -1;
197c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
198c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		eloop.max_pollfd_map = new_max_sock + 50;
199c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		eloop.pollfds_map = nmap;
200c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
201c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
202c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (eloop.count + 1 > eloop.max_poll_fds) {
203c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		struct pollfd *n;
204c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		int nmax = eloop.count + 1 + 50;
20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		n = os_realloc_array(eloop.pollfds, nmax,
20661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				     sizeof(struct pollfd));
207c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (n == NULL)
208c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return -1;
209c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
210c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		eloop.max_poll_fds = nmax;
211c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		eloop.pollfds = n;
212c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
213c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
21450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
21550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (new_max_sock >= eloop.epoll_max_fd) {
21650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
21750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		temp_table = os_realloc_array(eloop.epoll_table, next,
21850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt					      sizeof(struct eloop_sock));
21950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		if (temp_table == NULL)
22050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			return -1;
22150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
22250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		eloop.epoll_max_fd = next;
22350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		eloop.epoll_table = temp_table;
22450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
22550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
22650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (eloop.count + 1 > eloop.epoll_max_event_num) {
22750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		next = eloop.epoll_max_event_num == 0 ? 8 :
22850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			eloop.epoll_max_event_num * 2;
22950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		temp_events = os_realloc_array(eloop.epoll_events, next,
23050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt					       sizeof(struct epoll_event));
23150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		if (temp_events == NULL) {
23250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
23350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt				   "%s\n", __func__, strerror(errno));
23450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			return -1;
23550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		}
23650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
23750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		eloop.epoll_max_event_num = next;
23850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		eloop.epoll_events = temp_events;
23950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
24050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
241c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_trace_sock_remove_ref(table);
24361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = os_realloc_array(table->table, table->count + 1,
24461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       sizeof(struct eloop_sock));
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[table->count].sock = sock;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[table->count].eloop_data = eloop_data;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[table->count].user_data = user_data;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[table->count].handler = handler;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_record(&tmp[table->count]);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table->count++;
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table->table = tmp;
255c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	eloop.max_sock = new_max_sock;
256c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	eloop.count++;
25750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifndef CONFIG_ELOOP_EPOLL
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table->changed = 1;
25950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_trace_sock_add_ref(table);
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
26250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
26350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	os_memset(&ev, 0, sizeof(ev));
26450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	switch (table->type) {
26550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	case EVENT_TYPE_READ:
26650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		ev.events = EPOLLIN;
26750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		break;
26850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	case EVENT_TYPE_WRITE:
26950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		ev.events = EPOLLOUT;
27050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		break;
27150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	/*
27250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * Exceptions are always checked when using epoll, but I suppose it's
27350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * possible that someone registered a socket *only* for exception
27450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * handling.
27550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 */
27650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	case EVENT_TYPE_EXCEPTION:
27750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		ev.events = EPOLLERR | EPOLLHUP;
27850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		break;
27950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
28050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	ev.data.fd = sock;
28150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
28250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
28350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "failed. %s\n", __func__, sock, strerror(errno));
28450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
28550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
28650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
28750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		  sizeof(struct eloop_sock));
28850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt                                         int sock)
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (table == NULL || table->table == NULL || table->count == 0)
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < table->count; i++) {
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (table->table[i].sock == sock)
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i == table->count)
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_trace_sock_remove_ref(table);
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (i != table->count - 1) {
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memmove(&table->table[i], &table->table[i + 1],
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (table->count - i - 1) *
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sizeof(struct eloop_sock));
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table->count--;
314c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	eloop.count--;
31550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifndef CONFIG_ELOOP_EPOLL
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table->changed = 1;
31750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_trace_sock_add_ref(table);
31950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
32050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
32150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
32250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "failed. %s\n", __func__, sock, strerror(errno));
32350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return;
32450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
32550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
32650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
330c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
331c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
332c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx)
333c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
334c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (fd < mx && fd >= 0)
335c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return pollfds_map[fd];
336c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return NULL;
337c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
338c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
339c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
340c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int eloop_sock_table_set_fds(struct eloop_sock_table *readers,
341c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    struct eloop_sock_table *writers,
342c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    struct eloop_sock_table *exceptions,
343c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    struct pollfd *pollfds,
344c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    struct pollfd **pollfds_map,
345c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				    int max_pollfd_map)
346c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
347c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int i;
348c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int nxt = 0;
349c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int fd;
350c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct pollfd *pfd;
351c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
352c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	/* Clear pollfd lookup map. It will be re-populated below. */
353c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map);
354c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
355c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (readers && readers->table) {
356c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		for (i = 0; i < readers->count; i++) {
357c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			fd = readers->table[i].sock;
358c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			assert(fd >= 0 && fd < max_pollfd_map);
359c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			pollfds[nxt].fd = fd;
360c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			pollfds[nxt].events = POLLIN;
361c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			pollfds[nxt].revents = 0;
362c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			pollfds_map[fd] = &(pollfds[nxt]);
363c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			nxt++;
364c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
365c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
366c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
367c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (writers && writers->table) {
368c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		for (i = 0; i < writers->count; i++) {
369c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
370c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * See if we already added this descriptor, update it
371c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * if so.
372c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
373c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			fd = writers->table[i].sock;
374c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			assert(fd >= 0 && fd < max_pollfd_map);
375c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			pfd = pollfds_map[fd];
376c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			if (!pfd) {
377c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pfd = &(pollfds[nxt]);
378c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pfd->events = 0;
379c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pfd->fd = fd;
380c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pollfds[i].revents = 0;
381c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pollfds_map[fd] = pfd;
382c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				nxt++;
383c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			}
38404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			pfd->events |= POLLOUT;
385c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
386c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
387c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
388c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	/*
389c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	 * Exceptions are always checked when using poll, but I suppose it's
390c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	 * possible that someone registered a socket *only* for exception
391c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	 * handling. Set the POLLIN bit in this case.
392c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	 */
393c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (exceptions && exceptions->table) {
394c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		for (i = 0; i < exceptions->count; i++) {
395c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			/*
396c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * See if we already added this descriptor, just use it
397c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 * if so.
398c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			 */
399c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			fd = exceptions->table[i].sock;
400c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			assert(fd >= 0 && fd < max_pollfd_map);
401c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			pfd = pollfds_map[fd];
402c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			if (!pfd) {
403c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pfd = &(pollfds[nxt]);
404c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pfd->events = POLLIN;
405c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pfd->fd = fd;
406c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pollfds[i].revents = 0;
407c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				pollfds_map[fd] = pfd;
408c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				nxt++;
409c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			}
410c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
411c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
412c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
413c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return nxt;
414c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
415c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
416c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
417c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int eloop_sock_table_dispatch_table(struct eloop_sock_table *table,
418c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					   struct pollfd **pollfds_map,
419c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					   int max_pollfd_map,
420c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					   short int revents)
421c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
422c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int i;
423c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct pollfd *pfd;
424c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
425c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (!table || !table->table)
426c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return 0;
427c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
428c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	table->changed = 0;
429c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	for (i = 0; i < table->count; i++) {
430c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		pfd = find_pollfd(pollfds_map, table->table[i].sock,
431c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				  max_pollfd_map);
432c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (!pfd)
433c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
434c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
435c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (!(pfd->revents & revents))
436c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			continue;
437c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
438c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		table->table[i].handler(table->table[i].sock,
439c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					table->table[i].eloop_data,
440c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					table->table[i].user_data);
441c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (table->changed)
442c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			return 1;
443c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	}
444c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
445c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
446c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
447c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
448c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
449c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
450c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				      struct eloop_sock_table *writers,
451c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				      struct eloop_sock_table *exceptions,
452c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				      struct pollfd **pollfds_map,
453c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				      int max_pollfd_map)
454c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
455c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (eloop_sock_table_dispatch_table(readers, pollfds_map,
45604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					    max_pollfd_map, POLLIN | POLLERR |
45704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					    POLLHUP))
458c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return; /* pollfds may be invalid at this point */
459c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
460c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (eloop_sock_table_dispatch_table(writers, pollfds_map,
461c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					    max_pollfd_map, POLLOUT))
462c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return; /* pollfds may be invalid at this point */
463c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
464c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	eloop_sock_table_dispatch_table(exceptions, pollfds_map,
465c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					max_pollfd_map, POLLERR | POLLHUP);
466c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
467c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
46850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
46950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
47050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
471c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_set_fds(struct eloop_sock_table *table,
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     fd_set *fds)
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FD_ZERO(fds);
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (table->table == NULL)
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
482df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	for (i = 0; i < table->count; i++) {
483df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		assert(table->table[i].sock >= 0);
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		FD_SET(table->table[i].sock, fds);
485df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_dispatch(struct eloop_sock_table *table,
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      fd_set *fds)
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (table == NULL || table->table == NULL)
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table->changed = 0;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < table->count; i++) {
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (FD_ISSET(table->table[i].sock, fds)) {
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			table->table[i].handler(table->table[i].sock,
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						table->table[i].eloop_data,
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						table->table[i].user_data);
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (table->changed)
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
50950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
51050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
51150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
51250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
51350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidtstatic void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
51450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt{
51550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	struct eloop_sock *table;
51650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	int i;
51750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
51850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	for (i = 0; i < nfds; i++) {
51950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		table = &eloop.epoll_table[events[i].data.fd];
52050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		if (table->handler == NULL)
52150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			continue;
52250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		table->handler(table->sock, table->eloop_data,
52350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			       table->user_data);
52450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
52550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt}
52650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
527c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_destroy(struct eloop_sock_table *table)
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (table) {
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int i;
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < table->count && table->table; i++) {
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "sock=%d eloop_data=%p user_data=%p "
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "handler=%p",
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   table->table[i].sock,
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   table->table[i].eloop_data,
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   table->table[i].user_data,
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   table->table[i].handler);
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_trace_dump_funcname("eloop unregistered socket "
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						"handler",
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						table->table[i].handler);
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_trace_dump("eloop sock", &table->table[i]);
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(table->table);
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_read_sock(int sock, eloop_sock_handler handler,
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     void *eloop_data, void *user_data)
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   eloop_data, user_data);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_unregister_read_sock(int sock)
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_unregister_sock(sock, EVENT_TYPE_READ);
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (type) {
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_TYPE_READ:
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return &eloop.readers;
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_TYPE_WRITE:
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return &eloop.writers;
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_TYPE_EXCEPTION:
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return &eloop.exceptions;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_sock(int sock, eloop_event_type type,
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop_sock_handler handler,
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			void *eloop_data, void *user_data)
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_sock_table *table;
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
586df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	assert(sock >= 0);
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table = eloop_get_sock_table(type);
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eloop_sock_table_add_sock(table, sock, handler,
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 eloop_data, user_data);
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_unregister_sock(int sock, eloop_event_type type)
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_sock_table *table;
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	table = eloop_get_sock_table(type);
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_sock_table_remove_sock(table, sock);
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_timeout(unsigned int secs, unsigned int usecs,
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   eloop_timeout_handler handler,
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   void *eloop_data, void *user_data)
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_timeout *timeout, *tmp;
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_time_t now_sec;
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	timeout = os_zalloc(sizeof(*timeout));
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout == NULL)
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
612fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	if (os_get_reltime(&timeout->time) < 0) {
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(timeout);
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	now_sec = timeout->time.sec;
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	timeout->time.sec += secs;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (timeout->time.sec < now_sec) {
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Integer overflow - assume long enough timeout to be assumed
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * to be infinite, i.e., the timeout would never happen.
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "ever happen - ignore it", secs);
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(timeout);
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	timeout->time.usec += usecs;
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (timeout->time.usec >= 1000000) {
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		timeout->time.sec++;
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		timeout->time.usec -= 1000000;
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	timeout->eloop_data = eloop_data;
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	timeout->user_data = user_data;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	timeout->handler = handler;
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_add_ref(timeout, eloop, eloop_data);
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_add_ref(timeout, user, user_data);
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_record(timeout);
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Maintain timeouts in order of increasing time */
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
642fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt		if (os_reltime_before(&timeout->time, &tmp->time)) {
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dl_list_add(tmp->list.prev, &timeout->list);
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add_tail(&eloop.timeout, &timeout->list);
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_remove_timeout(struct eloop_timeout *timeout)
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_del(&timeout->list);
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_trace_remove_ref(timeout, user, timeout->user_data);
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(timeout);
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_cancel_timeout(eloop_timeout_handler handler,
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 void *eloop_data, void *user_data)
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_timeout *timeout, *prev;
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int removed = 0;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      struct eloop_timeout, list) {
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (timeout->handler == handler &&
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (timeout->eloop_data == eloop_data ||
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     eloop_data == ELOOP_ALL_CTX) &&
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (timeout->user_data == user_data ||
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     user_data == ELOOP_ALL_CTX)) {
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop_remove_timeout(timeout);
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			removed++;
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return removed;
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6844b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtint eloop_cancel_timeout_one(eloop_timeout_handler handler,
6854b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt			     void *eloop_data, void *user_data,
686fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			     struct os_reltime *remaining)
6874b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{
6884b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	struct eloop_timeout *timeout, *prev;
6894b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	int removed = 0;
690fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	struct os_reltime now;
6914b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
692fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	os_get_reltime(&now);
6934b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	remaining->sec = remaining->usec = 0;
6944b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
6954b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
6964b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt			      struct eloop_timeout, list) {
6974b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		if (timeout->handler == handler &&
6984b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		    (timeout->eloop_data == eloop_data) &&
6994b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		    (timeout->user_data == user_data)) {
7004b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt			removed = 1;
701fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			if (os_reltime_before(&now, &timeout->time))
702fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt				os_reltime_sub(&timeout->time, &now, remaining);
7034b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt			eloop_remove_timeout(timeout);
7044b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt			break;
7054b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		}
7064b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	}
7074b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	return removed;
7084b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt}
7094b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
7104b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_is_timeout_registered(eloop_timeout_handler handler,
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void *eloop_data, void *user_data)
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_timeout *tmp;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (tmp->handler == handler &&
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tmp->eloop_data == eloop_data &&
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    tmp->user_data == user_data)
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
727e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtint eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
728e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			  eloop_timeout_handler handler, void *eloop_data,
729e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			  void *user_data)
730e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{
731fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	struct os_reltime now, requested, remaining;
732e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	struct eloop_timeout *tmp;
733e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
734e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
735e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		if (tmp->handler == handler &&
736e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		    tmp->eloop_data == eloop_data &&
737e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		    tmp->user_data == user_data) {
738e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			requested.sec = req_secs;
739e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			requested.usec = req_usecs;
740fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			os_get_reltime(&now);
741fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			os_reltime_sub(&tmp->time, &now, &remaining);
742fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			if (os_reltime_before(&requested, &remaining)) {
743e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				eloop_cancel_timeout(handler, eloop_data,
744e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt						     user_data);
745e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				eloop_register_timeout(requested.sec,
746e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt						       requested.usec,
747e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt						       handler, eloop_data,
748e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt						       user_data);
749e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				return 1;
750e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			}
751fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			return 0;
752e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		}
753e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	}
754e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
755fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	return -1;
756e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt}
757e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
758e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt
7595460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtint eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
7605460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			    eloop_timeout_handler handler, void *eloop_data,
7615460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			    void *user_data)
7625460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{
763fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	struct os_reltime now, requested, remaining;
7645460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt	struct eloop_timeout *tmp;
7655460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
7665460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
7675460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt		if (tmp->handler == handler &&
7685460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt		    tmp->eloop_data == eloop_data &&
7695460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt		    tmp->user_data == user_data) {
7705460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			requested.sec = req_secs;
7715460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			requested.usec = req_usecs;
772fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			os_get_reltime(&now);
773fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			os_reltime_sub(&tmp->time, &now, &remaining);
774fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			if (os_reltime_before(&remaining, &requested)) {
7755460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				eloop_cancel_timeout(handler, eloop_data,
7765460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt						     user_data);
7775460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				eloop_register_timeout(requested.sec,
7785460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt						       requested.usec,
7795460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt						       handler, eloop_data,
7805460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt						       user_data);
7815460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				return 1;
7825460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			}
783fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			return 0;
7845460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt		}
7855460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt	}
7865460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
787fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	return -1;
7885460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt}
7895460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
7905460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_handle_alarm(int sig)
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "two seconds. Looks like there\n"
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "is a bug that ends up in a busy loop that "
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "prevents clean shutdown.\n"
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "Killing program forcefully.\n");
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	exit(1);
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_handle_signal(int sig)
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Use SIGALRM to break out from potential busy loops that
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * would not allow the program to be killed. */
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop.pending_terminate = 1;
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		signal(SIGALRM, eloop_handle_alarm);
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		alarm(2);
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop.signaled++;
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < eloop.signal_count; i++) {
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eloop.signals[i].sig == sig) {
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop.signals[i].signaled++;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_process_pending_signals(void)
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop.signaled == 0)
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop.signaled = 0;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eloop.pending_terminate) {
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		alarm(0);
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop.pending_terminate = 0;
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < eloop.signal_count; i++) {
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (eloop.signals[i].signaled) {
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop.signals[i].signaled = 0;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop.signals[i].handler(eloop.signals[i].sig,
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 eloop.signals[i].user_data);
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_signal(int sig, eloop_signal_handler handler,
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  void *user_data)
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_signal *tmp;
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
85861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
85961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			       sizeof(struct eloop_signal));
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (tmp == NULL)
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[eloop.signal_count].sig = sig;
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[eloop.signal_count].user_data = user_data;
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[eloop.signal_count].handler = handler;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tmp[eloop.signal_count].signaled = 0;
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop.signal_count++;
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop.signals = tmp;
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	signal(sig, eloop_handle_signal);
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_signal_terminate(eloop_signal_handler handler,
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    void *user_data)
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret = eloop_register_signal(SIGINT, handler, user_data);
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret == 0)
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = eloop_register_signal(SIGTERM, handler, user_data);
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_signal_reconfig(eloop_signal_handler handler,
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   void *user_data)
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS */
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eloop_register_signal(SIGHUP, handler, user_data);
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_run(void)
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
898c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
899c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int num_poll_fds;
900c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int timeout_ms = 0;
90150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
90250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd_set *rfds, *wfds, *efds;
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct timeval _tv;
90550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
90650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
90750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	int timeout_ms = -1;
90850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
909c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	int res;
910fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	struct os_reltime tv, now;
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
91250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rfds = os_malloc(sizeof(*rfds));
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wfds = os_malloc(sizeof(*wfds));
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	efds = os_malloc(sizeof(*efds));
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rfds == NULL || wfds == NULL || efds == NULL)
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
91850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (!eloop.terminate &&
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct eloop_timeout *timeout;
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					list);
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (timeout) {
927fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			os_get_reltime(&now);
928fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			if (os_reltime_before(&now, &timeout->time))
929fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt				os_reltime_sub(&timeout->time, &now, &tv);
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tv.sec = tv.usec = 0;
93250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
933c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			timeout_ms = tv.sec * 1000 + tv.usec / 1000;
93450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
93550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			_tv.tv_sec = tv.sec;
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			_tv.tv_usec = tv.usec;
93850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
941c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
942c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		num_poll_fds = eloop_sock_table_set_fds(
943c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			&eloop.readers, &eloop.writers, &eloop.exceptions,
944c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			eloop.pollfds, eloop.pollfds_map,
945c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			eloop.max_pollfd_map);
946c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		res = poll(eloop.pollfds, num_poll_fds,
947c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			   timeout ? timeout_ms : -1);
94850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
94950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_sock_table_set_fds(&eloop.readers, rfds);
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_sock_table_set_fds(&eloop.writers, wfds);
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_sock_table_set_fds(&eloop.exceptions, efds);
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = select(eloop.max_sock + 1, rfds, wfds, efds,
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     timeout ? &_tv : NULL);
95550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
95650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
95750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		if (eloop.count == 0) {
95850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			res = 0;
95950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		} else {
96050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			res = epoll_wait(eloop.epollfd, eloop.epoll_events,
96150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt					 eloop.count, timeout_ms);
96250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		}
96350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res < 0 && errno != EINTR && errno != 0) {
96550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			wpa_printf(MSG_ERROR, "eloop: %s: %s",
96650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
96750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt				   "poll"
96850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
96950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
97050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt				   "select"
97150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
97250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
97350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt				   "epoll"
97450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
97550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt				   , strerror(errno));
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto out;
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_process_pending_signals();
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* check if some registered timeouts have occurred */
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					list);
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (timeout) {
984fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			os_get_reltime(&now);
985fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			if (!os_reltime_before(&now, &timeout->time)) {
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void *eloop_data = timeout->eloop_data;
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				void *user_data = timeout->user_data;
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eloop_timeout_handler handler =
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					timeout->handler;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				eloop_remove_timeout(timeout);
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				handler(eloop_data, user_data);
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res <= 0)
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
999c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
1000c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
1001c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					  &eloop.exceptions, eloop.pollfds_map,
1002c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					  eloop.max_pollfd_map);
100350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
100450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_sock_table_dispatch(&eloop.readers, rfds);
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_sock_table_dispatch(&eloop.writers, wfds);
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_sock_table_dispatch(&eloop.exceptions, efds);
100850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
100950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
101050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		eloop_sock_table_dispatch(eloop.epoll_events, res);
101150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1014ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	eloop.terminate = 0;
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
101650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(rfds);
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(wfds);
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(efds);
102050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
1021c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return;
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_terminate(void)
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop.terminate = 1;
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_destroy(void)
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct eloop_timeout *timeout, *prev;
1034fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	struct os_reltime now;
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1036fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt	os_get_reltime(&now);
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      struct eloop_timeout, list) {
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int sec, usec;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sec = timeout->time.sec - now.sec;
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		usec = timeout->time.usec - now.usec;
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (timeout->time.usec < now.usec) {
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sec--;
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			usec += 1000000;
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "eloop_data=%p user_data=%p handler=%p",
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   sec, usec, timeout->eloop_data, timeout->user_data,
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   timeout->handler);
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_dump_funcname("eloop unregistered timeout handler",
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					timeout->handler);
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_trace_dump("eloop timeout", timeout);
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_remove_timeout(timeout);
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_sock_table_destroy(&eloop.readers);
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_sock_table_destroy(&eloop.writers);
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_sock_table_destroy(&eloop.exceptions);
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(eloop.signals);
1059c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1060c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
1061c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_free(eloop.pollfds);
1062c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_free(eloop.pollfds_map);
1063c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
106450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL
106550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	os_free(eloop.epoll_table);
106650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	os_free(eloop.epoll_events);
106750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	close(eloop.epollfd);
106850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_terminated(void)
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return eloop.terminate;
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_wait_for_read_sock(int sock)
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1080c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL
1081c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	struct pollfd pfd;
1082c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1083c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (sock < 0)
1084c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return;
1085c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1086c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(&pfd, 0, sizeof(pfd));
1087c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	pfd.fd = sock;
1088c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	pfd.events = POLLIN;
1089c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1090c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	poll(&pfd, 1, -1);
109150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */
109250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL)
109350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	/*
109450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * We can use epoll() here. But epoll() requres 4 system calls.
109550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for
109650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * epoll fd. So select() is better for performance here.
109750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 */
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd_set rfds;
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sock < 0)
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FD_ZERO(&rfds);
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FD_SET(sock, &rfds);
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	select(sock + 1, &rfds, NULL, NULL, NULL);
110650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
110850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
110950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT
111050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#undef CONFIG_ELOOP_SELECT
111150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */
1112