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