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