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