]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/wpa/src/utils/eloop.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / wpa / 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_time 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_time(&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_time_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_is_timeout_registered(eloop_timeout_handler handler,
560                                 void *eloop_data, void *user_data)
561 {
562         struct eloop_timeout *tmp;
563
564         dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
565                 if (tmp->handler == handler &&
566                     tmp->eloop_data == eloop_data &&
567                     tmp->user_data == user_data)
568                         return 1;
569         }
570
571         return 0;
572 }
573
574
575 #ifndef CONFIG_NATIVE_WINDOWS
576 static void eloop_handle_alarm(int sig)
577 {
578         wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
579                    "two seconds. Looks like there\n"
580                    "is a bug that ends up in a busy loop that "
581                    "prevents clean shutdown.\n"
582                    "Killing program forcefully.\n");
583         exit(1);
584 }
585 #endif /* CONFIG_NATIVE_WINDOWS */
586
587
588 static void eloop_handle_signal(int sig)
589 {
590         int i;
591
592 #ifndef CONFIG_NATIVE_WINDOWS
593         if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
594                 /* Use SIGALRM to break out from potential busy loops that
595                  * would not allow the program to be killed. */
596                 eloop.pending_terminate = 1;
597                 signal(SIGALRM, eloop_handle_alarm);
598                 alarm(2);
599         }
600 #endif /* CONFIG_NATIVE_WINDOWS */
601
602         eloop.signaled++;
603         for (i = 0; i < eloop.signal_count; i++) {
604                 if (eloop.signals[i].sig == sig) {
605                         eloop.signals[i].signaled++;
606                         break;
607                 }
608         }
609 }
610
611
612 static void eloop_process_pending_signals(void)
613 {
614         int i;
615
616         if (eloop.signaled == 0)
617                 return;
618         eloop.signaled = 0;
619
620         if (eloop.pending_terminate) {
621 #ifndef CONFIG_NATIVE_WINDOWS
622                 alarm(0);
623 #endif /* CONFIG_NATIVE_WINDOWS */
624                 eloop.pending_terminate = 0;
625         }
626
627         for (i = 0; i < eloop.signal_count; i++) {
628                 if (eloop.signals[i].signaled) {
629                         eloop.signals[i].signaled = 0;
630                         eloop.signals[i].handler(eloop.signals[i].sig,
631                                                  eloop.signals[i].user_data);
632                 }
633         }
634 }
635
636
637 int eloop_register_signal(int sig, eloop_signal_handler handler,
638                           void *user_data)
639 {
640         struct eloop_signal *tmp;
641
642         tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
643                                sizeof(struct eloop_signal));
644         if (tmp == NULL)
645                 return -1;
646
647         tmp[eloop.signal_count].sig = sig;
648         tmp[eloop.signal_count].user_data = user_data;
649         tmp[eloop.signal_count].handler = handler;
650         tmp[eloop.signal_count].signaled = 0;
651         eloop.signal_count++;
652         eloop.signals = tmp;
653         signal(sig, eloop_handle_signal);
654
655         return 0;
656 }
657
658
659 int eloop_register_signal_terminate(eloop_signal_handler handler,
660                                     void *user_data)
661 {
662         int ret = eloop_register_signal(SIGINT, handler, user_data);
663         if (ret == 0)
664                 ret = eloop_register_signal(SIGTERM, handler, user_data);
665         return ret;
666 }
667
668
669 int eloop_register_signal_reconfig(eloop_signal_handler handler,
670                                    void *user_data)
671 {
672 #ifdef CONFIG_NATIVE_WINDOWS
673         return 0;
674 #else /* CONFIG_NATIVE_WINDOWS */
675         return eloop_register_signal(SIGHUP, handler, user_data);
676 #endif /* CONFIG_NATIVE_WINDOWS */
677 }
678
679
680 void eloop_run(void)
681 {
682 #ifdef CONFIG_ELOOP_POLL
683         int num_poll_fds;
684         int timeout_ms = 0;
685 #else /* CONFIG_ELOOP_POLL */
686         fd_set *rfds, *wfds, *efds;
687         struct timeval _tv;
688 #endif /* CONFIG_ELOOP_POLL */
689         int res;
690         struct os_time tv, now;
691
692 #ifndef CONFIG_ELOOP_POLL
693         rfds = os_malloc(sizeof(*rfds));
694         wfds = os_malloc(sizeof(*wfds));
695         efds = os_malloc(sizeof(*efds));
696         if (rfds == NULL || wfds == NULL || efds == NULL)
697                 goto out;
698 #endif /* CONFIG_ELOOP_POLL */
699
700         while (!eloop.terminate &&
701                (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
702                 eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
703                 struct eloop_timeout *timeout;
704                 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
705                                         list);
706                 if (timeout) {
707                         os_get_time(&now);
708                         if (os_time_before(&now, &timeout->time))
709                                 os_time_sub(&timeout->time, &now, &tv);
710                         else
711                                 tv.sec = tv.usec = 0;
712 #ifdef CONFIG_ELOOP_POLL
713                         timeout_ms = tv.sec * 1000 + tv.usec / 1000;
714 #else /* CONFIG_ELOOP_POLL */
715                         _tv.tv_sec = tv.sec;
716                         _tv.tv_usec = tv.usec;
717 #endif /* CONFIG_ELOOP_POLL */
718                 }
719
720 #ifdef CONFIG_ELOOP_POLL
721                 num_poll_fds = eloop_sock_table_set_fds(
722                         &eloop.readers, &eloop.writers, &eloop.exceptions,
723                         eloop.pollfds, eloop.pollfds_map,
724                         eloop.max_pollfd_map);
725                 res = poll(eloop.pollfds, num_poll_fds,
726                            timeout ? timeout_ms : -1);
727
728                 if (res < 0 && errno != EINTR && errno != 0) {
729                         perror("poll");
730                         goto out;
731                 }
732 #else /* CONFIG_ELOOP_POLL */
733                 eloop_sock_table_set_fds(&eloop.readers, rfds);
734                 eloop_sock_table_set_fds(&eloop.writers, wfds);
735                 eloop_sock_table_set_fds(&eloop.exceptions, efds);
736                 res = select(eloop.max_sock + 1, rfds, wfds, efds,
737                              timeout ? &_tv : NULL);
738                 if (res < 0 && errno != EINTR && errno != 0) {
739                         perror("select");
740                         goto out;
741                 }
742 #endif /* CONFIG_ELOOP_POLL */
743                 eloop_process_pending_signals();
744
745                 /* check if some registered timeouts have occurred */
746                 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
747                                         list);
748                 if (timeout) {
749                         os_get_time(&now);
750                         if (!os_time_before(&now, &timeout->time)) {
751                                 void *eloop_data = timeout->eloop_data;
752                                 void *user_data = timeout->user_data;
753                                 eloop_timeout_handler handler =
754                                         timeout->handler;
755                                 eloop_remove_timeout(timeout);
756                                 handler(eloop_data, user_data);
757                         }
758
759                 }
760
761                 if (res <= 0)
762                         continue;
763
764 #ifdef CONFIG_ELOOP_POLL
765                 eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
766                                           &eloop.exceptions, eloop.pollfds_map,
767                                           eloop.max_pollfd_map);
768 #else /* CONFIG_ELOOP_POLL */
769                 eloop_sock_table_dispatch(&eloop.readers, rfds);
770                 eloop_sock_table_dispatch(&eloop.writers, wfds);
771                 eloop_sock_table_dispatch(&eloop.exceptions, efds);
772 #endif /* CONFIG_ELOOP_POLL */
773         }
774
775 out:
776 #ifndef CONFIG_ELOOP_POLL
777         os_free(rfds);
778         os_free(wfds);
779         os_free(efds);
780 #endif /* CONFIG_ELOOP_POLL */
781         return;
782 }
783
784
785 void eloop_terminate(void)
786 {
787         eloop.terminate = 1;
788 }
789
790
791 void eloop_destroy(void)
792 {
793         struct eloop_timeout *timeout, *prev;
794         struct os_time now;
795
796         os_get_time(&now);
797         dl_list_for_each_safe(timeout, prev, &eloop.timeout,
798                               struct eloop_timeout, list) {
799                 int sec, usec;
800                 sec = timeout->time.sec - now.sec;
801                 usec = timeout->time.usec - now.usec;
802                 if (timeout->time.usec < now.usec) {
803                         sec--;
804                         usec += 1000000;
805                 }
806                 wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
807                            "eloop_data=%p user_data=%p handler=%p",
808                            sec, usec, timeout->eloop_data, timeout->user_data,
809                            timeout->handler);
810                 wpa_trace_dump_funcname("eloop unregistered timeout handler",
811                                         timeout->handler);
812                 wpa_trace_dump("eloop timeout", timeout);
813                 eloop_remove_timeout(timeout);
814         }
815         eloop_sock_table_destroy(&eloop.readers);
816         eloop_sock_table_destroy(&eloop.writers);
817         eloop_sock_table_destroy(&eloop.exceptions);
818         os_free(eloop.signals);
819
820 #ifdef CONFIG_ELOOP_POLL
821         os_free(eloop.pollfds);
822         os_free(eloop.pollfds_map);
823 #endif /* CONFIG_ELOOP_POLL */
824 }
825
826
827 int eloop_terminated(void)
828 {
829         return eloop.terminate;
830 }
831
832
833 void eloop_wait_for_read_sock(int sock)
834 {
835 #ifdef CONFIG_ELOOP_POLL
836         struct pollfd pfd;
837
838         if (sock < 0)
839                 return;
840
841         os_memset(&pfd, 0, sizeof(pfd));
842         pfd.fd = sock;
843         pfd.events = POLLIN;
844
845         poll(&pfd, 1, -1);
846 #else /* CONFIG_ELOOP_POLL */
847         fd_set rfds;
848
849         if (sock < 0)
850                 return;
851
852         FD_ZERO(&rfds);
853         FD_SET(sock, &rfds);
854         select(sock + 1, &rfds, NULL, NULL, NULL);
855 #endif /* CONFIG_ELOOP_POLL */
856 }