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 21b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_KQUEUE) 22b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#error Do not define both of poll and kqueue 23b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif 24b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 25b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) && \ 26b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt !defined(CONFIG_ELOOP_KQUEUE) 2750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#define CONFIG_ELOOP_SELECT 2850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif 2950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 30c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 31c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#include <poll.h> 32c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 33c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 3450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 3550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#include <sys/epoll.h> 3650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 39b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#include <sys/event.h> 40b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 41b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_sock { 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_data; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_handler handler; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_TRACE_REF(eloop); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_TRACE_REF(user); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_TRACE_INFO 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_timeout { 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct dl_list list; 54fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime time; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_data; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_timeout_handler handler; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_TRACE_REF(eloop); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_TRACE_REF(user); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_TRACE_INFO 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_signal { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sig; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_data; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_signal_handler handler; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int signaled; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_sock_table { 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_sock *table; 7350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop_event_type type; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int changed; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eloop_data { 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int max_sock; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 80c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int count; /* sum of all table counts */ 81c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 82c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int max_pollfd_map; /* number of pollfds_map currently allocated */ 83c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int max_poll_fds; /* number of pollfds currently allocated */ 84c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd *pollfds; 85c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd **pollfds_map; 86c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 87b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) 88b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int max_fd; 89b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct eloop_sock *fd_table; 90b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ 9150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 9250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt int epollfd; 9350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt int epoll_max_event_num; 9450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt struct epoll_event *epoll_events; 9550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 96b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 97b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int kqueuefd; 98b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int kqueue_nevents; 99b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct kevent *kqueue_events; 100b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_sock_table readers; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_sock_table writers; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_sock_table exceptions; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct dl_list timeout; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int signal_count; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_signal *signals; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int signaled; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pending_terminate; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int terminate; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eloop_data eloop; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sigsegv_handler(int sig) 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_show("eloop SIGSEGV"); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt abort(); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_trace_sock_add_ref(struct eloop_sock_table *table) 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table == NULL || table->table == NULL) 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < table->count; i++) { 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_add_ref(&table->table[i], eloop, 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].eloop_data); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_add_ref(&table->table[i], user, 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].user_data); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table == NULL || table->table == NULL) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < table->count; i++) { 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_remove_ref(&table->table[i], eloop, 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].eloop_data); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_remove_ref(&table->table[i], user, 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].user_data); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* WPA_TRACE */ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define eloop_trace_sock_add_ref(table) do { } while (0) 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define eloop_trace_sock_remove_ref(table) do { } while (0) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_init(void) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&eloop, 0, sizeof(eloop)); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&eloop.timeout); 16550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 16650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.epollfd = epoll_create1(0); 16750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (eloop.epollfd < 0) { 168b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s", 169b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, strerror(errno)); 170b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return -1; 171b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 172b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 173b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 174b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.kqueuefd = kqueue(); 175b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop.kqueuefd < 0) { 176b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: kqueue failed: %s", 17750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt __func__, strerror(errno)); 17850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt return -1; 17950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 180b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 181b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) 18250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.readers.type = EVENT_TYPE_READ; 18350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.writers.type = EVENT_TYPE_WRITE; 18450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.exceptions.type = EVENT_TYPE_EXCEPTION; 185b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef WPA_TRACE 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt signal(SIGSEGV, eloop_sigsegv_handler); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* WPA_TRACE */ 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 193b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 194b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidtstatic int eloop_sock_queue(int sock, eloop_event_type type) 195b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt{ 196b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct epoll_event ev; 197b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 198b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt os_memset(&ev, 0, sizeof(ev)); 199b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt switch (type) { 200b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt case EVENT_TYPE_READ: 201b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt ev.events = EPOLLIN; 202b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt break; 203b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt case EVENT_TYPE_WRITE: 204b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt ev.events = EPOLLOUT; 205b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt break; 206b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt /* 207b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt * Exceptions are always checked when using epoll, but I suppose it's 208b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt * possible that someone registered a socket *only* for exception 209b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt * handling. 210b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt */ 211b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt case EVENT_TYPE_EXCEPTION: 212b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt ev.events = EPOLLERR | EPOLLHUP; 213b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt break; 214b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 215b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt ev.data.fd = sock; 216b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) { 217b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d failed: %s", 218b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, sock, strerror(errno)); 219b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return -1; 220b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 221b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return 0; 222b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt} 223b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 224b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 225b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 226b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 227b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidtstatic int eloop_sock_queue(int sock, eloop_event_type type) 228b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt{ 229b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int filter; 230b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct kevent ke; 231b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 232b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt switch (type) { 233b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt case EVENT_TYPE_READ: 234b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt filter = EVFILT_READ; 235b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt break; 236b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt case EVENT_TYPE_WRITE: 237b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt filter = EVFILT_WRITE; 238b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt break; 239b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt default: 240b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt filter = 0; 241b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 24257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt EV_SET(&ke, sock, filter, EV_ADD, 0, 0, 0); 243b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) == -1) { 244b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: kevent(ADD) for fd=%d failed: %s", 245b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, sock, strerror(errno)); 246b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return -1; 247b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 248b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return 0; 249b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt} 250b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 251b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 252b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eloop_sock_table_add_sock(struct eloop_sock_table *table, 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock, eloop_sock_handler handler, 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data, void *user_data) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 258b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct epoll_event *temp_events; 259b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 260b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 261b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct kevent *temp_events; 262b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 263b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) 26450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt struct eloop_sock *temp_table; 26550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt int next; 266b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_sock *tmp; 268c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int new_max_sock; 269c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 270c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sock > eloop.max_sock) 271c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt new_max_sock = sock; 272c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt else 273c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt new_max_sock = eloop.max_sock; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table == NULL) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 279c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (new_max_sock >= eloop.max_pollfd_map) { 280c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd **nmap; 28161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50, 28261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(struct pollfd *)); 283c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (nmap == NULL) 284c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return -1; 285c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 286c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.max_pollfd_map = new_max_sock + 50; 287c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.pollfds_map = nmap; 288c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 289c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 290c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (eloop.count + 1 > eloop.max_poll_fds) { 291c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd *n; 292c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int nmax = eloop.count + 1 + 50; 29361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt n = os_realloc_array(eloop.pollfds, nmax, 29461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(struct pollfd)); 295c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (n == NULL) 296c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return -1; 297c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 298c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.max_poll_fds = nmax; 299c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.pollfds = n; 300c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 301c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 302b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) 303b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (new_max_sock >= eloop.max_fd) { 304b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt next = eloop.max_fd == 0 ? 16 : eloop.max_fd * 2; 305b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt temp_table = os_realloc_array(eloop.fd_table, next, 30650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt sizeof(struct eloop_sock)); 30750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (temp_table == NULL) 30850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt return -1; 30950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 310b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.max_fd = next; 311b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.fd_table = temp_table; 31250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 313b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ 31450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 315b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 31650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (eloop.count + 1 > eloop.epoll_max_event_num) { 31750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt next = eloop.epoll_max_event_num == 0 ? 8 : 31850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.epoll_max_event_num * 2; 31950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt temp_events = os_realloc_array(eloop.epoll_events, next, 32050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt sizeof(struct epoll_event)); 32150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (temp_events == NULL) { 322b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: malloc for epoll failed: %s", 323b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, strerror(errno)); 32450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt return -1; 32550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 32650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 32750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.epoll_max_event_num = next; 32850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.epoll_events = temp_events; 32950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 33050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 331b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 332b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop.count + 1 > eloop.kqueue_nevents) { 333b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt next = eloop.kqueue_nevents == 0 ? 8 : eloop.kqueue_nevents * 2; 334b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt temp_events = os_malloc(next * sizeof(*temp_events)); 335b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (!temp_events) { 336b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, 337b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt "%s: malloc for kqueue failed: %s", 338b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, strerror(errno)); 339b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return -1; 340b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 341b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 342b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt os_free(eloop.kqueue_events); 343b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.kqueue_events = temp_events; 344b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.kqueue_nevents = next; 345b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 346b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 347c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_trace_sock_remove_ref(table); 34961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt tmp = os_realloc_array(table->table, table->count + 1, 35061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(struct eloop_sock)); 351746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt if (tmp == NULL) { 352746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt eloop_trace_sock_add_ref(table); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 354746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt } 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[table->count].sock = sock; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[table->count].eloop_data = eloop_data; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[table->count].user_data = user_data; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[table->count].handler = handler; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_record(&tmp[table->count]); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->count++; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table = tmp; 363c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.max_sock = new_max_sock; 364c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.count++; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->changed = 1; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_trace_sock_add_ref(table); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) 369b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop_sock_queue(sock, table->type) < 0) 37050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt return -1; 371b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt os_memcpy(&eloop.fd_table[sock], &table->table[table->count - 1], 37250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt sizeof(struct eloop_sock)); 373b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_remove_sock(struct eloop_sock_table *table, 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sock) 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 381b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 382b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct kevent ke; 383b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table == NULL || table->table == NULL || table->count == 0) 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < table->count; i++) { 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table->table[i].sock == sock) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i == table->count) 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_trace_sock_remove_ref(table); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i != table->count - 1) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(&table->table[i], &table->table[i + 1], 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (table->count - i - 1) * 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct eloop_sock)); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->count--; 402c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.count--; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->changed = 1; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_trace_sock_add_ref(table); 40550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 40650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) { 407b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d failed: %s", 408b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, sock, strerror(errno)); 40950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt return; 41050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 411b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock)); 41250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 413b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 41457c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt EV_SET(&ke, sock, 0, EV_DELETE, 0, 0, 0); 415b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) < 0) { 416b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: kevent(DEL) for fd=%d failed: %s", 417b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, sock, strerror(errno)); 418b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return; 419b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 420b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock)); 421b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 425c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 426c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 427c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx) 428c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 429c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (fd < mx && fd >= 0) 430c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return pollfds_map[fd]; 431c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return NULL; 432c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 433c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 434c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 435c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int eloop_sock_table_set_fds(struct eloop_sock_table *readers, 436c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct eloop_sock_table *writers, 437c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct eloop_sock_table *exceptions, 438c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd *pollfds, 439c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd **pollfds_map, 440c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int max_pollfd_map) 441c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 442c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int i; 443c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int nxt = 0; 444c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int fd; 445c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd *pfd; 446c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 447c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Clear pollfd lookup map. It will be re-populated below. */ 448c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map); 449c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 450c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (readers && readers->table) { 451c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (i = 0; i < readers->count; i++) { 452c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt fd = readers->table[i].sock; 453c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt assert(fd >= 0 && fd < max_pollfd_map); 454c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds[nxt].fd = fd; 455c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds[nxt].events = POLLIN; 456c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds[nxt].revents = 0; 457c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds_map[fd] = &(pollfds[nxt]); 458c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt nxt++; 459c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 460c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 461c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 462c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (writers && writers->table) { 463c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (i = 0; i < writers->count; i++) { 464c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 465c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See if we already added this descriptor, update it 466c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * if so. 467c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 468c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt fd = writers->table[i].sock; 469c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt assert(fd >= 0 && fd < max_pollfd_map); 470c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd = pollfds_map[fd]; 471c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!pfd) { 472c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd = &(pollfds[nxt]); 473c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd->events = 0; 474c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd->fd = fd; 475c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds[i].revents = 0; 476c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds_map[fd] = pfd; 477c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt nxt++; 478c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 47904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pfd->events |= POLLOUT; 480c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 481c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 482c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 483c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 484c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * Exceptions are always checked when using poll, but I suppose it's 485c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * possible that someone registered a socket *only* for exception 486c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * handling. Set the POLLIN bit in this case. 487c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 488c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (exceptions && exceptions->table) { 489c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (i = 0; i < exceptions->count; i++) { 490c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* 491c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See if we already added this descriptor, just use it 492c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * if so. 493c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt */ 494c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt fd = exceptions->table[i].sock; 495c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt assert(fd >= 0 && fd < max_pollfd_map); 496c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd = pollfds_map[fd]; 497c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!pfd) { 498c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd = &(pollfds[nxt]); 499c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd->events = POLLIN; 500c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd->fd = fd; 501c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds[i].revents = 0; 502c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pollfds_map[fd] = pfd; 503c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt nxt++; 504c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 505c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 506c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 507c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 508c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return nxt; 509c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 510c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 511c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 512c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int eloop_sock_table_dispatch_table(struct eloop_sock_table *table, 513c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd **pollfds_map, 514c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int max_pollfd_map, 515c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt short int revents) 516c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 517c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int i; 518c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd *pfd; 519c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 520c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!table || !table->table) 521c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 0; 522c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 523c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt table->changed = 0; 524c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (i = 0; i < table->count; i++) { 525c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd = find_pollfd(pollfds_map, table->table[i].sock, 526c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt max_pollfd_map); 527c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!pfd) 528c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt continue; 529c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 530c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (!(pfd->revents & revents)) 531c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt continue; 532c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 533c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt table->table[i].handler(table->table[i].sock, 534c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt table->table[i].eloop_data, 535c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt table->table[i].user_data); 536c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (table->changed) 537c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 1; 538c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 539c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 540c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return 0; 541c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 542c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 543c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 544c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic void eloop_sock_table_dispatch(struct eloop_sock_table *readers, 545c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct eloop_sock_table *writers, 546c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct eloop_sock_table *exceptions, 547c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd **pollfds_map, 548c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int max_pollfd_map) 549c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{ 550c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (eloop_sock_table_dispatch_table(readers, pollfds_map, 55104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt max_pollfd_map, POLLIN | POLLERR | 55204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt POLLHUP)) 553c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; /* pollfds may be invalid at this point */ 554c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 555c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (eloop_sock_table_dispatch_table(writers, pollfds_map, 556c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt max_pollfd_map, POLLOUT)) 557c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; /* pollfds may be invalid at this point */ 558c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 559c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop_sock_table_dispatch_table(exceptions, pollfds_map, 560c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt max_pollfd_map, POLLERR | POLLHUP); 561c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt} 562c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 56350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 56450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 56550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 566c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_set_fds(struct eloop_sock_table *table, 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fd_set *fds) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FD_ZERO(fds); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table->table == NULL) 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 577df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt for (i = 0; i < table->count; i++) { 578df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt assert(table->table[i].sock >= 0); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FD_SET(table->table[i].sock, fds); 580df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_dispatch(struct eloop_sock_table *table, 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fd_set *fds) 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table == NULL || table->table == NULL) 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->changed = 0; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < table->count; i++) { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (FD_ISSET(table->table[i].sock, fds)) { 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].handler(table->table[i].sock, 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].eloop_data, 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].user_data); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table->changed) 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 60550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 60650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 60750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 60850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidtstatic void eloop_sock_table_dispatch(struct epoll_event *events, int nfds) 60950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt{ 61050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt struct eloop_sock *table; 61150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt int i; 61250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 61350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt for (i = 0; i < nfds; i++) { 614b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt table = &eloop.fd_table[events[i].data.fd]; 61550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (table->handler == NULL) 61650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt continue; 61750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt table->handler(table->sock, table->eloop_data, 61850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt table->user_data); 619d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (eloop.readers.changed || 620d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop.writers.changed || 621d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop.exceptions.changed) 622d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt break; 62350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 62450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt} 62550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 626c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 629b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 630b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidtstatic void eloop_sock_table_dispatch(struct kevent *events, int nfds) 631b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt{ 632b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct eloop_sock *table; 633b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int i; 634b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 635b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt for (i = 0; i < nfds; i++) { 636b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt table = &eloop.fd_table[events[i].ident]; 637b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (table->handler == NULL) 638b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt continue; 639b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt table->handler(table->sock, table->eloop_data, 640b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt table->user_data); 641b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop.readers.changed || 642b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.writers.changed || 643b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.exceptions.changed) 644b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt break; 645b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 646b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt} 647b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 648b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 649b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidtstatic int eloop_sock_table_requeue(struct eloop_sock_table *table) 650b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt{ 651b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int i, r; 652b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 653b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt r = 0; 654b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt for (i = 0; i < table->count && table->table; i++) { 655b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop_sock_queue(table->table[i].sock, table->type) == -1) 656b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt r = -1; 657b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 658b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return r; 659b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt} 660b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 661b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 662b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 663b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 664b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidtint eloop_sock_requeue(void) 665b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt{ 666b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int r = 0; 667b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 668b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 669b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt close(eloop.kqueuefd); 670b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.kqueuefd = kqueue(); 671b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop.kqueuefd < 0) { 672b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt wpa_printf(MSG_ERROR, "%s: kqueue failed: %s", 673b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt __func__, strerror(errno)); 674b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return -1; 675b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 676b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 677b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop_sock_table_requeue(&eloop.readers) < 0) 678b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt r = -1; 679b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop_sock_table_requeue(&eloop.writers) < 0) 680b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt r = -1; 681b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop_sock_table_requeue(&eloop.exceptions) < 0) 682b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt r = -1; 683b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 684b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 685b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return r; 686b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt} 687b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 688b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_sock_table_destroy(struct eloop_sock_table *table) 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (table) { 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < table->count && table->table; i++) { 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "ELOOP: remaining socket: " 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "sock=%d eloop_data=%p user_data=%p " 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handler=%p", 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].sock, 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].eloop_data, 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].user_data, 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].handler); 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_dump_funcname("eloop unregistered socket " 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "handler", 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table->table[i].handler); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_dump("eloop sock", &table->table[i]); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(table->table); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_read_sock(int sock, eloop_sock_handler handler, 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data, void *user_data) 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eloop_register_sock(sock, EVENT_TYPE_READ, handler, 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_data, user_data); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_unregister_read_sock(int sock) 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_sock(sock, EVENT_TYPE_READ); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (type) { 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EVENT_TYPE_READ: 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &eloop.readers; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EVENT_TYPE_WRITE: 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &eloop.writers; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EVENT_TYPE_EXCEPTION: 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &eloop.exceptions; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_sock(int sock, eloop_event_type type, 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_handler handler, 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data, void *user_data) 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_sock_table *table; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 746df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt assert(sock >= 0); 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table = eloop_get_sock_table(type); 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eloop_sock_table_add_sock(table, sock, handler, 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_data, user_data); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_unregister_sock(int sock, eloop_event_type type) 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_sock_table *table; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt table = eloop_get_sock_table(type); 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_remove_sock(table, sock); 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_timeout(unsigned int secs, unsigned int usecs, 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_timeout_handler handler, 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data, void *user_data) 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_timeout *timeout, *tmp; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t now_sec; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout = os_zalloc(sizeof(*timeout)); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (timeout == NULL) 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 772fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (os_get_reltime(&timeout->time) < 0) { 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(timeout); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt now_sec = timeout->time.sec; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->time.sec += secs; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (timeout->time.sec < now_sec) { 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Integer overflow - assume long enough timeout to be assumed 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be infinite, i.e., the timeout would never happen. 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ever happen - ignore it", secs); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(timeout); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->time.usec += usecs; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (timeout->time.usec >= 1000000) { 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->time.sec++; 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->time.usec -= 1000000; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->eloop_data = eloop_data; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->user_data = user_data; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->handler = handler; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_add_ref(timeout, eloop, eloop_data); 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_add_ref(timeout, user, user_data); 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_record(timeout); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Maintain timeouts in order of increasing time */ 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 802fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (os_reltime_before(&timeout->time, &tmp->time)) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(tmp->list.prev, &timeout->list); 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add_tail(&eloop.timeout, &timeout->list); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_remove_timeout(struct eloop_timeout *timeout) 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&timeout->list); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data); 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_remove_ref(timeout, user, timeout->user_data); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(timeout); 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_cancel_timeout(eloop_timeout_handler handler, 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data, void *user_data) 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_timeout *timeout, *prev; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int removed = 0; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(timeout, prev, &eloop.timeout, 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_timeout, list) { 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (timeout->handler == handler && 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (timeout->eloop_data == eloop_data || 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_data == ELOOP_ALL_CTX) && 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (timeout->user_data == user_data || 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt user_data == ELOOP_ALL_CTX)) { 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_remove_timeout(timeout); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt removed++; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return removed; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8444b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtint eloop_cancel_timeout_one(eloop_timeout_handler handler, 8454b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt void *eloop_data, void *user_data, 846fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime *remaining) 8474b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 8484b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct eloop_timeout *timeout, *prev; 8494b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt int removed = 0; 850fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime now; 8514b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 852fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_get_reltime(&now); 8534b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt remaining->sec = remaining->usec = 0; 8544b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 8554b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt dl_list_for_each_safe(timeout, prev, &eloop.timeout, 8564b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct eloop_timeout, list) { 8574b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (timeout->handler == handler && 8584b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt (timeout->eloop_data == eloop_data) && 8594b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt (timeout->user_data == user_data)) { 8604b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt removed = 1; 861fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (os_reltime_before(&now, &timeout->time)) 862fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_reltime_sub(&timeout->time, &now, remaining); 8634b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt eloop_remove_timeout(timeout); 8644b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt break; 8654b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt } 8664b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt } 8674b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return removed; 8684b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 8694b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 8704b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_is_timeout_registered(eloop_timeout_handler handler, 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data, void *user_data) 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_timeout *tmp; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp->handler == handler && 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp->eloop_data == eloop_data && 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp->user_data == user_data) 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 887e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtint eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, 888e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt eloop_timeout_handler handler, void *eloop_data, 889e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt void *user_data) 890e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{ 891fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime now, requested, remaining; 892e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt struct eloop_timeout *tmp; 893e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 894e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 895e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (tmp->handler == handler && 896e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt tmp->eloop_data == eloop_data && 897e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt tmp->user_data == user_data) { 898e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt requested.sec = req_secs; 899e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt requested.usec = req_usecs; 900fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_get_reltime(&now); 901fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_reltime_sub(&tmp->time, &now, &remaining); 902fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (os_reltime_before(&requested, &remaining)) { 903e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt eloop_cancel_timeout(handler, eloop_data, 904e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt user_data); 905e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt eloop_register_timeout(requested.sec, 906e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt requested.usec, 907e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt handler, eloop_data, 908e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt user_data); 909e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return 1; 910e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 911fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 912e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 913e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 914e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 915fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 916e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt} 917e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 918e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 9195460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtint eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, 9205460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt eloop_timeout_handler handler, void *eloop_data, 9215460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt void *user_data) 9225460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{ 923fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime now, requested, remaining; 9245460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt struct eloop_timeout *tmp; 9255460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9265460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 9275460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt if (tmp->handler == handler && 9285460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt tmp->eloop_data == eloop_data && 9295460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt tmp->user_data == user_data) { 9305460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt requested.sec = req_secs; 9315460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt requested.usec = req_usecs; 932fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_get_reltime(&now); 933fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_reltime_sub(&tmp->time, &now, &remaining); 934fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (os_reltime_before(&remaining, &requested)) { 9355460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt eloop_cancel_timeout(handler, eloop_data, 9365460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt user_data); 9375460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt eloop_register_timeout(requested.sec, 9385460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt requested.usec, 9395460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt handler, eloop_data, 9405460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt user_data); 9415460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt return 1; 9425460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 943fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 9445460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 9455460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt } 9465460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 947fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 9485460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt} 9495460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9505460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_handle_alarm(int sig) 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "two seconds. Looks like there\n" 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "is a bug that ends up in a busy loop that " 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "prevents clean shutdown.\n" 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Killing program forcefully.\n"); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt exit(1); 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_handle_signal(int sig) 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use SIGALRM to break out from potential busy loops that 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * would not allow the program to be killed. */ 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.pending_terminate = 1; 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt signal(SIGALRM, eloop_handle_alarm); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alarm(2); 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signaled++; 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < eloop.signal_count; i++) { 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop.signals[i].sig == sig) { 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signals[i].signaled++; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eloop_process_pending_signals(void) 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop.signaled == 0) 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signaled = 0; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop.pending_terminate) { 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NATIVE_WINDOWS 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alarm(0); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.pending_terminate = 0; 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < eloop.signal_count; i++) { 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop.signals[i].signaled) { 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signals[i].signaled = 0; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signals[i].handler(eloop.signals[i].sig, 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signals[i].user_data); 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_signal(int sig, eloop_signal_handler handler, 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_data) 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_signal *tmp; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 101861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 101961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(struct eloop_signal)); 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[eloop.signal_count].sig = sig; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[eloop.signal_count].user_data = user_data; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[eloop.signal_count].handler = handler; 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[eloop.signal_count].signaled = 0; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signal_count++; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.signals = tmp; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt signal(sig, eloop_handle_signal); 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_signal_terminate(eloop_signal_handler handler, 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_data) 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = eloop_register_signal(SIGINT, handler, user_data); 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eloop_register_signal(SIGTERM, handler, user_data); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_register_signal_reconfig(eloop_signal_handler handler, 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_data) 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_NATIVE_WINDOWS 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_NATIVE_WINDOWS */ 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eloop_register_signal(SIGHUP, handler, user_data); 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NATIVE_WINDOWS */ 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_run(void) 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1058c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 1059c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int num_poll_fds; 1060c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int timeout_ms = 0; 106150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 106250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fd_set *rfds, *wfds, *efds; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct timeval _tv; 106550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 106650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 106750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt int timeout_ms = -1; 106850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 1069b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 1070b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct timespec ts; 1071b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 1072c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt int res; 1073fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime tv, now; 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 107550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rfds = os_malloc(sizeof(*rfds)); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wfds = os_malloc(sizeof(*wfds)); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt efds = os_malloc(sizeof(*efds)); 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rfds == NULL || wfds == NULL || efds == NULL) 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 108150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (!eloop.terminate && 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.writers.count > 0 || eloop.exceptions.count > 0)) { 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_timeout *timeout; 1087d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1088d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (eloop.pending_terminate) { 1089d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* 1090d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * This may happen in some corner cases where a signal 1091d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * is received during a blocking operation. We need to 1092d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * process the pending signals and exit if requested to 1093d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * avoid hitting the SIGALRM limit if the blocking 1094d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * operation took more than two seconds. 1095d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 1096d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop_process_pending_signals(); 1097d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (eloop.terminate) 1098d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt break; 1099d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1100d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt list); 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (timeout) { 1104fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_get_reltime(&now); 1105fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (os_reltime_before(&now, &timeout->time)) 1106fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_reltime_sub(&timeout->time, &now, &tv); 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tv.sec = tv.usec = 0; 110950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) 1110c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt timeout_ms = tv.sec * 1000 + tv.usec / 1000; 111150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */ 111250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _tv.tv_sec = tv.sec; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _tv.tv_usec = tv.usec; 111550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 1116b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 1117b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt ts.tv_sec = tv.sec; 1118b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt ts.tv_nsec = tv.usec * 1000L; 1119b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1122c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 1123c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt num_poll_fds = eloop_sock_table_set_fds( 1124c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt &eloop.readers, &eloop.writers, &eloop.exceptions, 1125c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.pollfds, eloop.pollfds_map, 1126c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.max_pollfd_map); 1127c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt res = poll(eloop.pollfds, num_poll_fds, 1128c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt timeout ? timeout_ms : -1); 112950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 113050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_set_fds(&eloop.readers, rfds); 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_set_fds(&eloop.writers, wfds); 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_set_fds(&eloop.exceptions, efds); 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = select(eloop.max_sock + 1, rfds, wfds, efds, 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout ? &_tv : NULL); 113650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 113750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 113850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (eloop.count == 0) { 113950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt res = 0; 114050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } else { 114150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt res = epoll_wait(eloop.epollfd, eloop.epoll_events, 114250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop.count, timeout_ms); 114350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 114450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 1145b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 1146b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (eloop.count == 0) { 1147b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt res = 0; 1148b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } else { 1149b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt res = kevent(eloop.kqueuefd, NULL, 0, 1150b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop.kqueue_events, eloop.kqueue_nevents, 1151b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt timeout ? &ts : NULL); 1152b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt } 1153b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0 && errno != EINTR && errno != 0) { 115550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt wpa_printf(MSG_ERROR, "eloop: %s: %s", 115650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 115750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt "poll" 115850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 115950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 116050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt "select" 116150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 116250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 116350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt "epoll" 116450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 1165b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 1166b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt "kqueue" 1167b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EKQUEUE */ 1168b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 116950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt , strerror(errno)); 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1172d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1173d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop.readers.changed = 0; 1174d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop.writers.changed = 0; 1175d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop.exceptions.changed = 0; 1176d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_process_pending_signals(); 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1179b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* check if some registered timeouts have occurred */ 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt list); 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (timeout) { 1184fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_get_reltime(&now); 1185fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt if (!os_reltime_before(&now, &timeout->time)) { 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *eloop_data = timeout->eloop_data; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *user_data = timeout->user_data; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_timeout_handler handler = 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->handler; 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_remove_timeout(timeout); 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handler(eloop_data, user_data); 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res <= 0) 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1199d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (eloop.readers.changed || 1200d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop.writers.changed || 1201d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt eloop.exceptions.changed) { 1202d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt /* 1203d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * Sockets may have been closed and reopened with the 1204d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * same FD in the signal or timeout handlers, so we 1205d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * must skip the previous results and check again 1206d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * whether any of the currently registered sockets have 1207d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt * events. 1208d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt */ 1209d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt continue; 1210d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt } 1211d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt 1212c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 1213c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop_sock_table_dispatch(&eloop.readers, &eloop.writers, 1214c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt &eloop.exceptions, eloop.pollfds_map, 1215c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eloop.max_pollfd_map); 121650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 121750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_dispatch(&eloop.readers, rfds); 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_dispatch(&eloop.writers, wfds); 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_dispatch(&eloop.exceptions, efds); 122150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 122250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 122350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt eloop_sock_table_dispatch(eloop.epoll_events, res); 122450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 1225b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 1226b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt eloop_sock_table_dispatch(eloop.kqueue_events, res); 1227b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1230ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt eloop.terminate = 0; 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout: 123250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rfds); 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wfds); 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(efds); 123650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 1237c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_terminate(void) 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop.terminate = 1; 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_destroy(void) 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_timeout *timeout, *prev; 1250fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt struct os_reltime now; 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1252fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt os_get_reltime(&now); 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each_safe(timeout, prev, &eloop.timeout, 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eloop_timeout, list) { 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sec, usec; 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = timeout->time.sec - now.sec; 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt usec = timeout->time.usec - now.usec; 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (timeout->time.usec < now.usec) { 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec--; 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt usec += 1000000; 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "eloop_data=%p user_data=%p handler=%p", 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec, usec, timeout->eloop_data, timeout->user_data, 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->handler); 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_dump_funcname("eloop unregistered timeout handler", 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout->handler); 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_trace_dump("eloop timeout", timeout); 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_remove_timeout(timeout); 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_destroy(&eloop.readers); 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_destroy(&eloop.writers); 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_sock_table_destroy(&eloop.exceptions); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(eloop.signals); 1275c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1276c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 1277c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_free(eloop.pollfds); 1278c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_free(eloop.pollfds_map); 1279c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 1280b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) 1281b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt os_free(eloop.fd_table); 1282b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ 128350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_EPOLL 128450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt os_free(eloop.epoll_events); 128550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt close(eloop.epollfd); 128650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_EPOLL */ 1287b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 1288b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt os_free(eloop.kqueue_events); 1289b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt close(eloop.kqueuefd); 1290b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eloop_terminated(void) 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1296d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return eloop.terminate || eloop.pending_terminate; 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eloop_wait_for_read_sock(int sock) 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1302c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_ELOOP_POLL 1303c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct pollfd pfd; 1304c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1305c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (sock < 0) 1306c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return; 1307c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1308c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(&pfd, 0, sizeof(pfd)); 1309c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd.fd = sock; 1310c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pfd.events = POLLIN; 1311c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 1312c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt poll(&pfd, 1, -1); 131350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_POLL */ 131450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) 131550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt /* 131650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt * We can use epoll() here. But epoll() requres 4 system calls. 131750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for 131850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt * epoll fd. So select() is better for performance here. 131950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt */ 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fd_set rfds; 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sock < 0) 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FD_ZERO(&rfds); 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FD_SET(sock, &rfds); 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt select(sock + 1, &rfds, NULL, NULL, NULL); 132850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */ 1329b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#ifdef CONFIG_ELOOP_KQUEUE 1330b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt int kfd; 1331b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt struct kevent ke1, ke2; 1332b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt 1333b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt kfd = kqueue(); 1334b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt if (kfd == -1) 1335b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt return; 133657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt EV_SET(&ke1, sock, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0); 1337b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt kevent(kfd, &ke1, 1, &ke2, 1, NULL); 1338b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt close(kfd); 1339b97e428f8acf1ecb93f38f8d0063d2f2fd0bc36eDmitry Shmidt#endif /* CONFIG_ELOOP_KQUEUE */ 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 134150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 134250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#ifdef CONFIG_ELOOP_SELECT 134350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#undef CONFIG_ELOOP_SELECT 134450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#endif /* CONFIG_ELOOP_SELECT */ 1345