139beb93cSSam Leffler /* 239beb93cSSam Leffler * Event loop based on select() loop 3e28a4053SRui Paulo * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5*f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6*f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 12e28a4053SRui Paulo #include "trace.h" 13e28a4053SRui Paulo #include "list.h" 1439beb93cSSam Leffler #include "eloop.h" 1539beb93cSSam Leffler 16*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 17*f05cddf9SRui Paulo #include <assert.h> 18*f05cddf9SRui Paulo #include <poll.h> 19*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 20*f05cddf9SRui Paulo 2139beb93cSSam Leffler 2239beb93cSSam Leffler struct eloop_sock { 2339beb93cSSam Leffler int sock; 2439beb93cSSam Leffler void *eloop_data; 2539beb93cSSam Leffler void *user_data; 2639beb93cSSam Leffler eloop_sock_handler handler; 27e28a4053SRui Paulo WPA_TRACE_REF(eloop); 28e28a4053SRui Paulo WPA_TRACE_REF(user); 29e28a4053SRui Paulo WPA_TRACE_INFO 3039beb93cSSam Leffler }; 3139beb93cSSam Leffler 3239beb93cSSam Leffler struct eloop_timeout { 33e28a4053SRui Paulo struct dl_list list; 3439beb93cSSam Leffler struct os_time time; 3539beb93cSSam Leffler void *eloop_data; 3639beb93cSSam Leffler void *user_data; 3739beb93cSSam Leffler eloop_timeout_handler handler; 38e28a4053SRui Paulo WPA_TRACE_REF(eloop); 39e28a4053SRui Paulo WPA_TRACE_REF(user); 40e28a4053SRui Paulo WPA_TRACE_INFO 4139beb93cSSam Leffler }; 4239beb93cSSam Leffler 4339beb93cSSam Leffler struct eloop_signal { 4439beb93cSSam Leffler int sig; 4539beb93cSSam Leffler void *user_data; 4639beb93cSSam Leffler eloop_signal_handler handler; 4739beb93cSSam Leffler int signaled; 4839beb93cSSam Leffler }; 4939beb93cSSam Leffler 5039beb93cSSam Leffler struct eloop_sock_table { 5139beb93cSSam Leffler int count; 5239beb93cSSam Leffler struct eloop_sock *table; 5339beb93cSSam Leffler int changed; 5439beb93cSSam Leffler }; 5539beb93cSSam Leffler 5639beb93cSSam Leffler struct eloop_data { 5739beb93cSSam Leffler int max_sock; 5839beb93cSSam Leffler 59*f05cddf9SRui Paulo int count; /* sum of all table counts */ 60*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 61*f05cddf9SRui Paulo int max_pollfd_map; /* number of pollfds_map currently allocated */ 62*f05cddf9SRui Paulo int max_poll_fds; /* number of pollfds currently allocated */ 63*f05cddf9SRui Paulo struct pollfd *pollfds; 64*f05cddf9SRui Paulo struct pollfd **pollfds_map; 65*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 6639beb93cSSam Leffler struct eloop_sock_table readers; 6739beb93cSSam Leffler struct eloop_sock_table writers; 6839beb93cSSam Leffler struct eloop_sock_table exceptions; 6939beb93cSSam Leffler 70e28a4053SRui Paulo struct dl_list timeout; 7139beb93cSSam Leffler 7239beb93cSSam Leffler int signal_count; 7339beb93cSSam Leffler struct eloop_signal *signals; 7439beb93cSSam Leffler int signaled; 7539beb93cSSam Leffler int pending_terminate; 7639beb93cSSam Leffler 7739beb93cSSam Leffler int terminate; 7839beb93cSSam Leffler int reader_table_changed; 7939beb93cSSam Leffler }; 8039beb93cSSam Leffler 8139beb93cSSam Leffler static struct eloop_data eloop; 8239beb93cSSam Leffler 8339beb93cSSam Leffler 84e28a4053SRui Paulo #ifdef WPA_TRACE 85e28a4053SRui Paulo 86e28a4053SRui Paulo static void eloop_sigsegv_handler(int sig) 87e28a4053SRui Paulo { 88e28a4053SRui Paulo wpa_trace_show("eloop SIGSEGV"); 89e28a4053SRui Paulo abort(); 90e28a4053SRui Paulo } 91e28a4053SRui Paulo 92e28a4053SRui Paulo static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) 93e28a4053SRui Paulo { 94e28a4053SRui Paulo int i; 95e28a4053SRui Paulo if (table == NULL || table->table == NULL) 96e28a4053SRui Paulo return; 97e28a4053SRui Paulo for (i = 0; i < table->count; i++) { 98e28a4053SRui Paulo wpa_trace_add_ref(&table->table[i], eloop, 99e28a4053SRui Paulo table->table[i].eloop_data); 100e28a4053SRui Paulo wpa_trace_add_ref(&table->table[i], user, 101e28a4053SRui Paulo table->table[i].user_data); 102e28a4053SRui Paulo } 103e28a4053SRui Paulo } 104e28a4053SRui Paulo 105e28a4053SRui Paulo 106e28a4053SRui Paulo static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) 107e28a4053SRui Paulo { 108e28a4053SRui Paulo int i; 109e28a4053SRui Paulo if (table == NULL || table->table == NULL) 110e28a4053SRui Paulo return; 111e28a4053SRui Paulo for (i = 0; i < table->count; i++) { 112e28a4053SRui Paulo wpa_trace_remove_ref(&table->table[i], eloop, 113e28a4053SRui Paulo table->table[i].eloop_data); 114e28a4053SRui Paulo wpa_trace_remove_ref(&table->table[i], user, 115e28a4053SRui Paulo table->table[i].user_data); 116e28a4053SRui Paulo } 117e28a4053SRui Paulo } 118e28a4053SRui Paulo 119e28a4053SRui Paulo #else /* WPA_TRACE */ 120e28a4053SRui Paulo 121e28a4053SRui Paulo #define eloop_trace_sock_add_ref(table) do { } while (0) 122e28a4053SRui Paulo #define eloop_trace_sock_remove_ref(table) do { } while (0) 123e28a4053SRui Paulo 124e28a4053SRui Paulo #endif /* WPA_TRACE */ 125e28a4053SRui Paulo 126e28a4053SRui Paulo 127e28a4053SRui Paulo int eloop_init(void) 12839beb93cSSam Leffler { 12939beb93cSSam Leffler os_memset(&eloop, 0, sizeof(eloop)); 130e28a4053SRui Paulo dl_list_init(&eloop.timeout); 131e28a4053SRui Paulo #ifdef WPA_TRACE 132e28a4053SRui Paulo signal(SIGSEGV, eloop_sigsegv_handler); 133e28a4053SRui Paulo #endif /* WPA_TRACE */ 13439beb93cSSam Leffler return 0; 13539beb93cSSam Leffler } 13639beb93cSSam Leffler 13739beb93cSSam Leffler 13839beb93cSSam Leffler static int eloop_sock_table_add_sock(struct eloop_sock_table *table, 13939beb93cSSam Leffler int sock, eloop_sock_handler handler, 14039beb93cSSam Leffler void *eloop_data, void *user_data) 14139beb93cSSam Leffler { 14239beb93cSSam Leffler struct eloop_sock *tmp; 143*f05cddf9SRui Paulo int new_max_sock; 144*f05cddf9SRui Paulo 145*f05cddf9SRui Paulo if (sock > eloop.max_sock) 146*f05cddf9SRui Paulo new_max_sock = sock; 147*f05cddf9SRui Paulo else 148*f05cddf9SRui Paulo new_max_sock = eloop.max_sock; 14939beb93cSSam Leffler 15039beb93cSSam Leffler if (table == NULL) 15139beb93cSSam Leffler return -1; 15239beb93cSSam Leffler 153*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 154*f05cddf9SRui Paulo if (new_max_sock >= eloop.max_pollfd_map) { 155*f05cddf9SRui Paulo struct pollfd **nmap; 156*f05cddf9SRui Paulo nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50, 157*f05cddf9SRui Paulo sizeof(struct pollfd *)); 158*f05cddf9SRui Paulo if (nmap == NULL) 159*f05cddf9SRui Paulo return -1; 160*f05cddf9SRui Paulo 161*f05cddf9SRui Paulo eloop.max_pollfd_map = new_max_sock + 50; 162*f05cddf9SRui Paulo eloop.pollfds_map = nmap; 163*f05cddf9SRui Paulo } 164*f05cddf9SRui Paulo 165*f05cddf9SRui Paulo if (eloop.count + 1 > eloop.max_poll_fds) { 166*f05cddf9SRui Paulo struct pollfd *n; 167*f05cddf9SRui Paulo int nmax = eloop.count + 1 + 50; 168*f05cddf9SRui Paulo n = os_realloc_array(eloop.pollfds, nmax, 169*f05cddf9SRui Paulo sizeof(struct pollfd)); 170*f05cddf9SRui Paulo if (n == NULL) 171*f05cddf9SRui Paulo return -1; 172*f05cddf9SRui Paulo 173*f05cddf9SRui Paulo eloop.max_poll_fds = nmax; 174*f05cddf9SRui Paulo eloop.pollfds = n; 175*f05cddf9SRui Paulo } 176*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 177*f05cddf9SRui Paulo 178e28a4053SRui Paulo eloop_trace_sock_remove_ref(table); 179*f05cddf9SRui Paulo tmp = os_realloc_array(table->table, table->count + 1, 180*f05cddf9SRui Paulo sizeof(struct eloop_sock)); 18139beb93cSSam Leffler if (tmp == NULL) 18239beb93cSSam Leffler return -1; 18339beb93cSSam Leffler 18439beb93cSSam Leffler tmp[table->count].sock = sock; 18539beb93cSSam Leffler tmp[table->count].eloop_data = eloop_data; 18639beb93cSSam Leffler tmp[table->count].user_data = user_data; 18739beb93cSSam Leffler tmp[table->count].handler = handler; 188e28a4053SRui Paulo wpa_trace_record(&tmp[table->count]); 18939beb93cSSam Leffler table->count++; 19039beb93cSSam Leffler table->table = tmp; 191*f05cddf9SRui Paulo eloop.max_sock = new_max_sock; 192*f05cddf9SRui Paulo eloop.count++; 19339beb93cSSam Leffler table->changed = 1; 194e28a4053SRui Paulo eloop_trace_sock_add_ref(table); 19539beb93cSSam Leffler 19639beb93cSSam Leffler return 0; 19739beb93cSSam Leffler } 19839beb93cSSam Leffler 19939beb93cSSam Leffler 20039beb93cSSam Leffler static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, 20139beb93cSSam Leffler int sock) 20239beb93cSSam Leffler { 20339beb93cSSam Leffler int i; 20439beb93cSSam Leffler 20539beb93cSSam Leffler if (table == NULL || table->table == NULL || table->count == 0) 20639beb93cSSam Leffler return; 20739beb93cSSam Leffler 20839beb93cSSam Leffler for (i = 0; i < table->count; i++) { 20939beb93cSSam Leffler if (table->table[i].sock == sock) 21039beb93cSSam Leffler break; 21139beb93cSSam Leffler } 21239beb93cSSam Leffler if (i == table->count) 21339beb93cSSam Leffler return; 214e28a4053SRui Paulo eloop_trace_sock_remove_ref(table); 21539beb93cSSam Leffler if (i != table->count - 1) { 21639beb93cSSam Leffler os_memmove(&table->table[i], &table->table[i + 1], 21739beb93cSSam Leffler (table->count - i - 1) * 21839beb93cSSam Leffler sizeof(struct eloop_sock)); 21939beb93cSSam Leffler } 22039beb93cSSam Leffler table->count--; 221*f05cddf9SRui Paulo eloop.count--; 22239beb93cSSam Leffler table->changed = 1; 223e28a4053SRui Paulo eloop_trace_sock_add_ref(table); 22439beb93cSSam Leffler } 22539beb93cSSam Leffler 22639beb93cSSam Leffler 227*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 228*f05cddf9SRui Paulo 229*f05cddf9SRui Paulo static struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx) 230*f05cddf9SRui Paulo { 231*f05cddf9SRui Paulo if (fd < mx && fd >= 0) 232*f05cddf9SRui Paulo return pollfds_map[fd]; 233*f05cddf9SRui Paulo return NULL; 234*f05cddf9SRui Paulo } 235*f05cddf9SRui Paulo 236*f05cddf9SRui Paulo 237*f05cddf9SRui Paulo static int eloop_sock_table_set_fds(struct eloop_sock_table *readers, 238*f05cddf9SRui Paulo struct eloop_sock_table *writers, 239*f05cddf9SRui Paulo struct eloop_sock_table *exceptions, 240*f05cddf9SRui Paulo struct pollfd *pollfds, 241*f05cddf9SRui Paulo struct pollfd **pollfds_map, 242*f05cddf9SRui Paulo int max_pollfd_map) 243*f05cddf9SRui Paulo { 244*f05cddf9SRui Paulo int i; 245*f05cddf9SRui Paulo int nxt = 0; 246*f05cddf9SRui Paulo int fd; 247*f05cddf9SRui Paulo struct pollfd *pfd; 248*f05cddf9SRui Paulo 249*f05cddf9SRui Paulo /* Clear pollfd lookup map. It will be re-populated below. */ 250*f05cddf9SRui Paulo os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map); 251*f05cddf9SRui Paulo 252*f05cddf9SRui Paulo if (readers && readers->table) { 253*f05cddf9SRui Paulo for (i = 0; i < readers->count; i++) { 254*f05cddf9SRui Paulo fd = readers->table[i].sock; 255*f05cddf9SRui Paulo assert(fd >= 0 && fd < max_pollfd_map); 256*f05cddf9SRui Paulo pollfds[nxt].fd = fd; 257*f05cddf9SRui Paulo pollfds[nxt].events = POLLIN; 258*f05cddf9SRui Paulo pollfds[nxt].revents = 0; 259*f05cddf9SRui Paulo pollfds_map[fd] = &(pollfds[nxt]); 260*f05cddf9SRui Paulo nxt++; 261*f05cddf9SRui Paulo } 262*f05cddf9SRui Paulo } 263*f05cddf9SRui Paulo 264*f05cddf9SRui Paulo if (writers && writers->table) { 265*f05cddf9SRui Paulo for (i = 0; i < writers->count; i++) { 266*f05cddf9SRui Paulo /* 267*f05cddf9SRui Paulo * See if we already added this descriptor, update it 268*f05cddf9SRui Paulo * if so. 269*f05cddf9SRui Paulo */ 270*f05cddf9SRui Paulo fd = writers->table[i].sock; 271*f05cddf9SRui Paulo assert(fd >= 0 && fd < max_pollfd_map); 272*f05cddf9SRui Paulo pfd = pollfds_map[fd]; 273*f05cddf9SRui Paulo if (!pfd) { 274*f05cddf9SRui Paulo pfd = &(pollfds[nxt]); 275*f05cddf9SRui Paulo pfd->events = 0; 276*f05cddf9SRui Paulo pfd->fd = fd; 277*f05cddf9SRui Paulo pollfds[i].revents = 0; 278*f05cddf9SRui Paulo pollfds_map[fd] = pfd; 279*f05cddf9SRui Paulo nxt++; 280*f05cddf9SRui Paulo } 281*f05cddf9SRui Paulo pfd->events |= POLLOUT; 282*f05cddf9SRui Paulo } 283*f05cddf9SRui Paulo } 284*f05cddf9SRui Paulo 285*f05cddf9SRui Paulo /* 286*f05cddf9SRui Paulo * Exceptions are always checked when using poll, but I suppose it's 287*f05cddf9SRui Paulo * possible that someone registered a socket *only* for exception 288*f05cddf9SRui Paulo * handling. Set the POLLIN bit in this case. 289*f05cddf9SRui Paulo */ 290*f05cddf9SRui Paulo if (exceptions && exceptions->table) { 291*f05cddf9SRui Paulo for (i = 0; i < exceptions->count; i++) { 292*f05cddf9SRui Paulo /* 293*f05cddf9SRui Paulo * See if we already added this descriptor, just use it 294*f05cddf9SRui Paulo * if so. 295*f05cddf9SRui Paulo */ 296*f05cddf9SRui Paulo fd = exceptions->table[i].sock; 297*f05cddf9SRui Paulo assert(fd >= 0 && fd < max_pollfd_map); 298*f05cddf9SRui Paulo pfd = pollfds_map[fd]; 299*f05cddf9SRui Paulo if (!pfd) { 300*f05cddf9SRui Paulo pfd = &(pollfds[nxt]); 301*f05cddf9SRui Paulo pfd->events = POLLIN; 302*f05cddf9SRui Paulo pfd->fd = fd; 303*f05cddf9SRui Paulo pollfds[i].revents = 0; 304*f05cddf9SRui Paulo pollfds_map[fd] = pfd; 305*f05cddf9SRui Paulo nxt++; 306*f05cddf9SRui Paulo } 307*f05cddf9SRui Paulo } 308*f05cddf9SRui Paulo } 309*f05cddf9SRui Paulo 310*f05cddf9SRui Paulo return nxt; 311*f05cddf9SRui Paulo } 312*f05cddf9SRui Paulo 313*f05cddf9SRui Paulo 314*f05cddf9SRui Paulo static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table, 315*f05cddf9SRui Paulo struct pollfd **pollfds_map, 316*f05cddf9SRui Paulo int max_pollfd_map, 317*f05cddf9SRui Paulo short int revents) 318*f05cddf9SRui Paulo { 319*f05cddf9SRui Paulo int i; 320*f05cddf9SRui Paulo struct pollfd *pfd; 321*f05cddf9SRui Paulo 322*f05cddf9SRui Paulo if (!table || !table->table) 323*f05cddf9SRui Paulo return 0; 324*f05cddf9SRui Paulo 325*f05cddf9SRui Paulo table->changed = 0; 326*f05cddf9SRui Paulo for (i = 0; i < table->count; i++) { 327*f05cddf9SRui Paulo pfd = find_pollfd(pollfds_map, table->table[i].sock, 328*f05cddf9SRui Paulo max_pollfd_map); 329*f05cddf9SRui Paulo if (!pfd) 330*f05cddf9SRui Paulo continue; 331*f05cddf9SRui Paulo 332*f05cddf9SRui Paulo if (!(pfd->revents & revents)) 333*f05cddf9SRui Paulo continue; 334*f05cddf9SRui Paulo 335*f05cddf9SRui Paulo table->table[i].handler(table->table[i].sock, 336*f05cddf9SRui Paulo table->table[i].eloop_data, 337*f05cddf9SRui Paulo table->table[i].user_data); 338*f05cddf9SRui Paulo if (table->changed) 339*f05cddf9SRui Paulo return 1; 340*f05cddf9SRui Paulo } 341*f05cddf9SRui Paulo 342*f05cddf9SRui Paulo return 0; 343*f05cddf9SRui Paulo } 344*f05cddf9SRui Paulo 345*f05cddf9SRui Paulo 346*f05cddf9SRui Paulo static void eloop_sock_table_dispatch(struct eloop_sock_table *readers, 347*f05cddf9SRui Paulo struct eloop_sock_table *writers, 348*f05cddf9SRui Paulo struct eloop_sock_table *exceptions, 349*f05cddf9SRui Paulo struct pollfd **pollfds_map, 350*f05cddf9SRui Paulo int max_pollfd_map) 351*f05cddf9SRui Paulo { 352*f05cddf9SRui Paulo if (eloop_sock_table_dispatch_table(readers, pollfds_map, 353*f05cddf9SRui Paulo max_pollfd_map, POLLIN | POLLERR | 354*f05cddf9SRui Paulo POLLHUP)) 355*f05cddf9SRui Paulo return; /* pollfds may be invalid at this point */ 356*f05cddf9SRui Paulo 357*f05cddf9SRui Paulo if (eloop_sock_table_dispatch_table(writers, pollfds_map, 358*f05cddf9SRui Paulo max_pollfd_map, POLLOUT)) 359*f05cddf9SRui Paulo return; /* pollfds may be invalid at this point */ 360*f05cddf9SRui Paulo 361*f05cddf9SRui Paulo eloop_sock_table_dispatch_table(exceptions, pollfds_map, 362*f05cddf9SRui Paulo max_pollfd_map, POLLERR | POLLHUP); 363*f05cddf9SRui Paulo } 364*f05cddf9SRui Paulo 365*f05cddf9SRui Paulo #else /* CONFIG_ELOOP_POLL */ 366*f05cddf9SRui Paulo 36739beb93cSSam Leffler static void eloop_sock_table_set_fds(struct eloop_sock_table *table, 36839beb93cSSam Leffler fd_set *fds) 36939beb93cSSam Leffler { 37039beb93cSSam Leffler int i; 37139beb93cSSam Leffler 37239beb93cSSam Leffler FD_ZERO(fds); 37339beb93cSSam Leffler 37439beb93cSSam Leffler if (table->table == NULL) 37539beb93cSSam Leffler return; 37639beb93cSSam Leffler 37739beb93cSSam Leffler for (i = 0; i < table->count; i++) 37839beb93cSSam Leffler FD_SET(table->table[i].sock, fds); 37939beb93cSSam Leffler } 38039beb93cSSam Leffler 38139beb93cSSam Leffler 38239beb93cSSam Leffler static void eloop_sock_table_dispatch(struct eloop_sock_table *table, 38339beb93cSSam Leffler fd_set *fds) 38439beb93cSSam Leffler { 38539beb93cSSam Leffler int i; 38639beb93cSSam Leffler 38739beb93cSSam Leffler if (table == NULL || table->table == NULL) 38839beb93cSSam Leffler return; 38939beb93cSSam Leffler 39039beb93cSSam Leffler table->changed = 0; 39139beb93cSSam Leffler for (i = 0; i < table->count; i++) { 39239beb93cSSam Leffler if (FD_ISSET(table->table[i].sock, fds)) { 39339beb93cSSam Leffler table->table[i].handler(table->table[i].sock, 39439beb93cSSam Leffler table->table[i].eloop_data, 39539beb93cSSam Leffler table->table[i].user_data); 39639beb93cSSam Leffler if (table->changed) 39739beb93cSSam Leffler break; 39839beb93cSSam Leffler } 39939beb93cSSam Leffler } 40039beb93cSSam Leffler } 40139beb93cSSam Leffler 402*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 403*f05cddf9SRui Paulo 40439beb93cSSam Leffler 40539beb93cSSam Leffler static void eloop_sock_table_destroy(struct eloop_sock_table *table) 40639beb93cSSam Leffler { 40739beb93cSSam Leffler if (table) { 40839beb93cSSam Leffler int i; 40939beb93cSSam Leffler for (i = 0; i < table->count && table->table; i++) { 410e28a4053SRui Paulo wpa_printf(MSG_INFO, "ELOOP: remaining socket: " 411e28a4053SRui Paulo "sock=%d eloop_data=%p user_data=%p " 412e28a4053SRui Paulo "handler=%p", 41339beb93cSSam Leffler table->table[i].sock, 41439beb93cSSam Leffler table->table[i].eloop_data, 41539beb93cSSam Leffler table->table[i].user_data, 41639beb93cSSam Leffler table->table[i].handler); 417e28a4053SRui Paulo wpa_trace_dump_funcname("eloop unregistered socket " 418e28a4053SRui Paulo "handler", 419e28a4053SRui Paulo table->table[i].handler); 420e28a4053SRui Paulo wpa_trace_dump("eloop sock", &table->table[i]); 42139beb93cSSam Leffler } 42239beb93cSSam Leffler os_free(table->table); 42339beb93cSSam Leffler } 42439beb93cSSam Leffler } 42539beb93cSSam Leffler 42639beb93cSSam Leffler 42739beb93cSSam Leffler int eloop_register_read_sock(int sock, eloop_sock_handler handler, 42839beb93cSSam Leffler void *eloop_data, void *user_data) 42939beb93cSSam Leffler { 43039beb93cSSam Leffler return eloop_register_sock(sock, EVENT_TYPE_READ, handler, 43139beb93cSSam Leffler eloop_data, user_data); 43239beb93cSSam Leffler } 43339beb93cSSam Leffler 43439beb93cSSam Leffler 43539beb93cSSam Leffler void eloop_unregister_read_sock(int sock) 43639beb93cSSam Leffler { 43739beb93cSSam Leffler eloop_unregister_sock(sock, EVENT_TYPE_READ); 43839beb93cSSam Leffler } 43939beb93cSSam Leffler 44039beb93cSSam Leffler 44139beb93cSSam Leffler static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) 44239beb93cSSam Leffler { 44339beb93cSSam Leffler switch (type) { 44439beb93cSSam Leffler case EVENT_TYPE_READ: 44539beb93cSSam Leffler return &eloop.readers; 44639beb93cSSam Leffler case EVENT_TYPE_WRITE: 44739beb93cSSam Leffler return &eloop.writers; 44839beb93cSSam Leffler case EVENT_TYPE_EXCEPTION: 44939beb93cSSam Leffler return &eloop.exceptions; 45039beb93cSSam Leffler } 45139beb93cSSam Leffler 45239beb93cSSam Leffler return NULL; 45339beb93cSSam Leffler } 45439beb93cSSam Leffler 45539beb93cSSam Leffler 45639beb93cSSam Leffler int eloop_register_sock(int sock, eloop_event_type type, 45739beb93cSSam Leffler eloop_sock_handler handler, 45839beb93cSSam Leffler void *eloop_data, void *user_data) 45939beb93cSSam Leffler { 46039beb93cSSam Leffler struct eloop_sock_table *table; 46139beb93cSSam Leffler 46239beb93cSSam Leffler table = eloop_get_sock_table(type); 46339beb93cSSam Leffler return eloop_sock_table_add_sock(table, sock, handler, 46439beb93cSSam Leffler eloop_data, user_data); 46539beb93cSSam Leffler } 46639beb93cSSam Leffler 46739beb93cSSam Leffler 46839beb93cSSam Leffler void eloop_unregister_sock(int sock, eloop_event_type type) 46939beb93cSSam Leffler { 47039beb93cSSam Leffler struct eloop_sock_table *table; 47139beb93cSSam Leffler 47239beb93cSSam Leffler table = eloop_get_sock_table(type); 47339beb93cSSam Leffler eloop_sock_table_remove_sock(table, sock); 47439beb93cSSam Leffler } 47539beb93cSSam Leffler 47639beb93cSSam Leffler 47739beb93cSSam Leffler int eloop_register_timeout(unsigned int secs, unsigned int usecs, 47839beb93cSSam Leffler eloop_timeout_handler handler, 47939beb93cSSam Leffler void *eloop_data, void *user_data) 48039beb93cSSam Leffler { 481e28a4053SRui Paulo struct eloop_timeout *timeout, *tmp; 482*f05cddf9SRui Paulo os_time_t now_sec; 48339beb93cSSam Leffler 484e28a4053SRui Paulo timeout = os_zalloc(sizeof(*timeout)); 48539beb93cSSam Leffler if (timeout == NULL) 48639beb93cSSam Leffler return -1; 48739beb93cSSam Leffler if (os_get_time(&timeout->time) < 0) { 48839beb93cSSam Leffler os_free(timeout); 48939beb93cSSam Leffler return -1; 49039beb93cSSam Leffler } 491*f05cddf9SRui Paulo now_sec = timeout->time.sec; 49239beb93cSSam Leffler timeout->time.sec += secs; 493*f05cddf9SRui Paulo if (timeout->time.sec < now_sec) { 494*f05cddf9SRui Paulo /* 495*f05cddf9SRui Paulo * Integer overflow - assume long enough timeout to be assumed 496*f05cddf9SRui Paulo * to be infinite, i.e., the timeout would never happen. 497*f05cddf9SRui Paulo */ 498*f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " 499*f05cddf9SRui Paulo "ever happen - ignore it", secs); 500*f05cddf9SRui Paulo os_free(timeout); 501*f05cddf9SRui Paulo return 0; 502*f05cddf9SRui Paulo } 50339beb93cSSam Leffler timeout->time.usec += usecs; 50439beb93cSSam Leffler while (timeout->time.usec >= 1000000) { 50539beb93cSSam Leffler timeout->time.sec++; 50639beb93cSSam Leffler timeout->time.usec -= 1000000; 50739beb93cSSam Leffler } 50839beb93cSSam Leffler timeout->eloop_data = eloop_data; 50939beb93cSSam Leffler timeout->user_data = user_data; 51039beb93cSSam Leffler timeout->handler = handler; 511e28a4053SRui Paulo wpa_trace_add_ref(timeout, eloop, eloop_data); 512e28a4053SRui Paulo wpa_trace_add_ref(timeout, user, user_data); 513e28a4053SRui Paulo wpa_trace_record(timeout); 51439beb93cSSam Leffler 515e28a4053SRui Paulo /* Maintain timeouts in order of increasing time */ 516e28a4053SRui Paulo dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 517e28a4053SRui Paulo if (os_time_before(&timeout->time, &tmp->time)) { 518e28a4053SRui Paulo dl_list_add(tmp->list.prev, &timeout->list); 519e28a4053SRui Paulo return 0; 520e28a4053SRui Paulo } 521e28a4053SRui Paulo } 522e28a4053SRui Paulo dl_list_add_tail(&eloop.timeout, &timeout->list); 523e28a4053SRui Paulo 52439beb93cSSam Leffler return 0; 52539beb93cSSam Leffler } 52639beb93cSSam Leffler 52739beb93cSSam Leffler 528e28a4053SRui Paulo static void eloop_remove_timeout(struct eloop_timeout *timeout) 529e28a4053SRui Paulo { 530e28a4053SRui Paulo dl_list_del(&timeout->list); 531e28a4053SRui Paulo wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data); 532e28a4053SRui Paulo wpa_trace_remove_ref(timeout, user, timeout->user_data); 533e28a4053SRui Paulo os_free(timeout); 53439beb93cSSam Leffler } 53539beb93cSSam Leffler 53639beb93cSSam Leffler 53739beb93cSSam Leffler int eloop_cancel_timeout(eloop_timeout_handler handler, 53839beb93cSSam Leffler void *eloop_data, void *user_data) 53939beb93cSSam Leffler { 540e28a4053SRui Paulo struct eloop_timeout *timeout, *prev; 54139beb93cSSam Leffler int removed = 0; 54239beb93cSSam Leffler 543e28a4053SRui Paulo dl_list_for_each_safe(timeout, prev, &eloop.timeout, 544e28a4053SRui Paulo struct eloop_timeout, list) { 54539beb93cSSam Leffler if (timeout->handler == handler && 54639beb93cSSam Leffler (timeout->eloop_data == eloop_data || 54739beb93cSSam Leffler eloop_data == ELOOP_ALL_CTX) && 54839beb93cSSam Leffler (timeout->user_data == user_data || 54939beb93cSSam Leffler user_data == ELOOP_ALL_CTX)) { 550e28a4053SRui Paulo eloop_remove_timeout(timeout); 55139beb93cSSam Leffler removed++; 552e28a4053SRui Paulo } 55339beb93cSSam Leffler } 55439beb93cSSam Leffler 55539beb93cSSam Leffler return removed; 55639beb93cSSam Leffler } 55739beb93cSSam Leffler 55839beb93cSSam Leffler 55939beb93cSSam Leffler int eloop_is_timeout_registered(eloop_timeout_handler handler, 56039beb93cSSam Leffler void *eloop_data, void *user_data) 56139beb93cSSam Leffler { 56239beb93cSSam Leffler struct eloop_timeout *tmp; 56339beb93cSSam Leffler 564e28a4053SRui Paulo dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 56539beb93cSSam Leffler if (tmp->handler == handler && 56639beb93cSSam Leffler tmp->eloop_data == eloop_data && 56739beb93cSSam Leffler tmp->user_data == user_data) 56839beb93cSSam Leffler return 1; 56939beb93cSSam Leffler } 57039beb93cSSam Leffler 57139beb93cSSam Leffler return 0; 57239beb93cSSam Leffler } 57339beb93cSSam Leffler 57439beb93cSSam Leffler 57539beb93cSSam Leffler #ifndef CONFIG_NATIVE_WINDOWS 57639beb93cSSam Leffler static void eloop_handle_alarm(int sig) 57739beb93cSSam Leffler { 578e28a4053SRui Paulo wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " 579e28a4053SRui Paulo "two seconds. Looks like there\n" 58039beb93cSSam Leffler "is a bug that ends up in a busy loop that " 58139beb93cSSam Leffler "prevents clean shutdown.\n" 58239beb93cSSam Leffler "Killing program forcefully.\n"); 58339beb93cSSam Leffler exit(1); 58439beb93cSSam Leffler } 58539beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */ 58639beb93cSSam Leffler 58739beb93cSSam Leffler 58839beb93cSSam Leffler static void eloop_handle_signal(int sig) 58939beb93cSSam Leffler { 59039beb93cSSam Leffler int i; 59139beb93cSSam Leffler 59239beb93cSSam Leffler #ifndef CONFIG_NATIVE_WINDOWS 59339beb93cSSam Leffler if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { 59439beb93cSSam Leffler /* Use SIGALRM to break out from potential busy loops that 59539beb93cSSam Leffler * would not allow the program to be killed. */ 59639beb93cSSam Leffler eloop.pending_terminate = 1; 59739beb93cSSam Leffler signal(SIGALRM, eloop_handle_alarm); 59839beb93cSSam Leffler alarm(2); 59939beb93cSSam Leffler } 60039beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */ 60139beb93cSSam Leffler 60239beb93cSSam Leffler eloop.signaled++; 60339beb93cSSam Leffler for (i = 0; i < eloop.signal_count; i++) { 60439beb93cSSam Leffler if (eloop.signals[i].sig == sig) { 60539beb93cSSam Leffler eloop.signals[i].signaled++; 60639beb93cSSam Leffler break; 60739beb93cSSam Leffler } 60839beb93cSSam Leffler } 60939beb93cSSam Leffler } 61039beb93cSSam Leffler 61139beb93cSSam Leffler 61239beb93cSSam Leffler static void eloop_process_pending_signals(void) 61339beb93cSSam Leffler { 61439beb93cSSam Leffler int i; 61539beb93cSSam Leffler 61639beb93cSSam Leffler if (eloop.signaled == 0) 61739beb93cSSam Leffler return; 61839beb93cSSam Leffler eloop.signaled = 0; 61939beb93cSSam Leffler 62039beb93cSSam Leffler if (eloop.pending_terminate) { 62139beb93cSSam Leffler #ifndef CONFIG_NATIVE_WINDOWS 62239beb93cSSam Leffler alarm(0); 62339beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */ 62439beb93cSSam Leffler eloop.pending_terminate = 0; 62539beb93cSSam Leffler } 62639beb93cSSam Leffler 62739beb93cSSam Leffler for (i = 0; i < eloop.signal_count; i++) { 62839beb93cSSam Leffler if (eloop.signals[i].signaled) { 62939beb93cSSam Leffler eloop.signals[i].signaled = 0; 63039beb93cSSam Leffler eloop.signals[i].handler(eloop.signals[i].sig, 63139beb93cSSam Leffler eloop.signals[i].user_data); 63239beb93cSSam Leffler } 63339beb93cSSam Leffler } 63439beb93cSSam Leffler } 63539beb93cSSam Leffler 63639beb93cSSam Leffler 63739beb93cSSam Leffler int eloop_register_signal(int sig, eloop_signal_handler handler, 63839beb93cSSam Leffler void *user_data) 63939beb93cSSam Leffler { 64039beb93cSSam Leffler struct eloop_signal *tmp; 64139beb93cSSam Leffler 642*f05cddf9SRui Paulo tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 64339beb93cSSam Leffler sizeof(struct eloop_signal)); 64439beb93cSSam Leffler if (tmp == NULL) 64539beb93cSSam Leffler return -1; 64639beb93cSSam Leffler 64739beb93cSSam Leffler tmp[eloop.signal_count].sig = sig; 64839beb93cSSam Leffler tmp[eloop.signal_count].user_data = user_data; 64939beb93cSSam Leffler tmp[eloop.signal_count].handler = handler; 65039beb93cSSam Leffler tmp[eloop.signal_count].signaled = 0; 65139beb93cSSam Leffler eloop.signal_count++; 65239beb93cSSam Leffler eloop.signals = tmp; 65339beb93cSSam Leffler signal(sig, eloop_handle_signal); 65439beb93cSSam Leffler 65539beb93cSSam Leffler return 0; 65639beb93cSSam Leffler } 65739beb93cSSam Leffler 65839beb93cSSam Leffler 65939beb93cSSam Leffler int eloop_register_signal_terminate(eloop_signal_handler handler, 66039beb93cSSam Leffler void *user_data) 66139beb93cSSam Leffler { 66239beb93cSSam Leffler int ret = eloop_register_signal(SIGINT, handler, user_data); 66339beb93cSSam Leffler if (ret == 0) 66439beb93cSSam Leffler ret = eloop_register_signal(SIGTERM, handler, user_data); 66539beb93cSSam Leffler return ret; 66639beb93cSSam Leffler } 66739beb93cSSam Leffler 66839beb93cSSam Leffler 66939beb93cSSam Leffler int eloop_register_signal_reconfig(eloop_signal_handler handler, 67039beb93cSSam Leffler void *user_data) 67139beb93cSSam Leffler { 67239beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS 67339beb93cSSam Leffler return 0; 67439beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS */ 67539beb93cSSam Leffler return eloop_register_signal(SIGHUP, handler, user_data); 67639beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */ 67739beb93cSSam Leffler } 67839beb93cSSam Leffler 67939beb93cSSam Leffler 68039beb93cSSam Leffler void eloop_run(void) 68139beb93cSSam Leffler { 682*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 683*f05cddf9SRui Paulo int num_poll_fds; 684*f05cddf9SRui Paulo int timeout_ms = 0; 685*f05cddf9SRui Paulo #else /* CONFIG_ELOOP_POLL */ 68639beb93cSSam Leffler fd_set *rfds, *wfds, *efds; 68739beb93cSSam Leffler struct timeval _tv; 688*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 689*f05cddf9SRui Paulo int res; 69039beb93cSSam Leffler struct os_time tv, now; 69139beb93cSSam Leffler 692*f05cddf9SRui Paulo #ifndef CONFIG_ELOOP_POLL 69339beb93cSSam Leffler rfds = os_malloc(sizeof(*rfds)); 69439beb93cSSam Leffler wfds = os_malloc(sizeof(*wfds)); 69539beb93cSSam Leffler efds = os_malloc(sizeof(*efds)); 696e28a4053SRui Paulo if (rfds == NULL || wfds == NULL || efds == NULL) 69739beb93cSSam Leffler goto out; 698*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 69939beb93cSSam Leffler 70039beb93cSSam Leffler while (!eloop.terminate && 701e28a4053SRui Paulo (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || 70239beb93cSSam Leffler eloop.writers.count > 0 || eloop.exceptions.count > 0)) { 703e28a4053SRui Paulo struct eloop_timeout *timeout; 704e28a4053SRui Paulo timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 705e28a4053SRui Paulo list); 706e28a4053SRui Paulo if (timeout) { 70739beb93cSSam Leffler os_get_time(&now); 708e28a4053SRui Paulo if (os_time_before(&now, &timeout->time)) 709e28a4053SRui Paulo os_time_sub(&timeout->time, &now, &tv); 71039beb93cSSam Leffler else 71139beb93cSSam Leffler tv.sec = tv.usec = 0; 712*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 713*f05cddf9SRui Paulo timeout_ms = tv.sec * 1000 + tv.usec / 1000; 714*f05cddf9SRui Paulo #else /* CONFIG_ELOOP_POLL */ 71539beb93cSSam Leffler _tv.tv_sec = tv.sec; 71639beb93cSSam Leffler _tv.tv_usec = tv.usec; 717*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 71839beb93cSSam Leffler } 71939beb93cSSam Leffler 720*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 721*f05cddf9SRui Paulo num_poll_fds = eloop_sock_table_set_fds( 722*f05cddf9SRui Paulo &eloop.readers, &eloop.writers, &eloop.exceptions, 723*f05cddf9SRui Paulo eloop.pollfds, eloop.pollfds_map, 724*f05cddf9SRui Paulo eloop.max_pollfd_map); 725*f05cddf9SRui Paulo res = poll(eloop.pollfds, num_poll_fds, 726*f05cddf9SRui Paulo timeout ? timeout_ms : -1); 727*f05cddf9SRui Paulo 728*f05cddf9SRui Paulo if (res < 0 && errno != EINTR && errno != 0) { 729*f05cddf9SRui Paulo perror("poll"); 730*f05cddf9SRui Paulo goto out; 731*f05cddf9SRui Paulo } 732*f05cddf9SRui Paulo #else /* CONFIG_ELOOP_POLL */ 73339beb93cSSam Leffler eloop_sock_table_set_fds(&eloop.readers, rfds); 73439beb93cSSam Leffler eloop_sock_table_set_fds(&eloop.writers, wfds); 73539beb93cSSam Leffler eloop_sock_table_set_fds(&eloop.exceptions, efds); 73639beb93cSSam Leffler res = select(eloop.max_sock + 1, rfds, wfds, efds, 737e28a4053SRui Paulo timeout ? &_tv : NULL); 73839beb93cSSam Leffler if (res < 0 && errno != EINTR && errno != 0) { 73939beb93cSSam Leffler perror("select"); 74039beb93cSSam Leffler goto out; 74139beb93cSSam Leffler } 742*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 74339beb93cSSam Leffler eloop_process_pending_signals(); 74439beb93cSSam Leffler 74539beb93cSSam Leffler /* check if some registered timeouts have occurred */ 746e28a4053SRui Paulo timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 747e28a4053SRui Paulo list); 748e28a4053SRui Paulo if (timeout) { 74939beb93cSSam Leffler os_get_time(&now); 750e28a4053SRui Paulo if (!os_time_before(&now, &timeout->time)) { 751e28a4053SRui Paulo void *eloop_data = timeout->eloop_data; 752e28a4053SRui Paulo void *user_data = timeout->user_data; 753e28a4053SRui Paulo eloop_timeout_handler handler = 754e28a4053SRui Paulo timeout->handler; 755e28a4053SRui Paulo eloop_remove_timeout(timeout); 756e28a4053SRui Paulo handler(eloop_data, user_data); 75739beb93cSSam Leffler } 75839beb93cSSam Leffler 75939beb93cSSam Leffler } 76039beb93cSSam Leffler 76139beb93cSSam Leffler if (res <= 0) 76239beb93cSSam Leffler continue; 76339beb93cSSam Leffler 764*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 765*f05cddf9SRui Paulo eloop_sock_table_dispatch(&eloop.readers, &eloop.writers, 766*f05cddf9SRui Paulo &eloop.exceptions, eloop.pollfds_map, 767*f05cddf9SRui Paulo eloop.max_pollfd_map); 768*f05cddf9SRui Paulo #else /* CONFIG_ELOOP_POLL */ 76939beb93cSSam Leffler eloop_sock_table_dispatch(&eloop.readers, rfds); 77039beb93cSSam Leffler eloop_sock_table_dispatch(&eloop.writers, wfds); 77139beb93cSSam Leffler eloop_sock_table_dispatch(&eloop.exceptions, efds); 772*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 77339beb93cSSam Leffler } 77439beb93cSSam Leffler 77539beb93cSSam Leffler out: 776*f05cddf9SRui Paulo #ifndef CONFIG_ELOOP_POLL 77739beb93cSSam Leffler os_free(rfds); 77839beb93cSSam Leffler os_free(wfds); 77939beb93cSSam Leffler os_free(efds); 780*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 781*f05cddf9SRui Paulo return; 78239beb93cSSam Leffler } 78339beb93cSSam Leffler 78439beb93cSSam Leffler 78539beb93cSSam Leffler void eloop_terminate(void) 78639beb93cSSam Leffler { 78739beb93cSSam Leffler eloop.terminate = 1; 78839beb93cSSam Leffler } 78939beb93cSSam Leffler 79039beb93cSSam Leffler 79139beb93cSSam Leffler void eloop_destroy(void) 79239beb93cSSam Leffler { 79339beb93cSSam Leffler struct eloop_timeout *timeout, *prev; 79439beb93cSSam Leffler struct os_time now; 79539beb93cSSam Leffler 79639beb93cSSam Leffler os_get_time(&now); 797e28a4053SRui Paulo dl_list_for_each_safe(timeout, prev, &eloop.timeout, 798e28a4053SRui Paulo struct eloop_timeout, list) { 79939beb93cSSam Leffler int sec, usec; 800e28a4053SRui Paulo sec = timeout->time.sec - now.sec; 801e28a4053SRui Paulo usec = timeout->time.usec - now.usec; 802e28a4053SRui Paulo if (timeout->time.usec < now.usec) { 80339beb93cSSam Leffler sec--; 80439beb93cSSam Leffler usec += 1000000; 80539beb93cSSam Leffler } 806e28a4053SRui Paulo wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " 807e28a4053SRui Paulo "eloop_data=%p user_data=%p handler=%p", 808e28a4053SRui Paulo sec, usec, timeout->eloop_data, timeout->user_data, 809e28a4053SRui Paulo timeout->handler); 810e28a4053SRui Paulo wpa_trace_dump_funcname("eloop unregistered timeout handler", 811e28a4053SRui Paulo timeout->handler); 812e28a4053SRui Paulo wpa_trace_dump("eloop timeout", timeout); 813e28a4053SRui Paulo eloop_remove_timeout(timeout); 81439beb93cSSam Leffler } 81539beb93cSSam Leffler eloop_sock_table_destroy(&eloop.readers); 81639beb93cSSam Leffler eloop_sock_table_destroy(&eloop.writers); 81739beb93cSSam Leffler eloop_sock_table_destroy(&eloop.exceptions); 81839beb93cSSam Leffler os_free(eloop.signals); 819*f05cddf9SRui Paulo 820*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 821*f05cddf9SRui Paulo os_free(eloop.pollfds); 822*f05cddf9SRui Paulo os_free(eloop.pollfds_map); 823*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 82439beb93cSSam Leffler } 82539beb93cSSam Leffler 82639beb93cSSam Leffler 82739beb93cSSam Leffler int eloop_terminated(void) 82839beb93cSSam Leffler { 82939beb93cSSam Leffler return eloop.terminate; 83039beb93cSSam Leffler } 83139beb93cSSam Leffler 83239beb93cSSam Leffler 83339beb93cSSam Leffler void eloop_wait_for_read_sock(int sock) 83439beb93cSSam Leffler { 835*f05cddf9SRui Paulo #ifdef CONFIG_ELOOP_POLL 836*f05cddf9SRui Paulo struct pollfd pfd; 837*f05cddf9SRui Paulo 838*f05cddf9SRui Paulo if (sock < 0) 839*f05cddf9SRui Paulo return; 840*f05cddf9SRui Paulo 841*f05cddf9SRui Paulo os_memset(&pfd, 0, sizeof(pfd)); 842*f05cddf9SRui Paulo pfd.fd = sock; 843*f05cddf9SRui Paulo pfd.events = POLLIN; 844*f05cddf9SRui Paulo 845*f05cddf9SRui Paulo poll(&pfd, 1, -1); 846*f05cddf9SRui Paulo #else /* CONFIG_ELOOP_POLL */ 84739beb93cSSam Leffler fd_set rfds; 84839beb93cSSam Leffler 84939beb93cSSam Leffler if (sock < 0) 85039beb93cSSam Leffler return; 85139beb93cSSam Leffler 85239beb93cSSam Leffler FD_ZERO(&rfds); 85339beb93cSSam Leffler FD_SET(sock, &rfds); 85439beb93cSSam Leffler select(sock + 1, &rfds, NULL, NULL, NULL); 855*f05cddf9SRui Paulo #endif /* CONFIG_ELOOP_POLL */ 85639beb93cSSam Leffler } 857