1 #include "first.h" 2 3 #include "fdevent_impl.h" 4 #include "fdevent.h" 5 #include "buffer.h" 6 #include "log.h" 7 8 #include <sys/types.h> 9 #include <unistd.h> 10 #include <errno.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #ifdef _WIN32 15 #include <winsock2.h> /* closesocket */ 16 #endif 17 18 #ifdef FDEVENT_USE_LINUX_EPOLL 19 __attribute_cold__ 20 static int fdevent_linux_sysepoll_init(struct fdevents *ev); 21 #endif 22 #ifdef FDEVENT_USE_FREEBSD_KQUEUE 23 __attribute_cold__ 24 static int fdevent_freebsd_kqueue_init(struct fdevents *ev); 25 #endif 26 #ifdef FDEVENT_USE_SOLARIS_PORT 27 __attribute_cold__ 28 static int fdevent_solaris_port_init(struct fdevents *ev); 29 #endif 30 #ifdef FDEVENT_USE_SOLARIS_DEVPOLL 31 __attribute_cold__ 32 static int fdevent_solaris_devpoll_init(struct fdevents *ev); 33 #endif 34 #ifdef FDEVENT_USE_LIBEV 35 __attribute_cold__ 36 static int fdevent_libev_init(struct fdevents *ev); 37 #endif 38 #ifdef FDEVENT_USE_POLL 39 __attribute_cold__ 40 static int fdevent_poll_init(struct fdevents *ev); 41 #endif 42 #ifdef FDEVENT_USE_SELECT 43 __attribute_cold__ 44 static int fdevent_select_init(struct fdevents *ev); 45 #endif 46 47 48 int 49 fdevent_config (const char **event_handler_name, log_error_st *errh) 50 { 51 static const struct ev_map { fdevent_handler_t et; const char *name; } 52 event_handlers[] = 53 { 54 /* - epoll is most reliable 55 * - select works everywhere 56 */ 57 #ifdef FDEVENT_USE_LINUX_EPOLL 58 { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" }, 59 { FDEVENT_HANDLER_LINUX_SYSEPOLL, "epoll" }, 60 #endif 61 #ifdef FDEVENT_USE_SOLARIS_PORT 62 { FDEVENT_HANDLER_SOLARIS_PORT, "solaris-eventports" }, 63 #endif 64 #ifdef FDEVENT_USE_SOLARIS_DEVPOLL 65 { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" }, 66 #endif 67 #ifdef FDEVENT_USE_FREEBSD_KQUEUE 68 { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" }, 69 { FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue" }, 70 #endif 71 #ifdef FDEVENT_USE_POLL 72 { FDEVENT_HANDLER_POLL, "poll" }, 73 #endif 74 #ifdef FDEVENT_USE_SELECT 75 { FDEVENT_HANDLER_SELECT, "select" }, 76 #endif 77 #ifdef FDEVENT_USE_LIBEV 78 { FDEVENT_HANDLER_LIBEV, "libev" }, 79 #endif 80 { FDEVENT_HANDLER_UNSET, NULL } 81 }; 82 83 const char *event_handler = *event_handler_name; 84 fdevent_handler_t et = FDEVENT_HANDLER_UNSET; 85 86 #ifndef FDEVENT_USE_LIBEV 87 if (NULL != event_handler && 0 == strcmp(event_handler, "libev")) 88 event_handler = NULL; 89 #endif 90 #ifdef FDEVENT_USE_POLL 91 if (NULL != event_handler && 0 == strcmp(event_handler, "select")) 92 event_handler = "poll"; 93 #endif 94 95 if (NULL == event_handler) { 96 /* choose a good default 97 * 98 * the event_handler list is sorted by 'goodness' 99 * taking the first available should be the best solution 100 */ 101 et = event_handlers[0].et; 102 *event_handler_name = event_handlers[0].name; 103 104 if (FDEVENT_HANDLER_UNSET == et) { 105 log_error(errh, __FILE__, __LINE__, 106 "sorry, there is no event handler for this system"); 107 108 return -1; 109 } 110 } 111 else { 112 /* 113 * User override 114 */ 115 116 for (uint32_t i = 0; event_handlers[i].name; ++i) { 117 if (0 == strcmp(event_handlers[i].name, event_handler)) { 118 et = event_handlers[i].et; 119 break; 120 } 121 } 122 123 if (FDEVENT_HANDLER_UNSET == et) { 124 log_error(errh, __FILE__, __LINE__, 125 "the selected event-handler in unknown or not supported: %s", 126 event_handler); 127 return -1; 128 } 129 } 130 131 return et; 132 } 133 134 135 const char * 136 fdevent_show_event_handlers (void) 137 { 138 return 139 "\nEvent Handlers:\n\n" 140 #ifdef FDEVENT_USE_SELECT 141 "\t+ select (generic)\n" 142 #else 143 "\t- select (generic)\n" 144 #endif 145 #ifdef FDEVENT_USE_POLL 146 "\t+ poll (Unix)\n" 147 #else 148 "\t- poll (Unix)\n" 149 #endif 150 #ifdef FDEVENT_USE_LINUX_EPOLL 151 "\t+ epoll (Linux)\n" 152 #else 153 "\t- epoll (Linux)\n" 154 #endif 155 #ifdef FDEVENT_USE_SOLARIS_DEVPOLL 156 "\t+ /dev/poll (Solaris)\n" 157 #else 158 "\t- /dev/poll (Solaris)\n" 159 #endif 160 #ifdef FDEVENT_USE_SOLARIS_PORT 161 "\t+ eventports (Solaris)\n" 162 #else 163 "\t- eventports (Solaris)\n" 164 #endif 165 #ifdef FDEVENT_USE_FREEBSD_KQUEUE 166 "\t+ kqueue (FreeBSD)\n" 167 #else 168 "\t- kqueue (FreeBSD)\n" 169 #endif 170 #ifdef FDEVENT_USE_LIBEV 171 "\t+ libev (generic)\n" 172 #else 173 "\t- libev (generic)\n" 174 #endif 175 ; 176 } 177 178 179 fdevents * 180 fdevent_init (const char *event_handler, int *max_fds, int *cur_fds, log_error_st *errh) 181 { 182 fdevents *ev; 183 uint32_t maxfds = (0 != *max_fds) 184 ? (uint32_t)*max_fds 185 : 4096; 186 int type = fdevent_config(&event_handler, errh); 187 if (type <= 0) return NULL; 188 189 fdevent_socket_nb_cloexec_init(); 190 191 #ifdef FDEVENT_USE_SELECT 192 /* select limits itself 193 * as it is a hard limit and will lead to a segfault we add some safety 194 * */ 195 if (type == FDEVENT_HANDLER_SELECT) { 196 if (maxfds > (uint32_t)FD_SETSIZE - 200) 197 maxfds = (uint32_t)FD_SETSIZE - 200; 198 } 199 #endif 200 *max_fds = (int)maxfds; 201 ++maxfds; /*(+1 for event-handler fd)*/ 202 203 ev = calloc(1, sizeof(*ev)); 204 force_assert(NULL != ev); 205 ev->errh = errh; 206 ev->cur_fds = cur_fds; 207 ev->event_handler = event_handler; 208 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray)); 209 if (NULL == ev->fdarray) { 210 log_error(ev->errh, __FILE__, __LINE__, 211 "server.max-fds too large? (%u)", maxfds-1); 212 free(ev); 213 return NULL; 214 } 215 ev->maxfds = maxfds; 216 217 switch(type) { 218 #ifdef FDEVENT_USE_POLL 219 case FDEVENT_HANDLER_POLL: 220 if (0 == fdevent_poll_init(ev)) return ev; 221 break; 222 #endif 223 #ifdef FDEVENT_USE_SELECT 224 case FDEVENT_HANDLER_SELECT: 225 if (0 == fdevent_select_init(ev)) return ev; 226 break; 227 #endif 228 #ifdef FDEVENT_USE_LINUX_EPOLL 229 case FDEVENT_HANDLER_LINUX_SYSEPOLL: 230 if (0 == fdevent_linux_sysepoll_init(ev)) return ev; 231 break; 232 #endif 233 #ifdef FDEVENT_USE_SOLARIS_DEVPOLL 234 case FDEVENT_HANDLER_SOLARIS_DEVPOLL: 235 if (0 == fdevent_solaris_devpoll_init(ev)) return ev; 236 break; 237 #endif 238 #ifdef FDEVENT_USE_SOLARIS_PORT 239 case FDEVENT_HANDLER_SOLARIS_PORT: 240 if (0 == fdevent_solaris_port_init(ev)) return ev; 241 break; 242 #endif 243 #ifdef FDEVENT_USE_FREEBSD_KQUEUE 244 case FDEVENT_HANDLER_FREEBSD_KQUEUE: 245 if (0 == fdevent_freebsd_kqueue_init(ev)) return ev; 246 break; 247 #endif 248 #ifdef FDEVENT_USE_LIBEV 249 case FDEVENT_HANDLER_LIBEV: 250 if (0 == fdevent_libev_init(ev)) return ev; 251 break; 252 #endif 253 /*case FDEVENT_HANDLER_UNSET:*/ 254 default: 255 break; 256 } 257 258 free(ev->fdarray); 259 free(ev); 260 261 log_error(errh, __FILE__, __LINE__, 262 "event-handler failed: %s; " 263 "try to set server.event-handler = \"poll\" or \"select\"", 264 event_handler); 265 return NULL; 266 } 267 268 269 void 270 fdevent_free (fdevents *ev) 271 { 272 if (!ev) return; 273 if (ev->free) ev->free(ev); 274 275 for (uint32_t i = 0; i < ev->maxfds; ++i) { 276 /* (fdevent_sched_run() should already have been run, 277 * but take reasonable precautions anyway) */ 278 if (ev->fdarray[i]) 279 free((fdnode *)((uintptr_t)ev->fdarray[i] & ~0x3)); 280 } 281 282 free(ev->fdarray); 283 free(ev); 284 } 285 286 287 int 288 fdevent_reset (fdevents *ev) 289 { 290 int rc = (NULL != ev->reset) ? ev->reset(ev) : 0; 291 if (-1 == rc) { 292 log_error(ev->errh, __FILE__, __LINE__, 293 "event-handler failed: %s; " 294 "try to set server.event-handler = \"poll\" or \"select\"", 295 ev->event_handler ? ev->event_handler : ""); 296 } 297 return rc; 298 } 299 300 301 static void 302 fdevent_sched_run (fdevents * const ev) 303 { 304 for (fdnode *fdn = ev->pendclose; fdn; ) { 305 int fd, rc; 306 #ifdef _WIN32 307 rc = (uintptr_t)fdn & 0x3; 308 #endif 309 fdn = (fdnode *)((uintptr_t)fdn & ~0x3); 310 fd = fdn->fd; 311 #ifdef _WIN32 312 if (rc == 0x1) { 313 rc = closesocket(fd); 314 } 315 else if (rc == 0x2) { 316 rc = close(fd); 317 } 318 #else 319 rc = close(fd); 320 #endif 321 322 if (0 != rc) { 323 log_perror(ev->errh, __FILE__, __LINE__, "close failed %d", fd); 324 } 325 else { 326 --(*ev->cur_fds); 327 } 328 329 fdnode * const fdn_tmp = fdn; 330 fdn = (fdnode *)fdn->ctx; /* next */ 331 /*(fdevent_unregister)*/ 332 free(fdn_tmp); /*fdnode_free(fdn_tmp);*/ 333 ev->fdarray[fd] = NULL; 334 } 335 ev->pendclose = NULL; 336 } 337 338 339 int 340 fdevent_poll (fdevents * const ev, const int timeout_ms) 341 { 342 const int n = ev->poll(ev, ev->pendclose ? 0 : timeout_ms); 343 if (n >= 0) 344 fdevent_sched_run(ev); 345 else if (errno != EINTR) 346 log_perror(ev->errh, __FILE__, __LINE__, "fdevent_poll failed"); 347 return n; 348 } 349 350 351 #ifdef FDEVENT_USE_LINUX_EPOLL 352 353 #include <sys/epoll.h> 354 355 static int 356 fdevent_linux_sysepoll_event_del (fdevents *ev, fdnode *fdn) 357 { 358 return epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fdn->fd, NULL); 359 } 360 361 static int 362 fdevent_linux_sysepoll_event_set (fdevents *ev, fdnode *fdn, int events) 363 { 364 int op = (-1 == fdn->fde_ndx) ? EPOLL_CTL_ADD : EPOLL_CTL_MOD; 365 int fd = fdn->fde_ndx = fdn->fd; 366 struct epoll_event ep; 367 #ifndef EPOLLRDHUP 368 events &= ~FDEVENT_RDHUP; 369 #endif 370 ep.events = events | EPOLLERR | EPOLLHUP; 371 ep.data.ptr = fdn; 372 return epoll_ctl(ev->epoll_fd, op, fd, &ep); 373 } 374 375 static int 376 fdevent_linux_sysepoll_poll (fdevents * const ev, int timeout_ms) 377 { 378 struct epoll_event * const restrict epoll_events = ev->epoll_events; 379 int n = epoll_wait(ev->epoll_fd, epoll_events, ev->maxfds, timeout_ms); 380 for (int i = 0; i < n; ++i) { 381 fdnode * const fdn = (fdnode *)epoll_events[i].data.ptr; 382 int revents = epoll_events[i].events; 383 if ((fdevent_handler)NULL != fdn->handler) 384 (*fdn->handler)(fdn->ctx, revents); 385 } 386 return n; 387 } 388 389 __attribute_cold__ 390 static void 391 fdevent_linux_sysepoll_free (fdevents *ev) 392 { 393 close(ev->epoll_fd); 394 free(ev->epoll_events); 395 } 396 397 __attribute_cold__ 398 static int 399 fdevent_linux_sysepoll_init (fdevents *ev) 400 { 401 force_assert(EPOLLIN == FDEVENT_IN); 402 force_assert(EPOLLPRI == FDEVENT_PRI); 403 force_assert(EPOLLOUT == FDEVENT_OUT); 404 force_assert(EPOLLERR == FDEVENT_ERR); 405 force_assert(EPOLLHUP == FDEVENT_HUP); 406 #ifdef EPOLLRDHUP 407 force_assert(EPOLLRDHUP == FDEVENT_RDHUP); 408 #endif 409 410 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; 411 ev->event_set = fdevent_linux_sysepoll_event_set; 412 ev->event_del = fdevent_linux_sysepoll_event_del; 413 ev->poll = fdevent_linux_sysepoll_poll; 414 ev->free = fdevent_linux_sysepoll_free; 415 416 #ifdef EPOLL_CLOEXEC 417 if (-1 == (ev->epoll_fd = epoll_create1(EPOLL_CLOEXEC))) return -1; 418 #else 419 if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) return -1; 420 fdevent_setfd_cloexec(ev->epoll_fd); 421 #endif 422 423 ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events)); 424 force_assert(NULL != ev->epoll_events); 425 426 return 0; 427 } 428 429 #endif /* FDEVENT_USE_LINUX_EPOLL */ 430 431 432 #ifdef FDEVENT_USE_FREEBSD_KQUEUE 433 434 #include <sys/event.h> 435 #include <sys/time.h> 436 #include <fcntl.h> 437 438 static int 439 fdevent_freebsd_kqueue_event_del (fdevents *ev, fdnode *fdn) 440 { 441 struct kevent kev[2]; 442 struct timespec ts = {0, 0}; 443 int fd = fdn->fd; 444 int n = 0; 445 int oevents = fdn->events; 446 447 if (oevents & FDEVENT_IN) { 448 EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, fdn); 449 n++; 450 } 451 if (oevents & FDEVENT_OUT) { 452 EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, fdn); 453 n++; 454 } 455 456 return (0 != n) ? kevent(ev->kq_fd, kev, n, NULL, 0, &ts) : 0; 457 /*(kevent() changelist still processed on EINTR, 458 * but EINTR should not be received since 0 == nevents)*/ 459 } 460 461 static int 462 fdevent_freebsd_kqueue_event_set (fdevents *ev, fdnode *fdn, int events) 463 { 464 struct kevent kev[2]; 465 struct timespec ts = {0, 0}; 466 int fd = fdn->fde_ndx = fdn->fd; 467 int n = 0; 468 int oevents = fdn->events; 469 int addevents = events & ~oevents; 470 int delevents = ~events & oevents; 471 472 if (addevents & FDEVENT_IN) { 473 EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD, 0, 0, fdn); 474 n++; 475 } 476 else if (delevents & FDEVENT_IN) { 477 EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, fdn); 478 n++; 479 } 480 481 if (addevents & FDEVENT_OUT) { 482 EV_SET(&kev[n], fd, EVFILT_WRITE, EV_ADD, 0, 0, fdn); 483 n++; 484 } 485 else if (delevents & FDEVENT_OUT) { 486 EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, fdn); 487 n++; 488 } 489 490 return (0 != n) ? kevent(ev->kq_fd, kev, n, NULL, 0, &ts) : 0; 491 /*(kevent() changelist still processed on EINTR, 492 * but EINTR should not be received since 0 == nevents)*/ 493 } 494 495 static int 496 fdevent_freebsd_kqueue_poll (fdevents * const ev, int timeout_ms) 497 { 498 struct timespec ts; 499 ts.tv_sec = timeout_ms / 1000; 500 ts.tv_nsec = (timeout_ms % 1000) * 1000000; 501 502 struct kevent * const restrict kq_results = ev->kq_results; 503 const int n = kevent(ev->kq_fd, NULL, 0, kq_results, ev->maxfds, &ts); 504 505 for (int i = 0; i < n; ++i) { 506 fdnode * const fdn = (fdnode *)kq_results[i].udata; 507 int filt = kq_results[i].filter; 508 int e = kq_results[i].flags; 509 if ((fdevent_handler)NULL != fdn->handler) { 510 int revents = (filt == EVFILT_READ) ? FDEVENT_IN : FDEVENT_OUT; 511 if (e & EV_EOF) 512 revents |= (filt == EVFILT_READ ? FDEVENT_RDHUP : FDEVENT_HUP); 513 if (e & EV_ERROR) 514 revents |= FDEVENT_ERR; 515 (*fdn->handler)(fdn->ctx, revents); 516 } 517 } 518 return n; 519 } 520 521 __attribute_cold__ 522 static int 523 fdevent_freebsd_kqueue_reset (fdevents *ev) 524 { 525 #ifdef __NetBSD__ 526 ev->kq_fd = kqueue1(O_NONBLOCK|O_CLOEXEC|O_NOSIGPIPE); 527 return (-1 != ev->kq_fd) ? 0 : -1; 528 #else 529 ev->kq_fd = kqueue(); 530 if (-1 == ev->kq_fd) return -1; 531 fdevent_setfd_cloexec(ev->kq_fd); 532 return 0; 533 #endif 534 } 535 536 __attribute_cold__ 537 static void 538 fdevent_freebsd_kqueue_free (fdevents *ev) 539 { 540 close(ev->kq_fd); 541 free(ev->kq_results); 542 } 543 544 __attribute_cold__ 545 static int 546 fdevent_freebsd_kqueue_init (fdevents *ev) 547 { 548 ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE; 549 ev->event_set = fdevent_freebsd_kqueue_event_set; 550 ev->event_del = fdevent_freebsd_kqueue_event_del; 551 ev->poll = fdevent_freebsd_kqueue_poll; 552 ev->reset = fdevent_freebsd_kqueue_reset; 553 ev->free = fdevent_freebsd_kqueue_free; 554 ev->kq_fd = -1; 555 ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results)); 556 force_assert(NULL != ev->kq_results); 557 return 0; 558 } 559 560 #endif /* FDEVENT_USE_FREEBSD_KQUEUE */ 561 562 563 #ifdef FDEVENT_USE_SOLARIS_PORT 564 565 #include <sys/poll.h> 566 #include <fcntl.h> 567 568 static int 569 fdevent_solaris_port_event_del (fdevents *ev, fdnode *fdn) 570 { 571 return port_dissociate(ev->port_fd, PORT_SOURCE_FD, fdn->fd); 572 } 573 574 static int 575 fdevent_solaris_port_event_set (fdevents *ev, fdnode *fdn, int events) 576 { 577 int fd = fdn->fde_ndx = fdn->fd; 578 intptr_t ud = events & (POLLIN|POLLOUT); 579 return port_associate(ev->port_fd,PORT_SOURCE_FD,fd,(int)ud,(void*)ud); 580 } 581 582 /* if there is any error it will return the return values of port_getn, 583 * otherwise it will return number of events */ 584 static int 585 fdevent_solaris_port_poll (fdevents *ev, int timeout_ms) 586 { 587 const int pfd = ev->port_fd; 588 int ret; 589 unsigned int available_events, wait_for_events = 0; 590 591 struct timespec timeout; 592 593 timeout.tv_sec = timeout_ms/1000L; 594 timeout.tv_nsec = (timeout_ms % 1000L) * 1000000L; 595 596 /* get the number of file descriptors with events */ 597 if ((ret = port_getn(pfd, ev->port_events, 0, &wait_for_events, &timeout)) < 0) return ret; 598 599 /* wait for at least one event */ 600 if (0 == wait_for_events) wait_for_events = 1; 601 602 available_events = wait_for_events; 603 604 /* get the events of the file descriptors */ 605 if ((ret = port_getn(pfd, ev->port_events, ev->maxfds, &available_events, &timeout)) < 0) { 606 /* if errno == ETIME and available_event == wait_for_events we didn't get any events */ 607 /* for other errors we didn't get any events either */ 608 if (!(errno == ETIME && wait_for_events != available_events)) return ret; 609 } 610 611 for (int i = 0; i < (int)available_events; ++i) { 612 int fd = (int)ev->port_events[i].portev_object; 613 fdnode * const fdn = ev->fdarray[fd]; 614 const intptr_t ud = (intptr_t)ev->port_events[i].portev_user; 615 int revents = ev->port_events[i].portev_events; 616 if (0 == ((uintptr_t)fdn & 0x3)) { 617 if (port_associate(pfd,PORT_SOURCE_FD,fd,(int)ud,(void*)ud) < 0) 618 log_error(ev->errh,__FILE__,__LINE__,"port_associate failed"); 619 (*fdn->handler)(fdn->ctx, revents); 620 } 621 else { 622 fdn->fde_ndx = -1; 623 } 624 } 625 return available_events; 626 } 627 628 __attribute_cold__ 629 static void 630 fdevent_solaris_port_free (fdevents *ev) 631 { 632 close(ev->port_fd); 633 free(ev->port_events); 634 } 635 636 __attribute_cold__ 637 static int 638 fdevent_solaris_port_init (fdevents *ev) 639 { 640 force_assert(POLLIN == FDEVENT_IN); 641 force_assert(POLLPRI == FDEVENT_PRI); 642 force_assert(POLLOUT == FDEVENT_OUT); 643 force_assert(POLLERR == FDEVENT_ERR); 644 force_assert(POLLHUP == FDEVENT_HUP); 645 force_assert(POLLNVAL == FDEVENT_NVAL); 646 #ifdef POLLRDHUP 647 force_assert(POLLRDHUP == FDEVENT_RDHUP); 648 #endif 649 650 ev->type = FDEVENT_HANDLER_SOLARIS_PORT; 651 ev->event_set = fdevent_solaris_port_event_set; 652 ev->event_del = fdevent_solaris_port_event_del; 653 ev->poll = fdevent_solaris_port_poll; 654 ev->free = fdevent_solaris_port_free; 655 ev->port_events = malloc(ev->maxfds * sizeof(*ev->port_events)); 656 force_assert(NULL != ev->port_events); 657 658 if ((ev->port_fd = port_create()) < 0) return -1; 659 660 return 0; 661 } 662 663 #endif /* FDEVENT_USE_SOLARIS_PORT */ 664 665 666 #ifdef FDEVENT_USE_SOLARIS_DEVPOLL 667 668 #include <sys/devpoll.h> 669 #include <sys/ioctl.h> 670 #include <fcntl.h> 671 672 static int 673 fdevent_solaris_devpoll_event_del (fdevents *ev, fdnode *fdn) 674 { 675 struct pollfd pfd; 676 pfd.fd = fdn->fd; 677 pfd.events = POLLREMOVE; 678 pfd.revents = 0; 679 return (-1 != write(ev->devpoll_fd, &pfd, sizeof(pfd))) ? 0 : -1; 680 } 681 682 static int 683 fdevent_solaris_devpoll_event_set (fdevents *ev, fdnode *fdn, int events) 684 { 685 struct pollfd pfd; 686 pfd.fd = fdn->fde_ndx = fdn->fd; 687 #ifndef POLLRDHUP 688 events &= ~FDEVENT_RDHUP; 689 #endif 690 pfd.events = events; 691 pfd.revents = 0; 692 return (-1 != write(ev->devpoll_fd, &pfd, sizeof(pfd))) ? 0 : -1; 693 } 694 695 static int 696 fdevent_solaris_devpoll_poll (fdevents *ev, int timeout_ms) 697 { 698 fdnode ** const fdarray = ev->fdarray; 699 struct pollfd * const devpollfds = ev->devpollfds; 700 struct dvpoll dopoll; 701 702 dopoll.dp_timeout = timeout_ms; 703 dopoll.dp_nfds = ev->maxfds - 1; 704 dopoll.dp_fds = devpollfds; 705 706 const int n = ioctl(ev->devpoll_fd, DP_POLL, &dopoll); 707 708 for (int i = 0; i < n; ++i) { 709 fdnode * const fdn = fdarray[devpollfds[i].fd]; 710 int revents = devpollfds[i].revents; 711 if (0 == ((uintptr_t)fdn & 0x3)) 712 (*fdn->handler)(fdn->ctx, revents); 713 } 714 return n; 715 } 716 717 __attribute_cold__ 718 static int 719 fdevent_solaris_devpoll_reset (fdevents *ev) 720 { 721 /* a forked process does only inherit the filedescriptor, 722 * but every operation on the device will lead to a EACCES */ 723 ev->devpoll_fd = fdevent_open_cloexec("/dev/poll", 1, O_RDWR, 0); 724 return (ev->devpoll_fd >= 0) ? 0 : -1; 725 } 726 727 __attribute_cold__ 728 static void 729 fdevent_solaris_devpoll_free (fdevents *ev) 730 { 731 free(ev->devpollfds); 732 close(ev->devpoll_fd); 733 } 734 735 __attribute_cold__ 736 static int 737 fdevent_solaris_devpoll_init (fdevents *ev) 738 { 739 force_assert(POLLIN == FDEVENT_IN); 740 force_assert(POLLPRI == FDEVENT_PRI); 741 force_assert(POLLOUT == FDEVENT_OUT); 742 force_assert(POLLERR == FDEVENT_ERR); 743 force_assert(POLLHUP == FDEVENT_HUP); 744 force_assert(POLLNVAL == FDEVENT_NVAL); 745 #ifdef POLLRDHUP 746 force_assert(POLLRDHUP == FDEVENT_RDHUP); 747 #endif 748 749 ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL; 750 ev->event_set = fdevent_solaris_devpoll_event_set; 751 ev->event_del = fdevent_solaris_devpoll_event_del; 752 ev->poll = fdevent_solaris_devpoll_poll; 753 ev->reset = fdevent_solaris_devpoll_reset; 754 ev->free = fdevent_solaris_devpoll_free; 755 ev->devpoll_fd = -1; 756 ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds); 757 force_assert(NULL != ev->devpollfds); 758 return 0; 759 } 760 761 #endif /* FDEVENT_USE_SOLARIS_DEVPOLL */ 762 763 764 #ifdef FDEVENT_USE_LIBEV 765 766 #if (defined(__APPLE__) && defined(__MACH__)) \ 767 || defined(__FreeBSD__) || defined(__NetBSD__) \ 768 || defined(__OpenBSD__) || defined(__DragonFly__) 769 /* libev EV_ERROR conflicts with kqueue sys/event.h EV_ERROR */ 770 #undef EV_ERROR 771 #endif 772 773 #include <ev.h> 774 775 static void 776 fdevent_libev_io_watcher_cb (struct ev_loop *loop, ev_io *w, int revents) 777 { 778 fdevents *ev = w->data; 779 fdnode *fdn = ev->fdarray[w->fd]; 780 int rv = 0; 781 UNUSED(loop); 782 783 if (revents & EV_READ) rv |= FDEVENT_IN; 784 if (revents & EV_WRITE) rv |= FDEVENT_OUT; 785 if (revents & EV_ERROR) rv |= FDEVENT_ERR; 786 787 if (0 == ((uintptr_t)fdn & 0x3)) 788 (*fdn->handler)(fdn->ctx, rv); 789 } 790 791 static int 792 fdevent_libev_event_del (fdevents *ev, fdnode *fdn) 793 { 794 ev_io *watcher = fdn->handler_ctx; 795 if (!watcher) return 0; 796 fdn->handler_ctx = NULL; 797 798 ev_io_stop(ev->libev_loop, watcher); 799 free(watcher); 800 801 return 0; 802 } 803 804 static int 805 fdevent_libev_event_set (fdevents *ev, fdnode *fdn, int events) 806 { 807 ev_io *watcher = fdn->handler_ctx; 808 int ev_events = 0; 809 810 if (events & FDEVENT_IN) ev_events |= EV_READ; 811 if (events & FDEVENT_OUT) ev_events |= EV_WRITE; 812 813 if (!watcher) { 814 fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io)); 815 force_assert(watcher); 816 fdn->fde_ndx = fdn->fd; 817 818 ev_io_init(watcher, fdevent_libev_io_watcher_cb, fdn->fd, ev_events); 819 watcher->data = ev; 820 ev_io_start(ev->libev_loop, watcher); 821 } 822 else { 823 if ((watcher->events & (EV_READ | EV_WRITE)) != ev_events) { 824 ev_io_stop(ev->libev_loop, watcher); 825 ev_io_set(watcher, watcher->fd, ev_events); 826 ev_io_start(ev->libev_loop, watcher); 827 } 828 } 829 830 return 0; 831 } 832 833 static void 834 fdevent_libev_timeout_watcher_cb (struct ev_loop *loop, ev_timer *w, int revents) 835 { 836 UNUSED(loop); 837 UNUSED(w); 838 UNUSED(revents); 839 } 840 841 static ev_timer timeout_watcher; 842 843 static int 844 fdevent_libev_poll (fdevents *ev, int timeout_ms) 845 { 846 timeout_watcher.repeat = (timeout_ms > 0) ? timeout_ms/1000.0 : 0.001; 847 848 ev_timer_again(ev->libev_loop, &timeout_watcher); 849 ev_run(ev->libev_loop, EVRUN_ONCE); 850 851 return 0; 852 } 853 854 __attribute_cold__ 855 static int 856 fdevent_libev_reset (fdevents *ev) 857 { 858 UNUSED(ev); 859 ev_default_fork(); 860 return 0; 861 } 862 863 __attribute_cold__ 864 static void 865 fdevent_libev_free (fdevents *ev) 866 { 867 UNUSED(ev); 868 } 869 870 __attribute_cold__ 871 static int 872 fdevent_libev_init (fdevents *ev) 873 { 874 struct ev_timer * const timer = &timeout_watcher; 875 memset(timer, 0, sizeof(*timer)); 876 877 ev->type = FDEVENT_HANDLER_LIBEV; 878 ev->event_set = fdevent_libev_event_set; 879 ev->event_del = fdevent_libev_event_del; 880 ev->poll = fdevent_libev_poll; 881 ev->reset = fdevent_libev_reset; 882 ev->free = fdevent_libev_free; 883 884 if (NULL == (ev->libev_loop = ev_default_loop(0))) return -1; 885 886 ev_timer_init(timer, fdevent_libev_timeout_watcher_cb, 0.0, 1.0); 887 888 return 0; 889 } 890 891 #endif /* FDEVENT_USE_LIBEV */ 892 893 894 #ifdef FDEVENT_USE_POLL 895 896 #ifdef HAVE_POLL_H 897 #include <poll.h> 898 #else 899 #include <sys/poll.h> 900 #endif 901 902 static int 903 fdevent_poll_event_del (fdevents *ev, fdnode *fdn) 904 { 905 int fd = fdn->fd; 906 int k = fdn->fde_ndx; 907 if ((uint32_t)k >= ev->used || ev->pollfds[k].fd != fd) 908 return (errno = EINVAL, -1); 909 910 ev->pollfds[k].fd = -1; 911 /* ev->pollfds[k].events = 0; */ 912 /* ev->pollfds[k].revents = 0; */ 913 914 if (ev->unused.size == ev->unused.used) { 915 ev->unused.size += 16; 916 ev->unused.ptr = realloc(ev->unused.ptr, 917 sizeof(*(ev->unused.ptr)) * ev->unused.size); 918 force_assert(NULL != ev->unused.ptr); 919 } 920 921 ev->unused.ptr[ev->unused.used++] = k; 922 923 return 0; 924 } 925 926 static int 927 fdevent_poll_event_set (fdevents *ev, fdnode *fdn, int events) 928 { 929 int fd = fdn->fd; 930 int k = fdn->fde_ndx; 931 932 #ifndef POLLRDHUP 933 events &= ~FDEVENT_RDHUP; 934 #endif 935 936 if (k >= 0) { 937 if ((uint32_t)k >= ev->used || ev->pollfds[k].fd != fd) 938 return (errno = EINVAL, -1); 939 ev->pollfds[k].events = events; 940 return 0; 941 } 942 943 if (ev->unused.used > 0) { 944 k = ev->unused.ptr[--ev->unused.used]; 945 } 946 else { 947 if (ev->size == ev->used) { 948 ev->size += 16; 949 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size); 950 force_assert(NULL != ev->pollfds); 951 } 952 953 k = ev->used++; 954 } 955 956 fdn->fde_ndx = k; 957 ev->pollfds[k].fd = fd; 958 ev->pollfds[k].events = events; 959 960 return 0; 961 } 962 963 static int 964 fdevent_poll_poll (fdevents *ev, int timeout_ms) 965 { 966 struct pollfd * const restrict pfds = ev->pollfds; 967 fdnode ** const fdarray = ev->fdarray; 968 const int n = poll(pfds, ev->used, timeout_ms); 969 for (int i = 0, m = 0; m < n; ++i) { 970 if (0 == pfds[i].revents) continue; 971 fdnode *fdn = fdarray[pfds[i].fd]; 972 if (0 == ((uintptr_t)fdn & 0x3)) 973 (*fdn->handler)(fdn->ctx, pfds[i].revents); 974 ++m; 975 } 976 return n; 977 } 978 979 __attribute_cold__ 980 static void 981 fdevent_poll_free (fdevents *ev) 982 { 983 free(ev->pollfds); 984 if (ev->unused.ptr) free(ev->unused.ptr); 985 } 986 987 __attribute_cold__ 988 static int 989 fdevent_poll_init (fdevents *ev) 990 { 991 force_assert(POLLIN == FDEVENT_IN); 992 force_assert(POLLPRI == FDEVENT_PRI); 993 force_assert(POLLOUT == FDEVENT_OUT); 994 force_assert(POLLERR == FDEVENT_ERR); 995 force_assert(POLLHUP == FDEVENT_HUP); 996 force_assert(POLLNVAL == FDEVENT_NVAL); 997 #ifdef POLLRDHUP 998 force_assert(POLLRDHUP == FDEVENT_RDHUP); 999 #endif 1000 1001 ev->type = FDEVENT_HANDLER_POLL; 1002 ev->event_set = fdevent_poll_event_set; 1003 ev->event_del = fdevent_poll_event_del; 1004 ev->poll = fdevent_poll_poll; 1005 ev->free = fdevent_poll_free; 1006 return 0; 1007 } 1008 1009 #endif /* FDEVENT_USE_POLL */ 1010 1011 1012 #ifdef FDEVENT_USE_SELECT 1013 1014 #include "sys-time.h" 1015 1016 __attribute_cold__ 1017 static int 1018 fdevent_select_reset (fdevents *ev) 1019 { 1020 FD_ZERO(&(ev->select_set_read)); 1021 FD_ZERO(&(ev->select_set_write)); 1022 FD_ZERO(&(ev->select_set_error)); 1023 ev->select_max_fd = -1; 1024 return 0; 1025 } 1026 1027 static int 1028 fdevent_select_event_del (fdevents *ev, fdnode *fdn) 1029 { 1030 int fd = fdn->fd; 1031 FD_CLR(fd, &(ev->select_set_read)); 1032 FD_CLR(fd, &(ev->select_set_write)); 1033 FD_CLR(fd, &(ev->select_set_error)); 1034 return 0; 1035 } 1036 1037 static int 1038 fdevent_select_event_set (fdevents *ev, fdnode *fdn, int events) 1039 { 1040 int fd = fdn->fde_ndx = fdn->fd; 1041 1042 /* we should be protected by max-fds, but you never know */ 1043 force_assert(fd < ((int)FD_SETSIZE)); 1044 1045 if (events & FDEVENT_IN) 1046 FD_SET(fd, &(ev->select_set_read)); 1047 else 1048 FD_CLR(fd, &(ev->select_set_read)); 1049 1050 if (events & FDEVENT_OUT) 1051 FD_SET(fd, &(ev->select_set_write)); 1052 else 1053 FD_CLR(fd, &(ev->select_set_write)); 1054 1055 FD_SET(fd, &(ev->select_set_error)); 1056 1057 if (fd > ev->select_max_fd) ev->select_max_fd = fd; 1058 1059 return 0; 1060 } 1061 1062 static int 1063 fdevent_select_event_get_revent (const fdevents *ev, int ndx) 1064 { 1065 int revents = 0; 1066 if (FD_ISSET(ndx, &ev->select_read)) revents |= FDEVENT_IN; 1067 if (FD_ISSET(ndx, &ev->select_write)) revents |= FDEVENT_OUT; 1068 if (FD_ISSET(ndx, &ev->select_error)) revents |= FDEVENT_ERR; 1069 return revents; 1070 } 1071 1072 static int 1073 fdevent_select_event_next_fdndx (const fdevents *ev, int ndx) 1074 { 1075 const int max_fd = ev->select_max_fd + 1; 1076 for (int i = (ndx < 0) ? 0 : ndx + 1; i < max_fd; ++i) { 1077 if (FD_ISSET(i, &(ev->select_read))) return i; 1078 if (FD_ISSET(i, &(ev->select_write))) return i; 1079 if (FD_ISSET(i, &(ev->select_error))) return i; 1080 } 1081 1082 return -1; 1083 } 1084 1085 static int 1086 fdevent_select_poll (fdevents *ev, int timeout_ms) 1087 { 1088 int n; 1089 struct timeval tv; 1090 1091 tv.tv_sec = timeout_ms / 1000; 1092 tv.tv_usec = (timeout_ms % 1000) * 1000; 1093 1094 ev->select_read = ev->select_set_read; 1095 ev->select_write = ev->select_set_write; 1096 ev->select_error = ev->select_set_error; 1097 1098 n = select(ev->select_max_fd + 1, 1099 &ev->select_read, &ev->select_write, &ev->select_error, &tv); 1100 for (int ndx = -1, i = 0; i < n; ++i) { 1101 fdnode *fdn; 1102 ndx = fdevent_select_event_next_fdndx(ev, ndx); 1103 if (-1 == ndx) break; 1104 fdn = ev->fdarray[ndx]; 1105 if (0 == ((uintptr_t)fdn & 0x3)) { 1106 int revents = fdevent_select_event_get_revent(ev, ndx); 1107 (*fdn->handler)(fdn->ctx, revents); 1108 } 1109 } 1110 return n; 1111 } 1112 1113 __attribute_cold__ 1114 static int fdevent_select_init (fdevents *ev) 1115 { 1116 ev->type = FDEVENT_HANDLER_SELECT; 1117 ev->event_set = fdevent_select_event_set; 1118 ev->event_del = fdevent_select_event_del; 1119 ev->poll = fdevent_select_poll; 1120 ev->reset = fdevent_select_reset; 1121 return 0; 1122 } 1123 1124 #endif /* FDEVENT_USE_SELECT */ 1125