eloop.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
172128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse/*
272128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * Event loop based on select() loop
372128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
472128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse *
572128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * This program is free software; you can redistribute it and/or modify
672128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * it under the terms of the GNU General Public License version 2 as
772128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * published by the Free Software Foundation.
872128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse *
972128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * Alternatively, this software may be distributed under the terms of BSD
1072128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * license.
1172128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse *
1272128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse * See README and COPYING for more details.
1372128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse */
1472128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse
1572128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse#include "includes.h"
1672128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse
1772128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse#include "common.h"
1872128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse#include "trace.h"
1972128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse#include "list.h"
2072128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse#include "eloop.h"
2172128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse
2272128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse
23de553d906b4a205d811a9e1651f14212ec284e29Jerome Glissestruct eloop_sock {
24ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	int sock;
25077c448d184799e0d9ec962013ec784c6a5c1807Henri Verbeet	void *eloop_data;
26a3a94554f5a12f0626d9712ddcdc81b1e21d36c2Dave Airlie	void *user_data;
2772128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse	eloop_sock_handler handler;
28330b6c85c961b32f704ce8ec7dbf8cb7fc0b80a8Marek Olšák	WPA_TRACE_REF(eloop);
29ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	WPA_TRACE_REF(user);
30330b6c85c961b32f704ce8ec7dbf8cb7fc0b80a8Marek Olšák	WPA_TRACE_INFO
31330b6c85c961b32f704ce8ec7dbf8cb7fc0b80a8Marek Olšák};
32330b6c85c961b32f704ce8ec7dbf8cb7fc0b80a8Marek Olšák
33330b6c85c961b32f704ce8ec7dbf8cb7fc0b80a8Marek Olšákstruct eloop_timeout {
34ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct dl_list list;
35ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct os_time time;
36de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	void *eloop_data;
37843dfe3206c4f397c7911b748373dde5540392a4Cédric Cano	void *user_data;
38843dfe3206c4f397c7911b748373dde5540392a4Cédric Cano	eloop_timeout_handler handler;
397779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	WPA_TRACE_REF(eloop);
407779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	WPA_TRACE_REF(user);
417779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	WPA_TRACE_INFO
427779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie};
437779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie
447779f6d1dffde2c0501e44adc342e52803de08d4Dave Airliestruct eloop_signal {
457779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	int sig;
467779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	void *user_data;
477779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	eloop_signal_handler handler;
487779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	int signaled;
497779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie};
507779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie
517779f6d1dffde2c0501e44adc342e52803de08d4Dave Airliestruct eloop_sock_table {
527779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	int count;
537779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	struct eloop_sock *table;
547779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	int changed;
557779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie};
567779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie
577779f6d1dffde2c0501e44adc342e52803de08d4Dave Airliestruct eloop_data {
587779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	int max_sock;
597779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie
60a6a710cbe7425819e1cd5ad5f2085311c092f2e7Henri Verbeet	struct eloop_sock_table readers;
611235becaa1cf7e29f580900592563c3329d326deJerome Glisse	struct eloop_sock_table writers;
62e4340c1908a6a3b09e1a15d5195f6da7d00494d0Marek Olšák	struct eloop_sock_table exceptions;
631235becaa1cf7e29f580900592563c3329d326deJerome Glisse
64843dfe3206c4f397c7911b748373dde5540392a4Cédric Cano	struct dl_list timeout;
65843dfe3206c4f397c7911b748373dde5540392a4Cédric Cano
661235becaa1cf7e29f580900592563c3329d326deJerome Glisse	int signal_count;
671235becaa1cf7e29f580900592563c3329d326deJerome Glisse	struct eloop_signal *signals;
681235becaa1cf7e29f580900592563c3329d326deJerome Glisse	int signaled;
696101b6d442b06a347c001fe85848d636ab7df260Marek Olšák	int pending_terminate;
706101b6d442b06a347c001fe85848d636ab7df260Marek Olšák
711235becaa1cf7e29f580900592563c3329d326deJerome Glisse	int terminate;
721235becaa1cf7e29f580900592563c3329d326deJerome Glisse	int reader_table_changed;
731235becaa1cf7e29f580900592563c3329d326deJerome Glisse};
740a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák
75d7577ae3a6d6e174ab36d244f6bd4dedd63c3d1dHenri Verbeetstatic struct eloop_data eloop;
76d7577ae3a6d6e174ab36d244f6bd4dedd63c3d1dHenri Verbeet
77d7577ae3a6d6e174ab36d244f6bd4dedd63c3d1dHenri Verbeet
78d7577ae3a6d6e174ab36d244f6bd4dedd63c3d1dHenri Verbeet#ifdef WPA_TRACE
79d7577ae3a6d6e174ab36d244f6bd4dedd63c3d1dHenri Verbeet
80d7577ae3a6d6e174ab36d244f6bd4dedd63c3d1dHenri Verbeetstatic void eloop_sigsegv_handler(int sig)
81843dfe3206c4f397c7911b748373dde5540392a4Cédric Cano{
820a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák	wpa_trace_show("eloop SIGSEGV");
831235becaa1cf7e29f580900592563c3329d326deJerome Glisse	abort();
841235becaa1cf7e29f580900592563c3329d326deJerome Glisse}
851235becaa1cf7e29f580900592563c3329d326deJerome Glisse
861235becaa1cf7e29f580900592563c3329d326deJerome Glissestatic void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
874f7dfd8ad3185f006e7ae8ed86bafd4d66ebc903Henri Verbeet{
881235becaa1cf7e29f580900592563c3329d326deJerome Glisse	int i;
891235becaa1cf7e29f580900592563c3329d326deJerome Glisse	if (table == NULL || table->table == NULL)
901235becaa1cf7e29f580900592563c3329d326deJerome Glisse		return;
911235becaa1cf7e29f580900592563c3329d326deJerome Glisse	for (i = 0; i < table->count; i++) {
921235becaa1cf7e29f580900592563c3329d326deJerome Glisse		wpa_trace_add_ref(&table->table[i], eloop,
931235becaa1cf7e29f580900592563c3329d326deJerome Glisse				  table->table[i].eloop_data);
944f7dfd8ad3185f006e7ae8ed86bafd4d66ebc903Henri Verbeet		wpa_trace_add_ref(&table->table[i], user,
951235becaa1cf7e29f580900592563c3329d326deJerome Glisse				  table->table[i].user_data);
961235becaa1cf7e29f580900592563c3329d326deJerome Glisse	}
971235becaa1cf7e29f580900592563c3329d326deJerome Glisse}
981235becaa1cf7e29f580900592563c3329d326deJerome Glisse
991235becaa1cf7e29f580900592563c3329d326deJerome Glisse
1001235becaa1cf7e29f580900592563c3329d326deJerome Glissestatic void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
1011235becaa1cf7e29f580900592563c3329d326deJerome Glisse{
1021235becaa1cf7e29f580900592563c3329d326deJerome Glisse	int i;
1031235becaa1cf7e29f580900592563c3329d326deJerome Glisse	if (table == NULL || table->table == NULL)
1041235becaa1cf7e29f580900592563c3329d326deJerome Glisse		return;
1051235becaa1cf7e29f580900592563c3329d326deJerome Glisse	for (i = 0; i < table->count; i++) {
106e4340c1908a6a3b09e1a15d5195f6da7d00494d0Marek Olšák		wpa_trace_remove_ref(&table->table[i], eloop,
1073b1c1f02537544a11772b94a8f2e8c3d4c886ca8Henri Verbeet				     table->table[i].eloop_data);
108eafd331cf3b024001abd3f64861f41cd33a9acb2Vadim Girlin		wpa_trace_remove_ref(&table->table[i], user,
1091235becaa1cf7e29f580900592563c3329d326deJerome Glisse				     table->table[i].user_data);
110052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian König	}
111e4340c1908a6a3b09e1a15d5195f6da7d00494d0Marek Olšák}
1124acf71f01ea1edb253cd38cc059d4af1a2a40bf4Vadim Girlin
1131235becaa1cf7e29f580900592563c3329d326deJerome Glisse#else /* WPA_TRACE */
1141235becaa1cf7e29f580900592563c3329d326deJerome Glisse
115c33e091d17b90df61f7b3873a2f124c4f26adf06Jerome Glisse#define eloop_trace_sock_add_ref(table) do { } while (0)
116c33e091d17b90df61f7b3873a2f124c4f26adf06Jerome Glisse#define eloop_trace_sock_remove_ref(table) do { } while (0)
117c33e091d17b90df61f7b3873a2f124c4f26adf06Jerome Glisse
118c33e091d17b90df61f7b3873a2f124c4f26adf06Jerome Glisse#endif /* WPA_TRACE */
119052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian König
120052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian König
121052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian Königint eloop_init(void)
1224acf71f01ea1edb253cd38cc059d4af1a2a40bf4Vadim Girlin{
123543b2331d7b45a29ccd3530daa2389e87e65d89bMarek Olšák	os_memset(&eloop, 0, sizeof(eloop));
1244acf71f01ea1edb253cd38cc059d4af1a2a40bf4Vadim Girlin	dl_list_init(&eloop.timeout);
125543b2331d7b45a29ccd3530daa2389e87e65d89bMarek Olšák#ifdef WPA_TRACE
126543b2331d7b45a29ccd3530daa2389e87e65d89bMarek Olšák	signal(SIGSEGV, eloop_sigsegv_handler);
1274acf71f01ea1edb253cd38cc059d4af1a2a40bf4Vadim Girlin#endif /* WPA_TRACE */
1284acf71f01ea1edb253cd38cc059d4af1a2a40bf4Vadim Girlin	return 0;
1294acf71f01ea1edb253cd38cc059d4af1a2a40bf4Vadim Girlin}
130543b2331d7b45a29ccd3530daa2389e87e65d89bMarek Olšák
1314acf71f01ea1edb253cd38cc059d4af1a2a40bf4Vadim Girlin
1322449695e822421fdcaf1c66dffc12d7d705ea69dMarek Olšákstatic int eloop_sock_table_add_sock(struct eloop_sock_table *table,
1332449695e822421fdcaf1c66dffc12d7d705ea69dMarek Olšák                                     int sock, eloop_sock_handler handler,
1342449695e822421fdcaf1c66dffc12d7d705ea69dMarek Olšák                                     void *eloop_data, void *user_data)
1352449695e822421fdcaf1c66dffc12d7d705ea69dMarek Olšák{
136543b2331d7b45a29ccd3530daa2389e87e65d89bMarek Olšák	struct eloop_sock *tmp;
137543b2331d7b45a29ccd3530daa2389e87e65d89bMarek Olšák
138052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian König	if (table == NULL)
139eafd331cf3b024001abd3f64861f41cd33a9acb2Vadim Girlin		return -1;
1401235becaa1cf7e29f580900592563c3329d326deJerome Glisse
1411235becaa1cf7e29f580900592563c3329d326deJerome Glisse	eloop_trace_sock_remove_ref(table);
1421235becaa1cf7e29f580900592563c3329d326deJerome Glisse	tmp = (struct eloop_sock *)
1431235becaa1cf7e29f580900592563c3329d326deJerome Glisse		os_realloc(table->table,
1444a47662beaa2092447939db7880531fb706afeddMarek Olšák			   (table->count + 1) * sizeof(struct eloop_sock));
1451235becaa1cf7e29f580900592563c3329d326deJerome Glisse	if (tmp == NULL)
1461235becaa1cf7e29f580900592563c3329d326deJerome Glisse		return -1;
1471235becaa1cf7e29f580900592563c3329d326deJerome Glisse
1481235becaa1cf7e29f580900592563c3329d326deJerome Glisse	tmp[table->count].sock = sock;
149052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian König	tmp[table->count].eloop_data = eloop_data;
1504a47662beaa2092447939db7880531fb706afeddMarek Olšák	tmp[table->count].user_data = user_data;
151052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian König	tmp[table->count].handler = handler;
152052b9e8fab2e7deddf7f287d63c45aa938e5ec67Christian König	wpa_trace_record(&tmp[table->count]);
153afc56b1861c1dae4137493af4c0e6dacc6ee41f9Jerome Glisse	table->count++;
1541235becaa1cf7e29f580900592563c3329d326deJerome Glisse	table->table = tmp;
1551235becaa1cf7e29f580900592563c3329d326deJerome Glisse	if (sock > eloop.max_sock)
15669251fc4cd5f71be403e08398bc43d19052a640dJerome Glisse		eloop.max_sock = sock;
157ccb9be105602edaaff196046e324c8cb4a12fe0aTilman Sauerbeck	table->changed = 1;
1586101b6d442b06a347c001fe85848d636ab7df260Marek Olšák	eloop_trace_sock_add_ref(table);
1594a47662beaa2092447939db7880531fb706afeddMarek Olšák
160ccb9be105602edaaff196046e324c8cb4a12fe0aTilman Sauerbeck	return 0;
161ccb9be105602edaaff196046e324c8cb4a12fe0aTilman Sauerbeck}
1621235becaa1cf7e29f580900592563c3329d326deJerome Glisse
1631235becaa1cf7e29f580900592563c3329d326deJerome Glisse
1641235becaa1cf7e29f580900592563c3329d326deJerome Glissestatic void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
1652b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse                                         int sock)
1662b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse{
167a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet	int i;
168a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet
169a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet	if (table == NULL || table->table == NULL || table->count == 0)
170a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet		return;
171a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet
172a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet	for (i = 0; i < table->count; i++) {
173a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet		if (table->table[i].sock == sock)
174a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet			break;
175a77e813de32643ae2dfffd7ad12abed596172cabHenri Verbeet	}
1762b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse	if (i == table->count)
1772b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse		return;
1782b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse	eloop_trace_sock_remove_ref(table);
1792b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse	if (i != table->count - 1) {
1802b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse		os_memmove(&table->table[i], &table->table[i + 1],
1812b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse			   (table->count - i - 1) *
1822b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse			   sizeof(struct eloop_sock));
1832b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse	}
18478293b99b23268e6698f1267aaf40647c17d95a5Marek Olšák	table->count--;
1852b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse	table->changed = 1;
18640aec11b7569fcdd2d884629b172af3db3fbaf1dMike Kaplinskiy	eloop_trace_sock_add_ref(table);
18778293b99b23268e6698f1267aaf40647c17d95a5Marek Olšák}
18878293b99b23268e6698f1267aaf40647c17d95a5Marek Olšák
18978293b99b23268e6698f1267aaf40647c17d95a5Marek Olšák
190fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airliestatic void eloop_sock_table_set_fds(struct eloop_sock_table *table,
191fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie				     fd_set *fds)
192fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie{
193fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	int i;
194fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie
195725a820b926575265e6790601a0defd9c30947dcVadim Girlin	FD_ZERO(fds);
196725a820b926575265e6790601a0defd9c30947dcVadim Girlin
19754e8dcaad65cbe3603730414fd8d76ac53f89a86Vadim Girlin	if (table->table == NULL)
19854e8dcaad65cbe3603730414fd8d76ac53f89a86Vadim Girlin		return;
199c4d644bac1e738af7e2a3f1bef7eea09df8bb81cVadim Girlin
200951b888be45539e5d5b535a5a393df719fae4172Vadim Girlin	for (i = 0; i < table->count; i++)
2012b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse		FD_SET(table->table[i].sock, fds);
2022b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse}
2032b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse
2042b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse
2052b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glissestatic void eloop_sock_table_dispatch(struct eloop_sock_table *table,
2062b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse				      fd_set *fds)
2072b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse{
2082b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse	int i;
2092b3b76a4a0e21eb4bd4f1a4da5ff6ed26ccbabd1Jerome Glisse
2107779f6d1dffde2c0501e44adc342e52803de08d4Dave Airlie	if (table == NULL || table->table == NULL)
21142c966bc496d4049d98eb1d45dd7bb0b55fa41bdTilman Sauerbeck		return;
212ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
213ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	table->changed = 0;
214ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	for (i = 0; i < table->count; i++) {
215ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		if (FD_ISSET(table->table[i].sock, fds)) {
216ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			table->table[i].handler(table->table[i].sock,
217ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard						table->table[i].eloop_data,
218ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard						table->table[i].user_data);
219ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			if (table->changed)
220ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				break;
221ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		}
222ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	}
223ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
224ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
225ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
226ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardstatic void eloop_sock_table_destroy(struct eloop_sock_table *table)
2276a829a1b724ca0d960decee217d260b4de8a5463Adam Rak{
2286a829a1b724ca0d960decee217d260b4de8a5463Adam Rak	if (table) {
2296a829a1b724ca0d960decee217d260b4de8a5463Adam Rak		int i;
2306a829a1b724ca0d960decee217d260b4de8a5463Adam Rak		for (i = 0; i < table->count && table->table; i++) {
2316a829a1b724ca0d960decee217d260b4de8a5463Adam Rak			wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
2326a829a1b724ca0d960decee217d260b4de8a5463Adam Rak				   "sock=%d eloop_data=%p user_data=%p "
2336a829a1b724ca0d960decee217d260b4de8a5463Adam Rak				   "handler=%p",
2346a829a1b724ca0d960decee217d260b4de8a5463Adam Rak				   table->table[i].sock,
2356a829a1b724ca0d960decee217d260b4de8a5463Adam Rak				   table->table[i].eloop_data,
2366a829a1b724ca0d960decee217d260b4de8a5463Adam Rak				   table->table[i].user_data,
2376a829a1b724ca0d960decee217d260b4de8a5463Adam Rak				   table->table[i].handler);
2386a829a1b724ca0d960decee217d260b4de8a5463Adam Rak			wpa_trace_dump_funcname("eloop unregistered socket "
2396a829a1b724ca0d960decee217d260b4de8a5463Adam Rak						"handler",
2406a829a1b724ca0d960decee217d260b4de8a5463Adam Rak						table->table[i].handler);
2416a829a1b724ca0d960decee217d260b4de8a5463Adam Rak			wpa_trace_dump("eloop sock", &table->table[i]);
2426a829a1b724ca0d960decee217d260b4de8a5463Adam Rak		}
2436a829a1b724ca0d960decee217d260b4de8a5463Adam Rak		os_free(table->table);
2446a829a1b724ca0d960decee217d260b4de8a5463Adam Rak	}
2456a829a1b724ca0d960decee217d260b4de8a5463Adam Rak}
2466a829a1b724ca0d960decee217d260b4de8a5463Adam Rak
2476a829a1b724ca0d960decee217d260b4de8a5463Adam Rak
2486a829a1b724ca0d960decee217d260b4de8a5463Adam Rakint eloop_register_read_sock(int sock, eloop_sock_handler handler,
2490c4b19ac63efa41242c515824301e6161aceeea5Tom Stellard			     void *eloop_data, void *user_data)
2500c4b19ac63efa41242c515824301e6161aceeea5Tom Stellard{
2510c4b19ac63efa41242c515824301e6161aceeea5Tom Stellard	return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
2526a829a1b724ca0d960decee217d260b4de8a5463Adam Rak				   eloop_data, user_data);
2536a829a1b724ca0d960decee217d260b4de8a5463Adam Rak}
2546a829a1b724ca0d960decee217d260b4de8a5463Adam Rak
2556a829a1b724ca0d960decee217d260b4de8a5463Adam Rak
2566a829a1b724ca0d960decee217d260b4de8a5463Adam Rakvoid eloop_unregister_read_sock(int sock)
2576a829a1b724ca0d960decee217d260b4de8a5463Adam Rak{
2586a829a1b724ca0d960decee217d260b4de8a5463Adam Rak	eloop_unregister_sock(sock, EVENT_TYPE_READ);
2596a829a1b724ca0d960decee217d260b4de8a5463Adam Rak}
2606a829a1b724ca0d960decee217d260b4de8a5463Adam Rak
2612c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
2622c485cda2062ca2b9af89ea62618515d960c7904Tom Stellardstatic struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
2632c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard{
2642c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	switch (type) {
2652c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	case EVENT_TYPE_READ:
2662c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard		return &eloop.readers;
2672c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	case EVENT_TYPE_WRITE:
2682c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard		return &eloop.writers;
2692c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	case EVENT_TYPE_EXCEPTION:
2702c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard		return &eloop.exceptions;
2712c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	}
272ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
273ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	return NULL;
274ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
275ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
276ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
277ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardint eloop_register_sock(int sock, eloop_event_type type,
278ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			eloop_sock_handler handler,
279ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			void *eloop_data, void *user_data)
280ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
281ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct eloop_sock_table *table;
282ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
283ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	table = eloop_get_sock_table(type);
284ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	return eloop_sock_table_add_sock(table, sock, handler,
285ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard					 eloop_data, user_data);
286ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
287ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
288ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
289ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardvoid eloop_unregister_sock(int sock, eloop_event_type type)
290ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
291ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct eloop_sock_table *table;
292ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
293ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	table = eloop_get_sock_table(type);
294ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	eloop_sock_table_remove_sock(table, sock);
295ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
2968f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune
297ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
298ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardint eloop_register_timeout(unsigned int secs, unsigned int usecs,
299ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			   eloop_timeout_handler handler,
300ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			   void *eloop_data, void *user_data)
301ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
302ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct eloop_timeout *timeout, *tmp;
303ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	os_time_t now_sec;
304ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
305ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	timeout = os_zalloc(sizeof(*timeout));
306ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	if (timeout == NULL)
307ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		return -1;
308ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	if (os_get_time(&timeout->time) < 0) {
309ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		os_free(timeout);
310ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		return -1;
311ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	}
312ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	now_sec = timeout->time.sec;
313ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	timeout->time.sec += secs;
3148f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	if (timeout->time.sec < now_sec) {
315da676eab93e7dad30b574b4eb4cffd4df952e819Vincent Lejeune		/*
316ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		 * Integer overflow - assume long enough timeout to be assumed
317ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		 * to be infinite, i.e., the timeout would never happen.
318ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		 */
319ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
3208f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune			   "ever happen - ignore it", secs);
3218f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune		os_free(timeout);
3228f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune		return 0;
3238f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	}
3248f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	timeout->time.usec += usecs;
3258f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	while (timeout->time.usec >= 1000000) {
3268f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune		timeout->time.sec++;
3278f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune		timeout->time.usec -= 1000000;
3288f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	}
3298f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	timeout->eloop_data = eloop_data;
3308f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	timeout->user_data = user_data;
3318f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	timeout->handler = handler;
3328f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	wpa_trace_add_ref(timeout, eloop, eloop_data);
3338f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	wpa_trace_add_ref(timeout, user, user_data);
3348f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	wpa_trace_record(timeout);
3358f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune
3368f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	/* Maintain timeouts in order of increasing time */
3378f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
3388f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune		if (os_time_before(&timeout->time, &tmp->time)) {
3398f597d57e959830040473b548e0e04cfc63866c2Vincent Lejeune			dl_list_add(tmp->list.prev, &timeout->list);
340ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			return 0;
341ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		}
342ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	}
343ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	dl_list_add_tail(&eloop.timeout, &timeout->list);
344ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
345ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	return 0;
346ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
347ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
348ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
349ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardstatic void eloop_remove_timeout(struct eloop_timeout *timeout)
350ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
351ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	dl_list_del(&timeout->list);
352ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
353ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	wpa_trace_remove_ref(timeout, user, timeout->user_data);
354ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	os_free(timeout);
355ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
356ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
357ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
358ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardint eloop_cancel_timeout(eloop_timeout_handler handler,
359ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			 void *eloop_data, void *user_data)
360ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
361ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct eloop_timeout *timeout, *prev;
362ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	int removed = 0;
363ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
364ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
365ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			      struct eloop_timeout, list) {
366ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		if (timeout->handler == handler &&
367ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		    (timeout->eloop_data == eloop_data ||
368ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		     eloop_data == ELOOP_ALL_CTX) &&
369ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		    (timeout->user_data == user_data ||
370ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		     user_data == ELOOP_ALL_CTX)) {
371ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			eloop_remove_timeout(timeout);
372ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			removed++;
373ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		}
374ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	}
375ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
376ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	return removed;
377ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
378ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
379ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
380ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardint eloop_is_timeout_registered(eloop_timeout_handler handler,
381ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				void *eloop_data, void *user_data)
3822fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard{
383ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct eloop_timeout *tmp;
384ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
385ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
3862fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard		if (tmp->handler == handler &&
387bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeune		    tmp->eloop_data == eloop_data &&
388bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeune		    tmp->user_data == user_data)
389ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			return 1;
3902fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard	}
391bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeune
392ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	return 0;
3932fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard}
394bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeune
395ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
3962fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard#ifndef CONFIG_NATIVE_WINDOWS
397bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeunestatic void eloop_handle_alarm(int sig)
398ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
3992fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard	wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
400bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeune		   "two seconds. Looks like there\n"
401ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		   "is a bug that ends up in a busy loop that "
4022fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard		   "prevents clean shutdown.\n"
403ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		   "Killing program forcefully.\n");
404bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeune	exit(1);
405ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
4062fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard#endif /* CONFIG_NATIVE_WINDOWS */
407bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeune
4082fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard
409bc4b4c605cc04138e5209782fa5939bfd71930bdVincent Lejeunestatic void eloop_handle_signal(int sig)
4102fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard{
411ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	int i;
412ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
413ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard#ifndef CONFIG_NATIVE_WINDOWS
414ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
415ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		/* Use SIGALRM to break out from potential busy loops that
416ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		 * would not allow the program to be killed. */
417ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		eloop.pending_terminate = 1;
418ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		signal(SIGALRM, eloop_handle_alarm);
419ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		alarm(2);
420ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	}
421ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard#endif /* CONFIG_NATIVE_WINDOWS */
422ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
423ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	eloop.signaled++;
424ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	for (i = 0; i < eloop.signal_count; i++) {
425ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		if (eloop.signals[i].sig == sig) {
4262fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard			eloop.signals[i].signaled++;
42718617d7423b2c12aac9adbb8354fbf5d0c8ddfeaTom Stellard			break;
42818617d7423b2c12aac9adbb8354fbf5d0c8ddfeaTom Stellard		}
42918617d7423b2c12aac9adbb8354fbf5d0c8ddfeaTom Stellard	}
4302fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard}
4312fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard
4322fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellard
4332fae8227ad906a6d6290134368b62f5dd3a1858eTom Stellardstatic void eloop_process_pending_signals(void)
434ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
435ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	int i;
436ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
437ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	if (eloop.signaled == 0)
438ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		return;
439ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	eloop.signaled = 0;
440ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
441ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	if (eloop.pending_terminate) {
442ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard#ifndef CONFIG_NATIVE_WINDOWS
443ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		alarm(0);
444ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard#endif /* CONFIG_NATIVE_WINDOWS */
445ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		eloop.pending_terminate = 0;
446ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	}
447ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
448ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	for (i = 0; i < eloop.signal_count; i++) {
449ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		if (eloop.signals[i].signaled) {
450ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			eloop.signals[i].signaled = 0;
451ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			eloop.signals[i].handler(eloop.signals[i].sig,
452ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard						 eloop.signals[i].user_data);
453ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		}
454ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	}
455ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard}
456ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
457ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
458ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellardint eloop_register_signal(int sig, eloop_signal_handler handler,
459ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			  void *user_data)
460ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard{
461ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	struct eloop_signal *tmp;
462ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
463ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	tmp = (struct eloop_signal *)
464ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		os_realloc(eloop.signals,
465ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			   (eloop.signal_count + 1) *
466ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			   sizeof(struct eloop_signal));
467ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	if (tmp == NULL)
468ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		return -1;
469ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
470ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	tmp[eloop.signal_count].sig = sig;
471ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	tmp[eloop.signal_count].user_data = user_data;
472ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	tmp[eloop.signal_count].handler = handler;
473e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	tmp[eloop.signal_count].signaled = 0;
474e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	eloop.signal_count++;
475e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	eloop.signals = tmp;
476e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	signal(sig, eloop_handle_signal);
4772c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
4782c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	return 0;
4792c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard}
4802c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
4812c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
482e42df8e10a83e76565474f82330d34403da71b49Tom Stellardint eloop_register_signal_terminate(eloop_signal_handler handler,
4832c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard				    void *user_data)
4842c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard{
4852c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	int ret = eloop_register_signal(SIGINT, handler, user_data);
4862c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	if (ret == 0)
4872c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard		ret = eloop_register_signal(SIGTERM, handler, user_data);
4882c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	return ret;
4892c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard}
4902c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
4912c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
4922c485cda2062ca2b9af89ea62618515d960c7904Tom Stellardint eloop_register_signal_reconfig(eloop_signal_handler handler,
4932c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard				   void *user_data)
4942c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard{
4952c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard#ifdef CONFIG_NATIVE_WINDOWS
4962c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	return 0;
4972c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard#else /* CONFIG_NATIVE_WINDOWS */
4982c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	return eloop_register_signal(SIGHUP, handler, user_data);
4992c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard#endif /* CONFIG_NATIVE_WINDOWS */
5002c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard}
5012c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
5022c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard
5032c485cda2062ca2b9af89ea62618515d960c7904Tom Stellardvoid eloop_run(void)
5042c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard{
5052c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	fd_set *rfds, *wfds, *efds;
5062c485cda2062ca2b9af89ea62618515d960c7904Tom Stellard	int res;
507e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	struct timeval _tv;
508e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	struct os_time tv, now;
509e42df8e10a83e76565474f82330d34403da71b49Tom Stellard
510e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	rfds = os_malloc(sizeof(*rfds));
511e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	wfds = os_malloc(sizeof(*wfds));
512e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	efds = os_malloc(sizeof(*efds));
513e42df8e10a83e76565474f82330d34403da71b49Tom Stellard	if (rfds == NULL || wfds == NULL || efds == NULL)
514e42df8e10a83e76565474f82330d34403da71b49Tom Stellard		goto out;
515e42df8e10a83e76565474f82330d34403da71b49Tom Stellard
516ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	while (!eloop.terminate &&
517ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard	       (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
518ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
519ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		struct eloop_timeout *timeout;
5206f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
521ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard					list);
522ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		if (timeout) {
523ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			os_get_time(&now);
524ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			if (os_time_before(&now, &timeout->time))
525ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				os_time_sub(&timeout->time, &now, &tv);
526ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			else
527ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				tv.sec = tv.usec = 0;
528ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			_tv.tv_sec = tv.sec;
529ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			_tv.tv_usec = tv.usec;
530ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		}
531ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
532ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		eloop_sock_table_set_fds(&eloop.readers, rfds);
533ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		eloop_sock_table_set_fds(&eloop.writers, wfds);
534ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		eloop_sock_table_set_fds(&eloop.exceptions, efds);
535ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		res = select(eloop.max_sock + 1, rfds, wfds, efds,
5366f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard			     timeout ? &_tv : NULL);
5376f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard		if (res < 0 && errno != EINTR && errno != 0) {
5386f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard			perror("select");
5396f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard			goto out;
5406f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard		}
5416f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard		eloop_process_pending_signals();
5426f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard
5436f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard		/* check if some registered timeouts have occurred */
5446f50f939ef85bb058c1401b5dad8340aa4f96aecTom Stellard		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
545e42df8e10a83e76565474f82330d34403da71b49Tom Stellard					list);
546e42df8e10a83e76565474f82330d34403da71b49Tom Stellard		if (timeout) {
547e42df8e10a83e76565474f82330d34403da71b49Tom Stellard			os_get_time(&now);
548e42df8e10a83e76565474f82330d34403da71b49Tom Stellard			if (!os_time_before(&now, &timeout->time)) {
549e42df8e10a83e76565474f82330d34403da71b49Tom Stellard				void *eloop_data = timeout->eloop_data;
550ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				void *user_data = timeout->user_data;
551ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				eloop_timeout_handler handler =
552ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard					timeout->handler;
553ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				eloop_remove_timeout(timeout);
554ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard				handler(eloop_data, user_data);
555ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard			}
556ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard
557ced73ea5df306156e5383b438d6858e58b1479e5Tom Stellard		}
558de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse
559de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		if (res <= 0)
560de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse			continue;
561de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse
562de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		eloop_sock_table_dispatch(&eloop.readers, rfds);
563de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		eloop_sock_table_dispatch(&eloop.writers, wfds);
564de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		eloop_sock_table_dispatch(&eloop.exceptions, efds);
565de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	}
566de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse
56772128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisseout:
568de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	os_free(rfds);
569de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	os_free(wfds);
570de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	os_free(efds);
571c6131879eb7dfdf26cd068109f6680608d608ab4Jerome Glisse}
572a03d456f5a41926e39194de70b2d50776e64b8a2Dave Airlie
573de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse
574de553d906b4a205d811a9e1651f14212ec284e29Jerome Glissevoid eloop_terminate(void)
575de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse{
57672128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse	eloop.terminate = 1;
577a03d456f5a41926e39194de70b2d50776e64b8a2Dave Airlie}
578de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse
5798260ab93461eca3e18f9c17a9ca1961a11372071Keith Whitwell
5808260ab93461eca3e18f9c17a9ca1961a11372071Keith Whitwellvoid eloop_destroy(void)
5818260ab93461eca3e18f9c17a9ca1961a11372071Keith Whitwell{
582de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	struct eloop_timeout *timeout, *prev;
583de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	struct os_time now;
584de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse
585de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse	os_get_time(&now);
58647d5a19df1e7760c4f5f0e340bfc56355c2e428bDave Airlie	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
58747d5a19df1e7760c4f5f0e340bfc56355c2e428bDave Airlie			      struct eloop_timeout, list) {
588de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		int sec, usec;
589de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		sec = timeout->time.sec - now.sec;
590de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		usec = timeout->time.usec - now.usec;
591de553d906b4a205d811a9e1651f14212ec284e29Jerome Glisse		if (timeout->time.usec < now.usec) {
59272128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse			sec--;
59372128962d640846472c1b0dc22cf4ac6ce875dc9Jerome Glisse			usec += 1000000;
594fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie		}
59550526e094f4c66957c7f74c190c35903bc82fb62Dave Airlie		wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
59650526e094f4c66957c7f74c190c35903bc82fb62Dave Airlie			   "eloop_data=%p user_data=%p handler=%p",
5974a47662beaa2092447939db7880531fb706afeddMarek Olšák			   sec, usec, timeout->eloop_data, timeout->user_data,
598fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie			   timeout->handler);
599fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie		wpa_trace_dump_funcname("eloop unregistered timeout handler",
600fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie					timeout->handler);
601fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie		wpa_trace_dump("eloop timeout", timeout);
602fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie		eloop_remove_timeout(timeout);
603fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	}
604fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	eloop_sock_table_destroy(&eloop.readers);
605fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	eloop_sock_table_destroy(&eloop.writers);
606fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	eloop_sock_table_destroy(&eloop.exceptions);
607fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	os_free(eloop.signals);
608fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie}
609fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie
610fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie
611fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlieint eloop_terminated(void)
612fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie{
613fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	return eloop.terminate;
614fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie}
615fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie
616fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie
6177ffd4e976fd11b8c083c2927effd25a2f79ac841Jerome Glissevoid eloop_wait_for_read_sock(int sock)
618fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie{
619fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie	fd_set rfds;
620fc6caef4cb67fb13642c5ebccee53019d1764df6Dave Airlie
62150526e094f4c66957c7f74c190c35903bc82fb62Dave Airlie	if (sock < 0)
62250526e094f4c66957c7f74c190c35903bc82fb62Dave Airlie		return;
6234a47662beaa2092447939db7880531fb706afeddMarek Olšák
62450526e094f4c66957c7f74c190c35903bc82fb62Dave Airlie	FD_ZERO(&rfds);
62550526e094f4c66957c7f74c190c35903bc82fb62Dave Airlie	FD_SET(sock, &rfds);
626738334e80cf8a7b9fbf573f3a77cbf767ce81095Vadim Girlin	select(sock + 1, &rfds, NULL, NULL, NULL);
62750526e094f4c66957c7f74c190c35903bc82fb62Dave Airlie}
628738334e80cf8a7b9fbf573f3a77cbf767ce81095Vadim Girlin