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 1443382998 Lines: 298 335 89.0 %
Date: 2015-09-27 Functions: 30 32 93.8 %

          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_EPOLL)
      22             : #define CONFIG_ELOOP_SELECT
      23             : #endif
      24             : 
      25             : #ifdef CONFIG_ELOOP_POLL
      26             : #include <poll.h>
      27             : #endif /* CONFIG_ELOOP_POLL */
      28             : 
      29             : #ifdef CONFIG_ELOOP_EPOLL
      30             : #include <sys/epoll.h>
      31             : #endif /* CONFIG_ELOOP_EPOLL */
      32             : 
      33             : struct eloop_sock {
      34             :         int sock;
      35             :         void *eloop_data;
      36             :         void *user_data;
      37             :         eloop_sock_handler handler;
      38             :         WPA_TRACE_REF(eloop);
      39             :         WPA_TRACE_REF(user);
      40             :         WPA_TRACE_INFO
      41             : };
      42             : 
      43             : struct eloop_timeout {
      44             :         struct dl_list list;
      45             :         struct os_reltime time;
      46             :         void *eloop_data;
      47             :         void *user_data;
      48             :         eloop_timeout_handler handler;
      49             :         WPA_TRACE_REF(eloop);
      50             :         WPA_TRACE_REF(user);
      51             :         WPA_TRACE_INFO
      52             : };
      53             : 
      54             : struct eloop_signal {
      55             :         int sig;
      56             :         void *user_data;
      57             :         eloop_signal_handler handler;
      58             :         int signaled;
      59             : };
      60             : 
      61             : struct eloop_sock_table {
      62             :         int count;
      63             :         struct eloop_sock *table;
      64             :         eloop_event_type type;
      65             :         int changed;
      66             : };
      67             : 
      68             : struct eloop_data {
      69             :         int max_sock;
      70             : 
      71             :         int count; /* sum of all table counts */
      72             : #ifdef CONFIG_ELOOP_POLL
      73             :         int max_pollfd_map; /* number of pollfds_map currently allocated */
      74             :         int max_poll_fds; /* number of pollfds currently allocated */
      75             :         struct pollfd *pollfds;
      76             :         struct pollfd **pollfds_map;
      77             : #endif /* CONFIG_ELOOP_POLL */
      78             : #ifdef CONFIG_ELOOP_EPOLL
      79             :         int epollfd;
      80             :         int epoll_max_event_num;
      81             :         int epoll_max_fd;
      82             :         struct eloop_sock *epoll_table;
      83             :         struct epoll_event *epoll_events;
      84             : #endif /* CONFIG_ELOOP_EPOLL */
      85             :         struct eloop_sock_table readers;
      86             :         struct eloop_sock_table writers;
      87             :         struct eloop_sock_table exceptions;
      88             : 
      89             :         struct dl_list timeout;
      90             : 
      91             :         int signal_count;
      92             :         struct eloop_signal *signals;
      93             :         int signaled;
      94             :         int pending_terminate;
      95             : 
      96             :         int terminate;
      97             : };
      98             : 
      99             : static struct eloop_data eloop;
     100             : 
     101             : 
     102             : #ifdef WPA_TRACE
     103             : 
     104           0 : static void eloop_sigsegv_handler(int sig)
     105             : {
     106           0 :         wpa_trace_show("eloop SIGSEGV");
     107           0 :         abort();
     108             : }
     109             : 
     110       47497 : static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
     111             : {
     112             :         int i;
     113       47497 :         if (table == NULL || table->table == NULL)
     114       47497 :                 return;
     115      649649 :         for (i = 0; i < table->count; i++) {
     116      602152 :                 wpa_trace_add_ref(&table->table[i], eloop,
     117             :                                   table->table[i].eloop_data);
     118      602152 :                 wpa_trace_add_ref(&table->table[i], user,
     119             :                                   table->table[i].user_data);
     120             :         }
     121             : }
     122             : 
     123             : 
     124       47497 : static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
     125             : {
     126             :         int i;
     127       47497 :         if (table == NULL || table->table == NULL)
     128       47569 :                 return;
     129      649577 :         for (i = 0; i < table->count; i++) {
     130      602152 :                 wpa_trace_remove_ref(&table->table[i], eloop,
     131             :                                      table->table[i].eloop_data);
     132      602152 :                 wpa_trace_remove_ref(&table->table[i], user,
     133             :                                      table->table[i].user_data);
     134             :         }
     135             : }
     136             : 
     137             : #else /* WPA_TRACE */
     138             : 
     139             : #define eloop_trace_sock_add_ref(table) do { } while (0)
     140             : #define eloop_trace_sock_remove_ref(table) do { } while (0)
     141             : 
     142             : #endif /* WPA_TRACE */
     143             : 
     144             : 
     145         105 : int eloop_init(void)
     146             : {
     147         105 :         os_memset(&eloop, 0, sizeof(eloop));
     148         105 :         dl_list_init(&eloop.timeout);
     149             : #ifdef CONFIG_ELOOP_EPOLL
     150             :         eloop.epollfd = epoll_create1(0);
     151             :         if (eloop.epollfd < 0) {
     152             :                 wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
     153             :                            __func__, strerror(errno));
     154             :                 return -1;
     155             :         }
     156             :         eloop.readers.type = EVENT_TYPE_READ;
     157             :         eloop.writers.type = EVENT_TYPE_WRITE;
     158             :         eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
     159             : #endif /* CONFIG_ELOOP_EPOLL */
     160             : #ifdef WPA_TRACE
     161         105 :         signal(SIGSEGV, eloop_sigsegv_handler);
     162             : #endif /* WPA_TRACE */
     163         105 :         return 0;
     164             : }
     165             : 
     166             : 
     167       23753 : static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
     168             :                                      int sock, eloop_sock_handler handler,
     169             :                                      void *eloop_data, void *user_data)
     170             : {
     171             : #ifdef CONFIG_ELOOP_EPOLL
     172             :         struct eloop_sock *temp_table;
     173             :         struct epoll_event ev, *temp_events;
     174             :         int next;
     175             : #endif /* CONFIG_ELOOP_EPOLL */
     176             :         struct eloop_sock *tmp;
     177             :         int new_max_sock;
     178             : 
     179       23753 :         if (sock > eloop.max_sock)
     180        1207 :                 new_max_sock = sock;
     181             :         else
     182       22546 :                 new_max_sock = eloop.max_sock;
     183             : 
     184       23753 :         if (table == NULL)
     185           0 :                 return -1;
     186             : 
     187             : #ifdef CONFIG_ELOOP_POLL
     188             :         if (new_max_sock >= eloop.max_pollfd_map) {
     189             :                 struct pollfd **nmap;
     190             :                 nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50,
     191             :                                         sizeof(struct pollfd *));
     192             :                 if (nmap == NULL)
     193             :                         return -1;
     194             : 
     195             :                 eloop.max_pollfd_map = new_max_sock + 50;
     196             :                 eloop.pollfds_map = nmap;
     197             :         }
     198             : 
     199             :         if (eloop.count + 1 > eloop.max_poll_fds) {
     200             :                 struct pollfd *n;
     201             :                 int nmax = eloop.count + 1 + 50;
     202             :                 n = os_realloc_array(eloop.pollfds, nmax,
     203             :                                      sizeof(struct pollfd));
     204             :                 if (n == NULL)
     205             :                         return -1;
     206             : 
     207             :                 eloop.max_poll_fds = nmax;
     208             :                 eloop.pollfds = n;
     209             :         }
     210             : #endif /* CONFIG_ELOOP_POLL */
     211             : #ifdef CONFIG_ELOOP_EPOLL
     212             :         if (new_max_sock >= eloop.epoll_max_fd) {
     213             :                 next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
     214             :                 temp_table = os_realloc_array(eloop.epoll_table, next,
     215             :                                               sizeof(struct eloop_sock));
     216             :                 if (temp_table == NULL)
     217             :                         return -1;
     218             : 
     219             :                 eloop.epoll_max_fd = next;
     220             :                 eloop.epoll_table = temp_table;
     221             :         }
     222             : 
     223             :         if (eloop.count + 1 > eloop.epoll_max_event_num) {
     224             :                 next = eloop.epoll_max_event_num == 0 ? 8 :
     225             :                         eloop.epoll_max_event_num * 2;
     226             :                 temp_events = os_realloc_array(eloop.epoll_events, next,
     227             :                                                sizeof(struct epoll_event));
     228             :                 if (temp_events == NULL) {
     229             :                         wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
     230             :                                    "%s\n", __func__, strerror(errno));
     231             :                         return -1;
     232             :                 }
     233             : 
     234             :                 eloop.epoll_max_event_num = next;
     235             :                 eloop.epoll_events = temp_events;
     236             :         }
     237             : #endif /* CONFIG_ELOOP_EPOLL */
     238             : 
     239       23753 :         eloop_trace_sock_remove_ref(table);
     240       23753 :         tmp = os_realloc_array(table->table, table->count + 1,
     241             :                                sizeof(struct eloop_sock));
     242       23753 :         if (tmp == NULL) {
     243           9 :                 eloop_trace_sock_add_ref(table);
     244           9 :                 return -1;
     245             :         }
     246             : 
     247       23744 :         tmp[table->count].sock = sock;
     248       23744 :         tmp[table->count].eloop_data = eloop_data;
     249       23744 :         tmp[table->count].user_data = user_data;
     250       23744 :         tmp[table->count].handler = handler;
     251       23744 :         wpa_trace_record(&tmp[table->count]);
     252       23744 :         table->count++;
     253       23744 :         table->table = tmp;
     254       23744 :         eloop.max_sock = new_max_sock;
     255       23744 :         eloop.count++;
     256       23744 :         table->changed = 1;
     257       23744 :         eloop_trace_sock_add_ref(table);
     258             : 
     259             : #ifdef CONFIG_ELOOP_EPOLL
     260             :         os_memset(&ev, 0, sizeof(ev));
     261             :         switch (table->type) {
     262             :         case EVENT_TYPE_READ:
     263             :                 ev.events = EPOLLIN;
     264             :                 break;
     265             :         case EVENT_TYPE_WRITE:
     266             :                 ev.events = EPOLLOUT;
     267             :                 break;
     268             :         /*
     269             :          * Exceptions are always checked when using epoll, but I suppose it's
     270             :          * possible that someone registered a socket *only* for exception
     271             :          * handling.
     272             :          */
     273             :         case EVENT_TYPE_EXCEPTION:
     274             :                 ev.events = EPOLLERR | EPOLLHUP;
     275             :                 break;
     276             :         }
     277             :         ev.data.fd = sock;
     278             :         if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
     279             :                 wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
     280             :                            "failed. %s\n", __func__, sock, strerror(errno));
     281             :                 return -1;
     282             :         }
     283             :         os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
     284             :                   sizeof(struct eloop_sock));
     285             : #endif /* CONFIG_ELOOP_EPOLL */
     286       23744 :         return 0;
     287             : }
     288             : 
     289             : 
     290       26196 : static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
     291             :                                          int sock)
     292             : {
     293             :         int i;
     294             : 
     295       26196 :         if (table == NULL || table->table == NULL || table->count == 0)
     296        1054 :                 return;
     297             : 
     298      286997 :         for (i = 0; i < table->count; i++) {
     299      285599 :                 if (table->table[i].sock == sock)
     300       23744 :                         break;
     301             :         }
     302       25142 :         if (i == table->count)
     303        1398 :                 return;
     304       23744 :         eloop_trace_sock_remove_ref(table);
     305       23744 :         if (i != table->count - 1) {
     306       10143 :                 os_memmove(&table->table[i], &table->table[i + 1],
     307             :                            (table->count - i - 1) *
     308             :                            sizeof(struct eloop_sock));
     309             :         }
     310       23744 :         table->count--;
     311       23744 :         eloop.count--;
     312       23744 :         table->changed = 1;
     313       23744 :         eloop_trace_sock_add_ref(table);
     314             : #ifdef CONFIG_ELOOP_EPOLL
     315             :         if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
     316             :                 wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
     317             :                            "failed. %s\n", __func__, sock, strerror(errno));
     318             :                 return;
     319             :         }
     320             :         os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
     321             : #endif /* CONFIG_ELOOP_EPOLL */
     322             : }
     323             : 
     324             : 
     325             : #ifdef CONFIG_ELOOP_POLL
     326             : 
     327             : static struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx)
     328             : {
     329             :         if (fd < mx && fd >= 0)
     330             :                 return pollfds_map[fd];
     331             :         return NULL;
     332             : }
     333             : 
     334             : 
     335             : static int eloop_sock_table_set_fds(struct eloop_sock_table *readers,
     336             :                                     struct eloop_sock_table *writers,
     337             :                                     struct eloop_sock_table *exceptions,
     338             :                                     struct pollfd *pollfds,
     339             :                                     struct pollfd **pollfds_map,
     340             :                                     int max_pollfd_map)
     341             : {
     342             :         int i;
     343             :         int nxt = 0;
     344             :         int fd;
     345             :         struct pollfd *pfd;
     346             : 
     347             :         /* Clear pollfd lookup map. It will be re-populated below. */
     348             :         os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map);
     349             : 
     350             :         if (readers && readers->table) {
     351             :                 for (i = 0; i < readers->count; i++) {
     352             :                         fd = readers->table[i].sock;
     353             :                         assert(fd >= 0 && fd < max_pollfd_map);
     354             :                         pollfds[nxt].fd = fd;
     355             :                         pollfds[nxt].events = POLLIN;
     356             :                         pollfds[nxt].revents = 0;
     357             :                         pollfds_map[fd] = &(pollfds[nxt]);
     358             :                         nxt++;
     359             :                 }
     360             :         }
     361             : 
     362             :         if (writers && writers->table) {
     363             :                 for (i = 0; i < writers->count; i++) {
     364             :                         /*
     365             :                          * See if we already added this descriptor, update it
     366             :                          * if so.
     367             :                          */
     368             :                         fd = writers->table[i].sock;
     369             :                         assert(fd >= 0 && fd < max_pollfd_map);
     370             :                         pfd = pollfds_map[fd];
     371             :                         if (!pfd) {
     372             :                                 pfd = &(pollfds[nxt]);
     373             :                                 pfd->events = 0;
     374             :                                 pfd->fd = fd;
     375             :                                 pollfds[i].revents = 0;
     376             :                                 pollfds_map[fd] = pfd;
     377             :                                 nxt++;
     378             :                         }
     379             :                         pfd->events |= POLLOUT;
     380             :                 }
     381             :         }
     382             : 
     383             :         /*
     384             :          * Exceptions are always checked when using poll, but I suppose it's
     385             :          * possible that someone registered a socket *only* for exception
     386             :          * handling. Set the POLLIN bit in this case.
     387             :          */
     388             :         if (exceptions && exceptions->table) {
     389             :                 for (i = 0; i < exceptions->count; i++) {
     390             :                         /*
     391             :                          * See if we already added this descriptor, just use it
     392             :                          * if so.
     393             :                          */
     394             :                         fd = exceptions->table[i].sock;
     395             :                         assert(fd >= 0 && fd < max_pollfd_map);
     396             :                         pfd = pollfds_map[fd];
     397             :                         if (!pfd) {
     398             :                                 pfd = &(pollfds[nxt]);
     399             :                                 pfd->events = POLLIN;
     400             :                                 pfd->fd = fd;
     401             :                                 pollfds[i].revents = 0;
     402             :                                 pollfds_map[fd] = pfd;
     403             :                                 nxt++;
     404             :                         }
     405             :                 }
     406             :         }
     407             : 
     408             :         return nxt;
     409             : }
     410             : 
     411             : 
     412             : static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table,
     413             :                                            struct pollfd **pollfds_map,
     414             :                                            int max_pollfd_map,
     415             :                                            short int revents)
     416             : {
     417             :         int i;
     418             :         struct pollfd *pfd;
     419             : 
     420             :         if (!table || !table->table)
     421             :                 return 0;
     422             : 
     423             :         table->changed = 0;
     424             :         for (i = 0; i < table->count; i++) {
     425             :                 pfd = find_pollfd(pollfds_map, table->table[i].sock,
     426             :                                   max_pollfd_map);
     427             :                 if (!pfd)
     428             :                         continue;
     429             : 
     430             :                 if (!(pfd->revents & revents))
     431             :                         continue;
     432             : 
     433             :                 table->table[i].handler(table->table[i].sock,
     434             :                                         table->table[i].eloop_data,
     435             :                                         table->table[i].user_data);
     436             :                 if (table->changed)
     437             :                         return 1;
     438             :         }
     439             : 
     440             :         return 0;
     441             : }
     442             : 
     443             : 
     444             : static void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
     445             :                                       struct eloop_sock_table *writers,
     446             :                                       struct eloop_sock_table *exceptions,
     447             :                                       struct pollfd **pollfds_map,
     448             :                                       int max_pollfd_map)
     449             : {
     450             :         if (eloop_sock_table_dispatch_table(readers, pollfds_map,
     451             :                                             max_pollfd_map, POLLIN | POLLERR |
     452             :                                             POLLHUP))
     453             :                 return; /* pollfds may be invalid at this point */
     454             : 
     455             :         if (eloop_sock_table_dispatch_table(writers, pollfds_map,
     456             :                                             max_pollfd_map, POLLOUT))
     457             :                 return; /* pollfds may be invalid at this point */
     458             : 
     459             :         eloop_sock_table_dispatch_table(exceptions, pollfds_map,
     460             :                                         max_pollfd_map, POLLERR | POLLHUP);
     461             : }
     462             : 
     463             : #endif /* CONFIG_ELOOP_POLL */
     464             : 
     465             : #ifdef CONFIG_ELOOP_SELECT
     466             : 
     467     2066595 : static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
     468             :                                      fd_set *fds)
     469             : {
     470             :         int i;
     471             : 
     472     2066595 :         FD_ZERO(fds);
     473             : 
     474     2066595 :         if (table->table == NULL)
     475     3005383 :                 return;
     476             : 
     477     7798478 :         for (i = 0; i < table->count; i++) {
     478     6670671 :                 assert(table->table[i].sock >= 0);
     479     6670671 :                 FD_SET(table->table[i].sock, fds);
     480             :         }
     481             : }
     482             : 
     483             : 
     484     1885566 : static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
     485             :                                       fd_set *fds)
     486             : {
     487             :         int i;
     488             : 
     489     1885566 :         if (table == NULL || table->table == NULL)
     490     2760894 :                 return;
     491             : 
     492     1010238 :         table->changed = 0;
     493     6864374 :         for (i = 0; i < table->count; i++) {
     494     5868427 :                 if (FD_ISSET(table->table[i].sock, fds)) {
     495     2251935 :                         table->table[i].handler(table->table[i].sock,
     496      750645 :                                                 table->table[i].eloop_data,
     497      750645 :                                                 table->table[i].user_data);
     498      750645 :                         if (table->changed)
     499       14291 :                                 break;
     500             :                 }
     501             :         }
     502             : }
     503             : 
     504             : #endif /* CONFIG_ELOOP_SELECT */
     505             : 
     506             : 
     507             : #ifdef CONFIG_ELOOP_EPOLL
     508             : static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
     509             : {
     510             :         struct eloop_sock *table;
     511             :         int i;
     512             : 
     513             :         for (i = 0; i < nfds; i++) {
     514             :                 table = &eloop.epoll_table[events[i].data.fd];
     515             :                 if (table->handler == NULL)
     516             :                         continue;
     517             :                 table->handler(table->sock, table->eloop_data,
     518             :                                table->user_data);
     519             :                 if (eloop.readers.changed ||
     520             :                     eloop.writers.changed ||
     521             :                     eloop.exceptions.changed)
     522             :                         break;
     523             :         }
     524             : }
     525             : #endif /* CONFIG_ELOOP_EPOLL */
     526             : 
     527             : 
     528         315 : static void eloop_sock_table_destroy(struct eloop_sock_table *table)
     529             : {
     530         315 :         if (table) {
     531             :                 int i;
     532         315 :                 for (i = 0; i < table->count && table->table; i++) {
     533           0 :                         wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
     534             :                                    "sock=%d eloop_data=%p user_data=%p "
     535             :                                    "handler=%p",
     536           0 :                                    table->table[i].sock,
     537           0 :                                    table->table[i].eloop_data,
     538           0 :                                    table->table[i].user_data,
     539           0 :                                    table->table[i].handler);
     540           0 :                         wpa_trace_dump_funcname("eloop unregistered socket "
     541             :                                                 "handler",
     542           0 :                                                 table->table[i].handler);
     543           0 :                         wpa_trace_dump("eloop sock", &table->table[i]);
     544             :                 }
     545         315 :                 os_free(table->table);
     546             :         }
     547         315 : }
     548             : 
     549             : 
     550       21054 : int eloop_register_read_sock(int sock, eloop_sock_handler handler,
     551             :                              void *eloop_data, void *user_data)
     552             : {
     553       21054 :         return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
     554             :                                    eloop_data, user_data);
     555             : }
     556             : 
     557             : 
     558       21054 : void eloop_unregister_read_sock(int sock)
     559             : {
     560       21054 :         eloop_unregister_sock(sock, EVENT_TYPE_READ);
     561       21054 : }
     562             : 
     563             : 
     564       49949 : static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
     565             : {
     566       49949 :         switch (type) {
     567             :         case EVENT_TYPE_READ:
     568       46791 :                 return &eloop.readers;
     569             :         case EVENT_TYPE_WRITE:
     570        3140 :                 return &eloop.writers;
     571             :         case EVENT_TYPE_EXCEPTION:
     572          18 :                 return &eloop.exceptions;
     573             :         }
     574             : 
     575           0 :         return NULL;
     576             : }
     577             : 
     578             : 
     579       23753 : int eloop_register_sock(int sock, eloop_event_type type,
     580             :                         eloop_sock_handler handler,
     581             :                         void *eloop_data, void *user_data)
     582             : {
     583             :         struct eloop_sock_table *table;
     584             : 
     585       23753 :         assert(sock >= 0);
     586       23753 :         table = eloop_get_sock_table(type);
     587       23753 :         return eloop_sock_table_add_sock(table, sock, handler,
     588             :                                          eloop_data, user_data);
     589             : }
     590             : 
     591             : 
     592       26196 : void eloop_unregister_sock(int sock, eloop_event_type type)
     593             : {
     594             :         struct eloop_sock_table *table;
     595             : 
     596       26196 :         table = eloop_get_sock_table(type);
     597       26196 :         eloop_sock_table_remove_sock(table, sock);
     598       26196 : }
     599             : 
     600             : 
     601      152266 : int eloop_register_timeout(unsigned int secs, unsigned int usecs,
     602             :                            eloop_timeout_handler handler,
     603             :                            void *eloop_data, void *user_data)
     604             : {
     605             :         struct eloop_timeout *timeout, *tmp;
     606             :         os_time_t now_sec;
     607             : 
     608      152266 :         timeout = os_zalloc(sizeof(*timeout));
     609      152266 :         if (timeout == NULL)
     610          36 :                 return -1;
     611      152230 :         if (os_get_reltime(&timeout->time) < 0) {
     612           0 :                 os_free(timeout);
     613           0 :                 return -1;
     614             :         }
     615      152230 :         now_sec = timeout->time.sec;
     616      152230 :         timeout->time.sec += secs;
     617      152230 :         if (timeout->time.sec < now_sec) {
     618             :                 /*
     619             :                  * Integer overflow - assume long enough timeout to be assumed
     620             :                  * to be infinite, i.e., the timeout would never happen.
     621             :                  */
     622           0 :                 wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
     623             :                            "ever happen - ignore it", secs);
     624           0 :                 os_free(timeout);
     625           0 :                 return 0;
     626             :         }
     627      152230 :         timeout->time.usec += usecs;
     628      310669 :         while (timeout->time.usec >= 1000000) {
     629        6209 :                 timeout->time.sec++;
     630        6209 :                 timeout->time.usec -= 1000000;
     631             :         }
     632      152230 :         timeout->eloop_data = eloop_data;
     633      152230 :         timeout->user_data = user_data;
     634      152230 :         timeout->handler = handler;
     635      152230 :         wpa_trace_add_ref(timeout, eloop, eloop_data);
     636      152230 :         wpa_trace_add_ref(timeout, user, user_data);
     637      152230 :         wpa_trace_record(timeout);
     638             : 
     639             :         /* Maintain timeouts in order of increasing time */
     640      518131 :         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
     641      500491 :                 if (os_reltime_before(&timeout->time, &tmp->time)) {
     642      134590 :                         dl_list_add(tmp->list.prev, &timeout->list);
     643      134590 :                         return 0;
     644             :                 }
     645             :         }
     646       17640 :         dl_list_add_tail(&eloop.timeout, &timeout->list);
     647             : 
     648       17640 :         return 0;
     649             : }
     650             : 
     651             : 
     652      152230 : static void eloop_remove_timeout(struct eloop_timeout *timeout)
     653             : {
     654      152230 :         dl_list_del(&timeout->list);
     655      152230 :         wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
     656      152230 :         wpa_trace_remove_ref(timeout, user, timeout->user_data);
     657      152230 :         os_free(timeout);
     658      152230 : }
     659             : 
     660             : 
     661      497794 : int eloop_cancel_timeout(eloop_timeout_handler handler,
     662             :                          void *eloop_data, void *user_data)
     663             : {
     664             :         struct eloop_timeout *timeout, *prev;
     665      497794 :         int removed = 0;
     666             : 
     667     4120295 :         dl_list_for_each_safe(timeout, prev, &eloop.timeout,
     668             :                               struct eloop_timeout, list) {
     669     3862062 :                 if (timeout->handler == handler &&
     670      375063 :                     (timeout->eloop_data == eloop_data ||
     671      110081 :                      eloop_data == ELOOP_ALL_CTX) &&
     672      148525 :                     (timeout->user_data == user_data ||
     673             :                      user_data == ELOOP_ALL_CTX)) {
     674       71639 :                         eloop_remove_timeout(timeout);
     675       71639 :                         removed++;
     676             :                 }
     677             :         }
     678             : 
     679      497794 :         return removed;
     680             : }
     681             : 
     682             : 
     683          23 : int eloop_cancel_timeout_one(eloop_timeout_handler handler,
     684             :                              void *eloop_data, void *user_data,
     685             :                              struct os_reltime *remaining)
     686             : {
     687             :         struct eloop_timeout *timeout, *prev;
     688          23 :         int removed = 0;
     689             :         struct os_reltime now;
     690             : 
     691          23 :         os_get_reltime(&now);
     692          23 :         remaining->sec = remaining->usec = 0;
     693             : 
     694          56 :         dl_list_for_each_safe(timeout, prev, &eloop.timeout,
     695             :                               struct eloop_timeout, list) {
     696          45 :                 if (timeout->handler == handler &&
     697          12 :                     (timeout->eloop_data == eloop_data) &&
     698           6 :                     (timeout->user_data == user_data)) {
     699           6 :                         removed = 1;
     700           6 :                         if (os_reltime_before(&now, &timeout->time))
     701           6 :                                 os_reltime_sub(&timeout->time, &now, remaining);
     702           6 :                         eloop_remove_timeout(timeout);
     703           6 :                         break;
     704             :                 }
     705             :         }
     706          23 :         return removed;
     707             : }
     708             : 
     709             : 
     710       41819 : int eloop_is_timeout_registered(eloop_timeout_handler handler,
     711             :                                 void *eloop_data, void *user_data)
     712             : {
     713             :         struct eloop_timeout *tmp;
     714             : 
     715      158427 :         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
     716      153168 :                 if (tmp->handler == handler &&
     717       40185 :                     tmp->eloop_data == eloop_data &&
     718       20092 :                     tmp->user_data == user_data)
     719       16467 :                         return 1;
     720             :         }
     721             : 
     722       25352 :         return 0;
     723             : }
     724             : 
     725             : 
     726        7327 : int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
     727             :                           eloop_timeout_handler handler, void *eloop_data,
     728             :                           void *user_data)
     729             : {
     730             :         struct os_reltime now, requested, remaining;
     731             :         struct eloop_timeout *tmp;
     732             : 
     733       37483 :         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
     734       31352 :                 if (tmp->handler == handler &&
     735        1196 :                     tmp->eloop_data == eloop_data &&
     736         598 :                     tmp->user_data == user_data) {
     737         598 :                         requested.sec = req_secs;
     738         598 :                         requested.usec = req_usecs;
     739         598 :                         os_get_reltime(&now);
     740         598 :                         os_reltime_sub(&tmp->time, &now, &remaining);
     741         598 :                         if (os_reltime_before(&requested, &remaining)) {
     742         173 :                                 eloop_cancel_timeout(handler, eloop_data,
     743             :                                                      user_data);
     744         173 :                                 eloop_register_timeout(requested.sec,
     745         173 :                                                        requested.usec,
     746             :                                                        handler, eloop_data,
     747             :                                                        user_data);
     748         173 :                                 return 1;
     749             :                         }
     750         425 :                         return 0;
     751             :                 }
     752             :         }
     753             : 
     754        6729 :         return -1;
     755             : }
     756             : 
     757             : 
     758           9 : int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
     759             :                             eloop_timeout_handler handler, void *eloop_data,
     760             :                             void *user_data)
     761             : {
     762             :         struct os_reltime now, requested, remaining;
     763             :         struct eloop_timeout *tmp;
     764             : 
     765          16 :         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
     766          23 :                 if (tmp->handler == handler &&
     767          16 :                     tmp->eloop_data == eloop_data &&
     768           8 :                     tmp->user_data == user_data) {
     769           8 :                         requested.sec = req_secs;
     770           8 :                         requested.usec = req_usecs;
     771           8 :                         os_get_reltime(&now);
     772           8 :                         os_reltime_sub(&tmp->time, &now, &remaining);
     773           8 :                         if (os_reltime_before(&remaining, &requested)) {
     774           8 :                                 eloop_cancel_timeout(handler, eloop_data,
     775             :                                                      user_data);
     776           8 :                                 eloop_register_timeout(requested.sec,
     777           8 :                                                        requested.usec,
     778             :                                                        handler, eloop_data,
     779             :                                                        user_data);
     780           8 :                                 return 1;
     781             :                         }
     782           0 :                         return 0;
     783             :                 }
     784             :         }
     785             : 
     786           1 :         return -1;
     787             : }
     788             : 
     789             : 
     790             : #ifndef CONFIG_NATIVE_WINDOWS
     791           0 : static void eloop_handle_alarm(int sig)
     792             : {
     793           0 :         wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
     794             :                    "two seconds. Looks like there\n"
     795             :                    "is a bug that ends up in a busy loop that "
     796             :                    "prevents clean shutdown.\n"
     797             :                    "Killing program forcefully.\n");
     798           0 :         exit(1);
     799             : }
     800             : #endif /* CONFIG_NATIVE_WINDOWS */
     801             : 
     802             : 
     803        1442 : static void eloop_handle_signal(int sig)
     804             : {
     805             :         int i;
     806             : 
     807             : #ifndef CONFIG_NATIVE_WINDOWS
     808        1442 :         if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
     809             :                 /* Use SIGALRM to break out from potential busy loops that
     810             :                  * would not allow the program to be killed. */
     811          43 :                 eloop.pending_terminate = 1;
     812          43 :                 signal(SIGALRM, eloop_handle_alarm);
     813          43 :                 alarm(2);
     814             :         }
     815             : #endif /* CONFIG_NATIVE_WINDOWS */
     816             : 
     817        1442 :         eloop.signaled++;
     818        1523 :         for (i = 0; i < eloop.signal_count; i++) {
     819        1523 :                 if (eloop.signals[i].sig == sig) {
     820        1442 :                         eloop.signals[i].signaled++;
     821        1442 :                         break;
     822             :                 }
     823             :         }
     824        1442 : }
     825             : 
     826             : 
     827      688868 : static void eloop_process_pending_signals(void)
     828             : {
     829             :         int i;
     830             : 
     831      688868 :         if (eloop.signaled == 0)
     832     1376305 :                 return;
     833        1431 :         eloop.signaled = 0;
     834             : 
     835        1431 :         if (eloop.pending_terminate) {
     836             : #ifndef CONFIG_NATIVE_WINDOWS
     837          43 :                 alarm(0);
     838             : #endif /* CONFIG_NATIVE_WINDOWS */
     839          43 :                 eloop.pending_terminate = 0;
     840             :         }
     841             : 
     842        7133 :         for (i = 0; i < eloop.signal_count; i++) {
     843        5702 :                 if (eloop.signals[i].signaled) {
     844        1432 :                         eloop.signals[i].signaled = 0;
     845        2864 :                         eloop.signals[i].handler(eloop.signals[i].sig,
     846        1432 :                                                  eloop.signals[i].user_data);
     847             :                 }
     848             :         }
     849             : }
     850             : 
     851             : 
     852         237 : int eloop_register_signal(int sig, eloop_signal_handler handler,
     853             :                           void *user_data)
     854             : {
     855             :         struct eloop_signal *tmp;
     856             : 
     857         237 :         tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
     858             :                                sizeof(struct eloop_signal));
     859         237 :         if (tmp == NULL)
     860           0 :                 return -1;
     861             : 
     862         237 :         tmp[eloop.signal_count].sig = sig;
     863         237 :         tmp[eloop.signal_count].user_data = user_data;
     864         237 :         tmp[eloop.signal_count].handler = handler;
     865         237 :         tmp[eloop.signal_count].signaled = 0;
     866         237 :         eloop.signal_count++;
     867         237 :         eloop.signals = tmp;
     868         237 :         signal(sig, eloop_handle_signal);
     869             : 
     870         237 :         return 0;
     871             : }
     872             : 
     873             : 
     874          77 : int eloop_register_signal_terminate(eloop_signal_handler handler,
     875             :                                     void *user_data)
     876             : {
     877          77 :         int ret = eloop_register_signal(SIGINT, handler, user_data);
     878          77 :         if (ret == 0)
     879          77 :                 ret = eloop_register_signal(SIGTERM, handler, user_data);
     880          77 :         return ret;
     881             : }
     882             : 
     883             : 
     884          27 : int eloop_register_signal_reconfig(eloop_signal_handler handler,
     885             :                                    void *user_data)
     886             : {
     887             : #ifdef CONFIG_NATIVE_WINDOWS
     888             :         return 0;
     889             : #else /* CONFIG_NATIVE_WINDOWS */
     890          27 :         return eloop_register_signal(SIGHUP, handler, user_data);
     891             : #endif /* CONFIG_NATIVE_WINDOWS */
     892             : }
     893             : 
     894             : 
     895          44 : void eloop_run(void)
     896             : {
     897             : #ifdef CONFIG_ELOOP_POLL
     898             :         int num_poll_fds;
     899             :         int timeout_ms = 0;
     900             : #endif /* CONFIG_ELOOP_POLL */
     901             : #ifdef CONFIG_ELOOP_SELECT
     902             :         fd_set *rfds, *wfds, *efds;
     903             :         struct timeval _tv;
     904             : #endif /* CONFIG_ELOOP_SELECT */
     905             : #ifdef CONFIG_ELOOP_EPOLL
     906             :         int timeout_ms = -1;
     907             : #endif /* CONFIG_ELOOP_EPOLL */
     908             :         int res;
     909             :         struct os_reltime tv, now;
     910             : 
     911             : #ifdef CONFIG_ELOOP_SELECT
     912          44 :         rfds = os_malloc(sizeof(*rfds));
     913          44 :         wfds = os_malloc(sizeof(*wfds));
     914          44 :         efds = os_malloc(sizeof(*efds));
     915          44 :         if (rfds == NULL || wfds == NULL || efds == NULL)
     916             :                 goto out;
     917             : #endif /* CONFIG_ELOOP_SELECT */
     918             : 
     919     1377821 :         while (!eloop.terminate &&
     920      688868 :                (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
     921           0 :                 eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
     922             :                 struct eloop_timeout *timeout;
     923             : 
     924      688868 :                 if (eloop.pending_terminate) {
     925             :                         /*
     926             :                          * This may happen in some corner cases where a signal
     927             :                          * is received during a blocking operation. We need to
     928             :                          * process the pending signals and exit if requested to
     929             :                          * avoid hitting the SIGALRM limit if the blocking
     930             :                          * operation took more than two seconds.
     931             :                          */
     932           3 :                         eloop_process_pending_signals();
     933           3 :                         if (eloop.terminate)
     934           3 :                                 break;
     935             :                 }
     936             : 
     937      688865 :                 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
     938             :                                         list);
     939      688865 :                 if (timeout) {
     940      688865 :                         os_get_reltime(&now);
     941      688865 :                         if (os_reltime_before(&now, &timeout->time))
     942      624949 :                                 os_reltime_sub(&timeout->time, &now, &tv);
     943             :                         else
     944       63916 :                                 tv.sec = tv.usec = 0;
     945             : #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
     946             :                         timeout_ms = tv.sec * 1000 + tv.usec / 1000;
     947             : #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
     948             : #ifdef CONFIG_ELOOP_SELECT
     949      688865 :                         _tv.tv_sec = tv.sec;
     950      688865 :                         _tv.tv_usec = tv.usec;
     951             : #endif /* CONFIG_ELOOP_SELECT */
     952             :                 }
     953             : 
     954             : #ifdef CONFIG_ELOOP_POLL
     955             :                 num_poll_fds = eloop_sock_table_set_fds(
     956             :                         &eloop.readers, &eloop.writers, &eloop.exceptions,
     957             :                         eloop.pollfds, eloop.pollfds_map,
     958             :                         eloop.max_pollfd_map);
     959             :                 res = poll(eloop.pollfds, num_poll_fds,
     960             :                            timeout ? timeout_ms : -1);
     961             : #endif /* CONFIG_ELOOP_POLL */
     962             : #ifdef CONFIG_ELOOP_SELECT
     963      688865 :                 eloop_sock_table_set_fds(&eloop.readers, rfds);
     964      688865 :                 eloop_sock_table_set_fds(&eloop.writers, wfds);
     965      688865 :                 eloop_sock_table_set_fds(&eloop.exceptions, efds);
     966      688865 :                 res = select(eloop.max_sock + 1, rfds, wfds, efds,
     967             :                              timeout ? &_tv : NULL);
     968             : #endif /* CONFIG_ELOOP_SELECT */
     969             : #ifdef CONFIG_ELOOP_EPOLL
     970             :                 if (eloop.count == 0) {
     971             :                         res = 0;
     972             :                 } else {
     973             :                         res = epoll_wait(eloop.epollfd, eloop.epoll_events,
     974             :                                          eloop.count, timeout_ms);
     975             :                 }
     976             : #endif /* CONFIG_ELOOP_EPOLL */
     977      688865 :                 if (res < 0 && errno != EINTR && errno != 0) {
     978           0 :                         wpa_printf(MSG_ERROR, "eloop: %s: %s",
     979             : #ifdef CONFIG_ELOOP_POLL
     980             :                                    "poll"
     981             : #endif /* CONFIG_ELOOP_POLL */
     982             : #ifdef CONFIG_ELOOP_SELECT
     983             :                                    "select"
     984             : #endif /* CONFIG_ELOOP_SELECT */
     985             : #ifdef CONFIG_ELOOP_EPOLL
     986             :                                    "epoll"
     987             : #endif /* CONFIG_ELOOP_EPOLL */
     988           0 :                                    , strerror(errno));
     989           0 :                         goto out;
     990             :                 }
     991             : 
     992      688865 :                 eloop.readers.changed = 0;
     993      688865 :                 eloop.writers.changed = 0;
     994      688865 :                 eloop.exceptions.changed = 0;
     995             : 
     996      688865 :                 eloop_process_pending_signals();
     997             : 
     998             :                 /* check if some registered timeouts have occurred */
     999      688865 :                 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
    1000             :                                         list);
    1001      688865 :                 if (timeout) {
    1002      688865 :                         os_get_reltime(&now);
    1003      688865 :                         if (!os_reltime_before(&now, &timeout->time)) {
    1004       80585 :                                 void *eloop_data = timeout->eloop_data;
    1005       80585 :                                 void *user_data = timeout->user_data;
    1006       80585 :                                 eloop_timeout_handler handler =
    1007             :                                         timeout->handler;
    1008       80585 :                                 eloop_remove_timeout(timeout);
    1009       80585 :                                 handler(eloop_data, user_data);
    1010             :                         }
    1011             : 
    1012             :                 }
    1013             : 
    1014      688865 :                 if (res <= 0)
    1015       59626 :                         continue;
    1016             : 
    1017     1258076 :                 if (eloop.readers.changed ||
    1018     1257359 :                     eloop.writers.changed ||
    1019      628522 :                     eloop.exceptions.changed) {
    1020             :                          /*
    1021             :                           * Sockets may have been closed and reopened with the
    1022             :                           * same FD in the signal or timeout handlers, so we
    1023             :                           * must skip the previous results and check again
    1024             :                           * whether any of the currently registered sockets have
    1025             :                           * events.
    1026             :                           */
    1027         717 :                         continue;
    1028             :                 }
    1029             : 
    1030             : #ifdef CONFIG_ELOOP_POLL
    1031             :                 eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
    1032             :                                           &eloop.exceptions, eloop.pollfds_map,
    1033             :                                           eloop.max_pollfd_map);
    1034             : #endif /* CONFIG_ELOOP_POLL */
    1035             : #ifdef CONFIG_ELOOP_SELECT
    1036      628522 :                 eloop_sock_table_dispatch(&eloop.readers, rfds);
    1037      628522 :                 eloop_sock_table_dispatch(&eloop.writers, wfds);
    1038      628522 :                 eloop_sock_table_dispatch(&eloop.exceptions, efds);
    1039             : #endif /* CONFIG_ELOOP_SELECT */
    1040             : #ifdef CONFIG_ELOOP_EPOLL
    1041             :                 eloop_sock_table_dispatch(eloop.epoll_events, res);
    1042             : #endif /* CONFIG_ELOOP_EPOLL */
    1043             :         }
    1044             : 
    1045          44 :         eloop.terminate = 0;
    1046             : out:
    1047             : #ifdef CONFIG_ELOOP_SELECT
    1048          44 :         os_free(rfds);
    1049          44 :         os_free(wfds);
    1050          44 :         os_free(efds);
    1051             : #endif /* CONFIG_ELOOP_SELECT */
    1052          44 :         return;
    1053             : }
    1054             : 
    1055             : 
    1056          44 : void eloop_terminate(void)
    1057             : {
    1058          44 :         eloop.terminate = 1;
    1059          44 : }
    1060             : 
    1061             : 
    1062         105 : void eloop_destroy(void)
    1063             : {
    1064             :         struct eloop_timeout *timeout, *prev;
    1065             :         struct os_reltime now;
    1066             : 
    1067         105 :         os_get_reltime(&now);
    1068         105 :         dl_list_for_each_safe(timeout, prev, &eloop.timeout,
    1069             :                               struct eloop_timeout, list) {
    1070             :                 int sec, usec;
    1071           0 :                 sec = timeout->time.sec - now.sec;
    1072           0 :                 usec = timeout->time.usec - now.usec;
    1073           0 :                 if (timeout->time.usec < now.usec) {
    1074           0 :                         sec--;
    1075           0 :                         usec += 1000000;
    1076             :                 }
    1077           0 :                 wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
    1078             :                            "eloop_data=%p user_data=%p handler=%p",
    1079             :                            sec, usec, timeout->eloop_data, timeout->user_data,
    1080             :                            timeout->handler);
    1081           0 :                 wpa_trace_dump_funcname("eloop unregistered timeout handler",
    1082           0 :                                         timeout->handler);
    1083           0 :                 wpa_trace_dump("eloop timeout", timeout);
    1084           0 :                 eloop_remove_timeout(timeout);
    1085             :         }
    1086         105 :         eloop_sock_table_destroy(&eloop.readers);
    1087         105 :         eloop_sock_table_destroy(&eloop.writers);
    1088         105 :         eloop_sock_table_destroy(&eloop.exceptions);
    1089         105 :         os_free(eloop.signals);
    1090             : 
    1091             : #ifdef CONFIG_ELOOP_POLL
    1092             :         os_free(eloop.pollfds);
    1093             :         os_free(eloop.pollfds_map);
    1094             : #endif /* CONFIG_ELOOP_POLL */
    1095             : #ifdef CONFIG_ELOOP_EPOLL
    1096             :         os_free(eloop.epoll_table);
    1097             :         os_free(eloop.epoll_events);
    1098             :         close(eloop.epollfd);
    1099             : #endif /* CONFIG_ELOOP_EPOLL */
    1100         105 : }
    1101             : 
    1102             : 
    1103        4940 : int eloop_terminated(void)
    1104             : {
    1105        4940 :         return eloop.terminate || eloop.pending_terminate;
    1106             : }
    1107             : 
    1108             : 
    1109           1 : void eloop_wait_for_read_sock(int sock)
    1110             : {
    1111             : #ifdef CONFIG_ELOOP_POLL
    1112             :         struct pollfd pfd;
    1113             : 
    1114             :         if (sock < 0)
    1115             :                 return;
    1116             : 
    1117             :         os_memset(&pfd, 0, sizeof(pfd));
    1118             :         pfd.fd = sock;
    1119             :         pfd.events = POLLIN;
    1120             : 
    1121             :         poll(&pfd, 1, -1);
    1122             : #endif /* CONFIG_ELOOP_POLL */
    1123             : #if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL)
    1124             :         /*
    1125             :          * We can use epoll() here. But epoll() requres 4 system calls.
    1126             :          * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for
    1127             :          * epoll fd. So select() is better for performance here.
    1128             :          */
    1129             :         fd_set rfds;
    1130             : 
    1131           1 :         if (sock < 0)
    1132           1 :                 return;
    1133             : 
    1134           1 :         FD_ZERO(&rfds);
    1135           1 :         FD_SET(sock, &rfds);
    1136           1 :         select(sock + 1, &rfds, NULL, NULL, NULL);
    1137             : #endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
    1138             : }
    1139             : 
    1140             : #ifdef CONFIG_ELOOP_SELECT
    1141             : #undef CONFIG_ELOOP_SELECT
    1142             : #endif /* CONFIG_ELOOP_SELECT */

Generated by: LCOV version 1.10