LCOV - code coverage report
Current view: top level - src/utils - eloop.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 301 338 89.1 %
Date: 2016-10-02 Functions: 31 33 93.9 %

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

Generated by: LCOV version 1.10