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