Disconnect hostapd from building in base
[dragonfly.git] / contrib / hostapd / src / utils / eloop.c
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
11 #include "common.h"
12 #include "trace.h"
13 #include "list.h"
14 #include "eloop.h"
15
16 #ifdef CONFIG_ELOOP_POLL
17 #include <assert.h>
18 #include <poll.h>
19 #endif /* CONFIG_ELOOP_POLL */
20
21
22 struct eloop_sock {
23         int sock;
24         void *eloop_data;
25         void *user_data;
26         eloop_sock_handler handler;
27         WPA_TRACE_REF(eloop);
28         WPA_TRACE_REF(user);
29         WPA_TRACE_INFO
30 };
31
32 struct eloop_timeout {
33         struct dl_list list;
34         struct os_reltime time;
35         void *eloop_data;
36         void *user_data;
37         eloop_timeout_handler handler;
38         WPA_TRACE_REF(eloop);
39         WPA_TRACE_REF(user);
40         WPA_TRACE_INFO
41 };
42
43 struct eloop_signal {
44         int sig;
45         void *user_data;
46         eloop_signal_handler handler;
47         int signaled;
48 };
49
50 struct eloop_sock_table {
51         int count;
52         struct eloop_sock *table;
53         int changed;
54 };
55
56 struct eloop_data {
57         int max_sock;
58
59         int count; /* sum of all table counts */
60 #ifdef CONFIG_ELOOP_POLL
61         int max_pollfd_map; /* number of pollfds_map currently allocated */
62         int max_poll_fds; /* number of pollfds currently allocated */
63         struct pollfd *pollfds;
64         struct pollfd **pollfds_map;
65 #endif /* CONFIG_ELOOP_POLL */
66         struct eloop_sock_table readers;
67         struct eloop_sock_table writers;
68         struct eloop_sock_table exceptions;
69
70         struct dl_list timeout;
71
72         int signal_count;
73         struct eloop_signal *signals;
74         int signaled;
75         int pending_terminate;
76
77         int terminate;
78         int reader_table_changed;
79 };
80
81 static struct eloop_data eloop;
82
83
84 #ifdef WPA_TRACE
85
86 static void eloop_sigsegv_handler(int sig)
87 {
88         wpa_trace_show("eloop SIGSEGV");
89         abort();
90 }
91
92 static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
93 {
94         int i;
95         if (table == NULL || table->table == NULL)
96                 return;
97         for (i = 0; i < table->count; i++) {
98                 wpa_trace_add_ref(&table->table[i], eloop,
99                                   table->table[i].eloop_data);
100                 wpa_trace_add_ref(&table->table[i], user,
101                                   table->table[i].user_data);
102         }
103 }
104
105
106 static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
107 {
108         int i;
109         if (table == NULL || table->table == NULL)
110                 return;
111         for (i = 0; i < table->count; i++) {
112                 wpa_trace_remove_ref(&table->table[i], eloop,
113                                      table->table[i].eloop_data);
114                 wpa_trace_remove_ref(&table->table[i], user,
115                                      table->table[i].user_data);
116         }
117 }
118
119 #else /* WPA_TRACE */
120
121 #define eloop_trace_sock_add_ref(table) do { } while (0)
122 #define eloop_trace_sock_remove_ref(table) do { } while (0)
123
124 #endif /* WPA_TRACE */
125
126
127 int eloop_init(void)
128 {
129         os_memset(&eloop, 0, sizeof(eloop));
130         dl_list_init(&eloop.timeout);
131 #ifdef WPA_TRACE
132         signal(SIGSEGV, eloop_sigsegv_handler);
133 #endif /* WPA_TRACE */
134         return 0;
135 }
136
137
138 static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
139                                      int sock, eloop_sock_handler handler,
140                                      void *eloop_data, void *user_data)
141 {
142         struct eloop_sock *tmp;
143         int new_max_sock;
144
145         if (sock > eloop.max_sock)
146                 new_max_sock = sock;
147         else
148                 new_max_sock = eloop.max_sock;
149
150         if (table == NULL)
151                 return -1;
152
153 #ifdef CONFIG_ELOOP_POLL
154         if (new_max_sock >= eloop.max_pollfd_map) {
155                 struct pollfd **nmap;
156                 nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50,
157                                         sizeof(struct pollfd *));
158                 if (nmap == NULL)
159                         return -1;
160
161                 eloop.max_pollfd_map = new_max_sock + 50;
162                 eloop.pollfds_map = nmap;
163         }
164
165         if (eloop.count + 1 > eloop.max_poll_fds) {
166                 struct pollfd *n;
167                 int nmax = eloop.count + 1 + 50;
168                 n = os_realloc_array(eloop.pollfds, nmax,
169                                      sizeof(struct pollfd));
170                 if (n == NULL)
171                         return -1;
172
173                 eloop.max_poll_fds = nmax;
174                 eloop.pollfds = n;
175         }
176 #endif /* CONFIG_ELOOP_POLL */
177
178         eloop_trace_sock_remove_ref(table);
179         tmp = os_realloc_array(table->table, table->count + 1,
180                                sizeof(struct eloop_sock));
181         if (tmp == NULL)
182                 return -1;
183
184         tmp[table->count].sock = sock;
185         tmp[table->count].eloop_data = eloop_data;
186         tmp[table->count].user_data = user_data;
187         tmp[table->count].handler = handler;
188         wpa_trace_record(&tmp[table->count]);
189         table->count++;
190         table->table = tmp;
191         eloop.max_sock = new_max_sock;
192         eloop.count++;
193         table->changed = 1;
194         eloop_trace_sock_add_ref(table);
195
196         return 0;
197 }
198
199
200 static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
201                                          int sock)
202 {
203         int i;
204
205         if (table == NULL || table->table == NULL || table->count == 0)
206                 return;
207
208         for (i = 0; i < table->count; i++) {
209                 if (table->table[i].sock == sock)
210                         break;
211         }
212         if (i == table->count)
213                 return;
214         eloop_trace_sock_remove_ref(table);
215         if (i != table->count - 1) {
216                 os_memmove(&table->table[i], &table->table[i + 1],
217                            (table->count - i - 1) *
218                            sizeof(struct eloop_sock));
219         }
220         table->count--;
221         eloop.count--;
222         table->changed = 1;
223         eloop_trace_sock_add_ref(table);
224 }
225
226
227 #ifdef CONFIG_ELOOP_POLL
228
229 static struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx)
230 {
231         if (fd < mx && fd >= 0)
232                 return pollfds_map[fd];
233         return NULL;
234 }
235
236
237 static int eloop_sock_table_set_fds(struct eloop_sock_table *readers,
238                                     struct eloop_sock_table *writers,
239                                     struct eloop_sock_table *exceptions,
240                                     struct pollfd *pollfds,
241                                     struct pollfd **pollfds_map,
242                                     int max_pollfd_map)
243 {
244         int i;
245         int nxt = 0;
246         int fd;
247         struct pollfd *pfd;
248
249         /* Clear pollfd lookup map. It will be re-populated below. */
250         os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map);
251
252         if (readers && readers->table) {
253                 for (i = 0; i < readers->count; i++) {
254                         fd = readers->table[i].sock;
255                         assert(fd >= 0 && fd < max_pollfd_map);
256                         pollfds[nxt].fd = fd;
257                         pollfds[nxt].events = POLLIN;
258                         pollfds[nxt].revents = 0;
259                         pollfds_map[fd] = &(pollfds[nxt]);
260                         nxt++;
261                 }
262         }
263
264         if (writers && writers->table) {
265                 for (i = 0; i < writers->count; i++) {
266                         /*
267                          * See if we already added this descriptor, update it
268                          * if so.
269                          */
270                         fd = writers->table[i].sock;
271                         assert(fd >= 0 && fd < max_pollfd_map);
272                         pfd = pollfds_map[fd];
273                         if (!pfd) {
274                                 pfd = &(pollfds[nxt]);
275                                 pfd->events = 0;
276                                 pfd->fd = fd;
277                                 pollfds[i].revents = 0;
278                                 pollfds_map[fd] = pfd;
279                                 nxt++;
280                         }
281                         pfd->events |= POLLOUT;
282                 }
283         }
284
285         /*
286          * Exceptions are always checked when using poll, but I suppose it's
287          * possible that someone registered a socket *only* for exception
288          * handling. Set the POLLIN bit in this case.
289          */
290         if (exceptions && exceptions->table) {
291                 for (i = 0; i < exceptions->count; i++) {
292                         /*
293                          * See if we already added this descriptor, just use it
294                          * if so.
295                          */
296                         fd = exceptions->table[i].sock;
297                         assert(fd >= 0 && fd < max_pollfd_map);
298                         pfd = pollfds_map[fd];
299                         if (!pfd) {
300                                 pfd = &(pollfds[nxt]);
301                                 pfd->events = POLLIN;
302                                 pfd->fd = fd;
303                                 pollfds[i].revents = 0;
304                                 pollfds_map[fd] = pfd;
305                                 nxt++;
306                         }
307                 }
308         }
309
310         return nxt;
311 }
312
313
314 static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table,
315                                            struct pollfd **pollfds_map,
316                                            int max_pollfd_map,
317                                            short int revents)
318 {
319         int i;
320         struct pollfd *pfd;
321
322         if (!table || !table->table)
323                 return 0;
324
325         table->changed = 0;
326         for (i = 0; i < table->count; i++) {
327                 pfd = find_pollfd(pollfds_map, table->table[i].sock,
328                                   max_pollfd_map);
329                 if (!pfd)
330                         continue;
331
332                 if (!(pfd->revents & revents))
333                         continue;
334
335                 table->table[i].handler(table->table[i].sock,
336                                         table->table[i].eloop_data,
337                                         table->table[i].user_data);
338                 if (table->changed)
339                         return 1;
340         }
341
342         return 0;
343 }
344
345
346 static void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
347                                       struct eloop_sock_table *writers,
348                                       struct eloop_sock_table *exceptions,
349                                       struct pollfd **pollfds_map,
350                                       int max_pollfd_map)
351 {
352         if (eloop_sock_table_dispatch_table(readers, pollfds_map,
353                                             max_pollfd_map, POLLIN | POLLERR |
354                                             POLLHUP))
355                 return; /* pollfds may be invalid at this point */
356
357         if (eloop_sock_table_dispatch_table(writers, pollfds_map,
358                                             max_pollfd_map, POLLOUT))
359                 return; /* pollfds may be invalid at this point */
360
361         eloop_sock_table_dispatch_table(exceptions, pollfds_map,
362                                         max_pollfd_map, POLLERR | POLLHUP);
363 }
364
365 #else /* CONFIG_ELOOP_POLL */
366
367 static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
368                                      fd_set *fds)
369 {
370         int i;
371
372         FD_ZERO(fds);
373
374         if (table->table == NULL)
375                 return;
376
377         for (i = 0; i < table->count; i++)
378                 FD_SET(table->table[i].sock, fds);
379 }
380
381
382 static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
383                                       fd_set *fds)
384 {
385         int i;
386
387         if (table == NULL || table->table == NULL)
388                 return;
389
390         table->changed = 0;
391         for (i = 0; i < table->count; i++) {
392                 if (FD_ISSET(table->table[i].sock, fds)) {
393                         table->table[i].handler(table->table[i].sock,
394                                                 table->table[i].eloop_data,
395                                                 table->table[i].user_data);
396                         if (table->changed)
397                                 break;
398                 }
399         }
400 }
401
402 #endif /* CONFIG_ELOOP_POLL */
403
404
405 static void eloop_sock_table_destroy(struct eloop_sock_table *table)
406 {
407         if (table) {
408                 int i;
409                 for (i = 0; i < table->count && table->table; i++) {
410                         wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
411                                    "sock=%d eloop_data=%p user_data=%p "
412                                    "handler=%p",
413                                    table->table[i].sock,
414                                    table->table[i].eloop_data,
415                                    table->table[i].user_data,
416                                    table->table[i].handler);
417                         wpa_trace_dump_funcname("eloop unregistered socket "
418                                                 "handler",
419                                                 table->table[i].handler);
420                         wpa_trace_dump("eloop sock", &table->table[i]);
421                 }
422                 os_free(table->table);
423         }
424 }
425
426
427 int eloop_register_read_sock(int sock, eloop_sock_handler handler,
428                              void *eloop_data, void *user_data)
429 {
430         return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
431                                    eloop_data, user_data);
432 }
433
434
435 void eloop_unregister_read_sock(int sock)
436 {
437         eloop_unregister_sock(sock, EVENT_TYPE_READ);
438 }
439
440
441 static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
442 {
443         switch (type) {
444         case EVENT_TYPE_READ:
445                 return &eloop.readers;
446         case EVENT_TYPE_WRITE:
447                 return &eloop.writers;
448         case EVENT_TYPE_EXCEPTION:
449                 return &eloop.exceptions;
450         }
451
452         return NULL;
453 }
454
455
456 int eloop_register_sock(int sock, eloop_event_type type,
457                         eloop_sock_handler handler,
458                         void *eloop_data, void *user_data)
459 {
460         struct eloop_sock_table *table;
461
462         table = eloop_get_sock_table(type);
463         return eloop_sock_table_add_sock(table, sock, handler,
464                                          eloop_data, user_data);
465 }
466
467
468 void eloop_unregister_sock(int sock, eloop_event_type type)
469 {
470         struct eloop_sock_table *table;
471
472         table = eloop_get_sock_table(type);
473         eloop_sock_table_remove_sock(table, sock);
474 }
475
476
477 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
478                            eloop_timeout_handler handler,
479                            void *eloop_data, void *user_data)
480 {
481         struct eloop_timeout *timeout, *tmp;
482         os_time_t now_sec;
483
484         timeout = os_zalloc(sizeof(*timeout));
485         if (timeout == NULL)
486                 return -1;
487         if (os_get_reltime(&timeout->time) < 0) {
488                 os_free(timeout);
489                 return -1;
490         }
491         now_sec = timeout->time.sec;
492         timeout->time.sec += secs;
493         if (timeout->time.sec < now_sec) {
494                 /*
495                  * Integer overflow - assume long enough timeout to be assumed
496                  * to be infinite, i.e., the timeout would never happen.
497                  */
498                 wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
499                            "ever happen - ignore it", secs);
500                 os_free(timeout);
501                 return 0;
502         }
503         timeout->time.usec += usecs;
504         while (timeout->time.usec >= 1000000) {
505                 timeout->time.sec++;
506                 timeout->time.usec -= 1000000;
507         }
508         timeout->eloop_data = eloop_data;
509         timeout->user_data = user_data;
510         timeout->handler = handler;
511         wpa_trace_add_ref(timeout, eloop, eloop_data);
512         wpa_trace_add_ref(timeout, user, user_data);
513         wpa_trace_record(timeout);
514
515         /* Maintain timeouts in order of increasing time */
516         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
517                 if (os_reltime_before(&timeout->time, &tmp->time)) {
518                         dl_list_add(tmp->list.prev, &timeout->list);
519                         return 0;
520                 }
521         }
522         dl_list_add_tail(&eloop.timeout, &timeout->list);
523
524         return 0;
525 }
526
527
528 static void eloop_remove_timeout(struct eloop_timeout *timeout)
529 {
530         dl_list_del(&timeout->list);
531         wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
532         wpa_trace_remove_ref(timeout, user, timeout->user_data);
533         os_free(timeout);
534 }
535
536
537 int eloop_cancel_timeout(eloop_timeout_handler handler,
538                          void *eloop_data, void *user_data)
539 {
540         struct eloop_timeout *timeout, *prev;
541         int removed = 0;
542
543         dl_list_for_each_safe(timeout, prev, &eloop.timeout,
544                               struct eloop_timeout, list) {
545                 if (timeout->handler == handler &&
546                     (timeout->eloop_data == eloop_data ||
547                      eloop_data == ELOOP_ALL_CTX) &&
548                     (timeout->user_data == user_data ||
549                      user_data == ELOOP_ALL_CTX)) {
550                         eloop_remove_timeout(timeout);
551                         removed++;
552                 }
553         }
554
555         return removed;
556 }
557
558
559 int eloop_cancel_timeout_one(eloop_timeout_handler handler,
560                              void *eloop_data, void *user_data,
561                              struct os_reltime *remaining)
562 {
563         struct eloop_timeout *timeout, *prev;
564         int removed = 0;
565         struct os_reltime now;
566
567         os_get_reltime(&now);
568         remaining->sec = remaining->usec = 0;
569
570         dl_list_for_each_safe(timeout, prev, &eloop.timeout,
571                               struct eloop_timeout, list) {
572                 if (timeout->handler == handler &&
573                     (timeout->eloop_data == eloop_data) &&
574                     (timeout->user_data == user_data)) {
575                         removed = 1;
576                         if (os_reltime_before(&now, &timeout->time))
577                                 os_reltime_sub(&timeout->time, &now, remaining);
578                         eloop_remove_timeout(timeout);
579                         break;
580                 }
581         }
582         return removed;
583 }
584
585
586 int eloop_is_timeout_registered(eloop_timeout_handler handler,
587                                 void *eloop_data, void *user_data)
588 {
589         struct eloop_timeout *tmp;
590
591         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
592                 if (tmp->handler == handler &&
593                     tmp->eloop_data == eloop_data &&
594                     tmp->user_data == user_data)
595                         return 1;
596         }
597
598         return 0;
599 }
600
601
602 int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
603                           eloop_timeout_handler handler, void *eloop_data,
604                           void *user_data)
605 {
606         struct os_reltime now, requested, remaining;
607         struct eloop_timeout *tmp;
608
609         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
610                 if (tmp->handler == handler &&
611                     tmp->eloop_data == eloop_data &&
612                     tmp->user_data == user_data) {
613                         requested.sec = req_secs;
614                         requested.usec = req_usecs;
615                         os_get_reltime(&now);
616                         os_reltime_sub(&tmp->time, &now, &remaining);
617                         if (os_reltime_before(&requested, &remaining)) {
618                                 eloop_cancel_timeout(handler, eloop_data,
619                                                      user_data);
620                                 eloop_register_timeout(requested.sec,
621                                                        requested.usec,
622                                                        handler, eloop_data,
623                                                        user_data);
624                                 return 1;
625                         }
626                         return 0;
627                 }
628         }
629
630         return -1;
631 }
632
633
634 int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
635                             eloop_timeout_handler handler, void *eloop_data,
636                             void *user_data)
637 {
638         struct os_reltime now, requested, remaining;
639         struct eloop_timeout *tmp;
640
641         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
642                 if (tmp->handler == handler &&
643                     tmp->eloop_data == eloop_data &&
644                     tmp->user_data == user_data) {
645                         requested.sec = req_secs;
646                         requested.usec = req_usecs;
647                         os_get_reltime(&now);
648                         os_reltime_sub(&tmp->time, &now, &remaining);
649                         if (os_reltime_before(&remaining, &requested)) {
650                                 eloop_cancel_timeout(handler, eloop_data,
651                                                      user_data);
652                                 eloop_register_timeout(requested.sec,
653                                                        requested.usec,
654                                                        handler, eloop_data,
655                                                        user_data);
656                                 return 1;
657                         }
658                         return 0;
659                 }
660         }
661
662         return -1;
663 }
664
665
666 #ifndef CONFIG_NATIVE_WINDOWS
667 static void eloop_handle_alarm(int sig)
668 {
669         wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
670                    "two seconds. Looks like there\n"
671                    "is a bug that ends up in a busy loop that "
672                    "prevents clean shutdown.\n"
673                    "Killing program forcefully.\n");
674         exit(1);
675 }
676 #endif /* CONFIG_NATIVE_WINDOWS */
677
678
679 static void eloop_handle_signal(int sig)
680 {
681         int i;
682
683 #ifndef CONFIG_NATIVE_WINDOWS
684         if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
685                 /* Use SIGALRM to break out from potential busy loops that
686                  * would not allow the program to be killed. */
687                 eloop.pending_terminate = 1;
688                 signal(SIGALRM, eloop_handle_alarm);
689                 alarm(2);
690         }
691 #endif /* CONFIG_NATIVE_WINDOWS */
692
693         eloop.signaled++;
694         for (i = 0; i < eloop.signal_count; i++) {
695                 if (eloop.signals[i].sig == sig) {
696                         eloop.signals[i].signaled++;
697                         break;
698                 }
699         }
700 }
701
702
703 static void eloop_process_pending_signals(void)
704 {
705         int i;
706
707         if (eloop.signaled == 0)
708                 return;
709         eloop.signaled = 0;
710
711         if (eloop.pending_terminate) {
712 #ifndef CONFIG_NATIVE_WINDOWS
713                 alarm(0);
714 #endif /* CONFIG_NATIVE_WINDOWS */
715                 eloop.pending_terminate = 0;
716         }
717
718         for (i = 0; i < eloop.signal_count; i++) {
719                 if (eloop.signals[i].signaled) {
720                         eloop.signals[i].signaled = 0;
721                         eloop.signals[i].handler(eloop.signals[i].sig,
722                                                  eloop.signals[i].user_data);
723                 }
724         }
725 }
726
727
728 int eloop_register_signal(int sig, eloop_signal_handler handler,
729                           void *user_data)
730 {
731         struct eloop_signal *tmp;
732
733         tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
734                                sizeof(struct eloop_signal));
735         if (tmp == NULL)
736                 return -1;
737
738         tmp[eloop.signal_count].sig = sig;
739         tmp[eloop.signal_count].user_data = user_data;
740         tmp[eloop.signal_count].handler = handler;
741         tmp[eloop.signal_count].signaled = 0;
742         eloop.signal_count++;
743         eloop.signals = tmp;
744         signal(sig, eloop_handle_signal);
745
746         return 0;
747 }
748
749
750 int eloop_register_signal_terminate(eloop_signal_handler handler,
751                                     void *user_data)
752 {
753         int ret = eloop_register_signal(SIGINT, handler, user_data);
754         if (ret == 0)
755                 ret = eloop_register_signal(SIGTERM, handler, user_data);
756         return ret;
757 }
758
759
760 int eloop_register_signal_reconfig(eloop_signal_handler handler,
761                                    void *user_data)
762 {
763 #ifdef CONFIG_NATIVE_WINDOWS
764         return 0;
765 #else /* CONFIG_NATIVE_WINDOWS */
766         return eloop_register_signal(SIGHUP, handler, user_data);
767 #endif /* CONFIG_NATIVE_WINDOWS */
768 }
769
770
771 void eloop_run(void)
772 {
773 #ifdef CONFIG_ELOOP_POLL
774         int num_poll_fds;
775         int timeout_ms = 0;
776 #else /* CONFIG_ELOOP_POLL */
777         fd_set *rfds, *wfds, *efds;
778         struct timeval _tv;
779 #endif /* CONFIG_ELOOP_POLL */
780         int res;
781         struct os_reltime tv, now;
782
783 #ifndef CONFIG_ELOOP_POLL
784         rfds = os_malloc(sizeof(*rfds));
785         wfds = os_malloc(sizeof(*wfds));
786         efds = os_malloc(sizeof(*efds));
787         if (rfds == NULL || wfds == NULL || efds == NULL)
788                 goto out;
789 #endif /* CONFIG_ELOOP_POLL */
790
791         while (!eloop.terminate &&
792                (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
793                 eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
794                 struct eloop_timeout *timeout;
795                 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
796                                         list);
797                 if (timeout) {
798                         os_get_reltime(&now);
799                         if (os_reltime_before(&now, &timeout->time))
800                                 os_reltime_sub(&timeout->time, &now, &tv);
801                         else
802                                 tv.sec = tv.usec = 0;
803 #ifdef CONFIG_ELOOP_POLL
804                         timeout_ms = tv.sec * 1000 + tv.usec / 1000;
805 #else /* CONFIG_ELOOP_POLL */
806                         _tv.tv_sec = tv.sec;
807                         _tv.tv_usec = tv.usec;
808 #endif /* CONFIG_ELOOP_POLL */
809                 }
810
811 #ifdef CONFIG_ELOOP_POLL
812                 num_poll_fds = eloop_sock_table_set_fds(
813                         &eloop.readers, &eloop.writers, &eloop.exceptions,
814                         eloop.pollfds, eloop.pollfds_map,
815                         eloop.max_pollfd_map);
816                 res = poll(eloop.pollfds, num_poll_fds,
817                            timeout ? timeout_ms : -1);
818
819                 if (res < 0 && errno != EINTR && errno != 0) {
820                         wpa_printf(MSG_INFO, "eloop: poll: %s",
821                                    strerror(errno));
822                         goto out;
823                 }
824 #else /* CONFIG_ELOOP_POLL */
825                 eloop_sock_table_set_fds(&eloop.readers, rfds);
826                 eloop_sock_table_set_fds(&eloop.writers, wfds);
827                 eloop_sock_table_set_fds(&eloop.exceptions, efds);
828                 res = select(eloop.max_sock + 1, rfds, wfds, efds,
829                              timeout ? &_tv : NULL);
830                 if (res < 0 && errno != EINTR && errno != 0) {
831                         wpa_printf(MSG_INFO, "eloop: select: %s",
832                                    strerror(errno));
833                         goto out;
834                 }
835 #endif /* CONFIG_ELOOP_POLL */
836                 eloop_process_pending_signals();
837
838                 /* check if some registered timeouts have occurred */
839                 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
840                                         list);
841                 if (timeout) {
842                         os_get_reltime(&now);
843                         if (!os_reltime_before(&now, &timeout->time)) {
844                                 void *eloop_data = timeout->eloop_data;
845                                 void *user_data = timeout->user_data;
846                                 eloop_timeout_handler handler =
847                                         timeout->handler;
848                                 eloop_remove_timeout(timeout);
849                                 handler(eloop_data, user_data);
850                         }
851
852                 }
853
854                 if (res <= 0)
855                         continue;
856
857 #ifdef CONFIG_ELOOP_POLL
858                 eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
859                                           &eloop.exceptions, eloop.pollfds_map,
860                                           eloop.max_pollfd_map);
861 #else /* CONFIG_ELOOP_POLL */
862                 eloop_sock_table_dispatch(&eloop.readers, rfds);
863                 eloop_sock_table_dispatch(&eloop.writers, wfds);
864                 eloop_sock_table_dispatch(&eloop.exceptions, efds);
865 #endif /* CONFIG_ELOOP_POLL */
866         }
867
868         eloop.terminate = 0;
869 out:
870 #ifndef CONFIG_ELOOP_POLL
871         os_free(rfds);
872         os_free(wfds);
873         os_free(efds);
874 #endif /* CONFIG_ELOOP_POLL */
875         return;
876 }
877
878
879 void eloop_terminate(void)
880 {
881         eloop.terminate = 1;
882 }
883
884
885 void eloop_destroy(void)
886 {
887         struct eloop_timeout *timeout, *prev;
888         struct os_reltime now;
889
890         os_get_reltime(&now);
891         dl_list_for_each_safe(timeout, prev, &eloop.timeout,
892                               struct eloop_timeout, list) {
893                 int sec, usec;
894                 sec = timeout->time.sec - now.sec;
895                 usec = timeout->time.usec - now.usec;
896                 if (timeout->time.usec < now.usec) {
897                         sec--;
898                         usec += 1000000;
899                 }
900                 wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
901                            "eloop_data=%p user_data=%p handler=%p",
902                            sec, usec, timeout->eloop_data, timeout->user_data,
903                            timeout->handler);
904                 wpa_trace_dump_funcname("eloop unregistered timeout handler",
905                                         timeout->handler);
906                 wpa_trace_dump("eloop timeout", timeout);
907                 eloop_remove_timeout(timeout);
908         }
909         eloop_sock_table_destroy(&eloop.readers);
910         eloop_sock_table_destroy(&eloop.writers);
911         eloop_sock_table_destroy(&eloop.exceptions);
912         os_free(eloop.signals);
913
914 #ifdef CONFIG_ELOOP_POLL
915         os_free(eloop.pollfds);
916         os_free(eloop.pollfds_map);
917 #endif /* CONFIG_ELOOP_POLL */
918 }
919
920
921 int eloop_terminated(void)
922 {
923         return eloop.terminate;
924 }
925
926
927 void eloop_wait_for_read_sock(int sock)
928 {
929 #ifdef CONFIG_ELOOP_POLL
930         struct pollfd pfd;
931
932         if (sock < 0)
933                 return;
934
935         os_memset(&pfd, 0, sizeof(pfd));
936         pfd.fd = sock;
937         pfd.events = POLLIN;
938
939         poll(&pfd, 1, -1);
940 #else /* CONFIG_ELOOP_POLL */
941         fd_set rfds;
942
943         if (sock < 0)
944                 return;
945
946         FD_ZERO(&rfds);
947         FD_SET(sock, &rfds);
948         select(sock + 1, &rfds, NULL, NULL, NULL);
949 #endif /* CONFIG_ELOOP_POLL */
950 }