1 /* 2 * uloop - event loop implementation 3 * 4 * Copyright (C) 2010-2016 Felix Fietkau <nbd@openwrt.org> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include <sys/time.h> 19 #include <sys/types.h> 20 21 #include <unistd.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <errno.h> 25 #include <poll.h> 26 #include <string.h> 27 #include <fcntl.h> 28 #include <stdbool.h> 29 #include <limits.h> 30 #include <signal.h> 31 32 #include "uloop.h" 33 #include "utils.h" 34 35 #ifdef USE_KQUEUE 36 #include <sys/event.h> 37 #endif 38 #ifdef USE_EPOLL 39 #include <sys/epoll.h> 40 #include <sys/timerfd.h> 41 #endif 42 #include <sys/wait.h> 43 44 struct uloop_fd_event { 45 struct uloop_fd *fd; 46 unsigned int events; 47 }; 48 49 struct uloop_fd_stack { 50 struct uloop_fd_stack *next; 51 struct uloop_fd *fd; 52 unsigned int events; 53 }; 54 55 static struct uloop_fd_stack *fd_stack = NULL; 56 57 #define ULOOP_MAX_EVENTS 10 58 59 static struct list_head timeouts = LIST_HEAD_INIT(timeouts); 60 static struct list_head processes = LIST_HEAD_INIT(processes); 61 static struct list_head signals = LIST_HEAD_INIT(signals); 62 63 static int poll_fd = -1; 64 bool uloop_cancelled = false; 65 bool uloop_handle_sigchld = true; 66 static int uloop_status = 0; 67 static volatile sig_atomic_t do_sigchld = 0; 68 69 static struct uloop_fd_event cur_fds[ULOOP_MAX_EVENTS]; 70 static int cur_fd, cur_nfds; 71 static int uloop_run_depth = 0; 72 73 uloop_fd_handler uloop_fd_set_cb = NULL; 74 75 int uloop_fd_add(struct uloop_fd *sock, unsigned int flags); 76 77 #ifdef USE_KQUEUE 78 #include "uloop-kqueue.c" 79 #endif 80 81 #ifdef USE_EPOLL 82 #include "uloop-epoll.c" 83 #endif 84 85 static void set_signo(uint64_t *signums, int signo) 86 { 87 if (signo >= 1 && signo <= 64) 88 *signums |= (UINT64_C(1) << (signo - 1)); 89 } 90 91 static bool get_signo(uint64_t signums, int signo) 92 { 93 return (signo >= 1) && (signo <= 64) && (signums & (UINT64_C(1) << (signo - 1))); 94 } 95 96 static void signal_consume(struct uloop_fd *fd, unsigned int events) 97 { 98 struct uloop_signal *usig, *usig_next; 99 uint64_t signums = 0; 100 uint8_t buf[32]; 101 ssize_t nsigs; 102 103 do { 104 nsigs = read(fd->fd, buf, sizeof(buf)); 105 106 for (ssize_t i = 0; i < nsigs; i++) 107 set_signo(&signums, buf[i]); 108 } 109 while (nsigs > 0); 110 111 list_for_each_entry_safe(usig, usig_next, &signals, list) 112 if (get_signo(signums, usig->signo)) 113 usig->cb(usig); 114 } 115 116 static int waker_pipe = -1; 117 static struct uloop_fd waker_fd = { 118 .fd = -1, 119 .cb = signal_consume, 120 }; 121 122 static void waker_init_fd(int fd) 123 { 124 int flags; 125 126 flags = fcntl(fd, F_GETFD); 127 if (flags >= 0) 128 fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 129 130 flags = fcntl(fd, F_GETFL); 131 if (flags >= 0) 132 fcntl(fd, F_SETFL, flags | O_NONBLOCK); 133 } 134 135 static int waker_init(void) 136 { 137 int fds[2]; 138 139 if (waker_pipe >= 0) 140 return 0; 141 142 if (pipe(fds) < 0) 143 return -1; 144 145 waker_init_fd(fds[0]); 146 waker_init_fd(fds[1]); 147 waker_pipe = fds[1]; 148 149 waker_fd.fd = fds[0]; 150 waker_fd.cb = signal_consume; 151 uloop_fd_add(&waker_fd, ULOOP_READ); 152 153 return 0; 154 } 155 156 static void uloop_setup_signals(bool add); 157 158 int uloop_init(void) 159 { 160 if (uloop_init_pollfd() < 0) 161 return -1; 162 163 if (waker_init() < 0) { 164 uloop_done(); 165 return -1; 166 } 167 168 uloop_setup_signals(true); 169 170 return 0; 171 } 172 173 static bool uloop_fd_stack_event(struct uloop_fd *fd, int events) 174 { 175 struct uloop_fd_stack *cur; 176 177 /* 178 * Do not buffer events for level-triggered fds, they will keep firing. 179 * Caller needs to take care of recursion issues. 180 */ 181 if (!(fd->flags & ULOOP_EDGE_TRIGGER)) 182 return false; 183 184 for (cur = fd_stack; cur; cur = cur->next) { 185 if (cur->fd != fd) 186 continue; 187 188 if (events < 0) 189 cur->fd = NULL; 190 else 191 cur->events |= events | ULOOP_EVENT_BUFFERED; 192 193 return true; 194 } 195 196 return false; 197 } 198 199 static void uloop_run_events(int64_t timeout) 200 { 201 struct uloop_fd_event *cur; 202 struct uloop_fd *fd; 203 204 if (!cur_nfds) { 205 cur_fd = 0; 206 cur_nfds = uloop_fetch_events(timeout); 207 if (cur_nfds < 0) 208 cur_nfds = 0; 209 } 210 211 while (cur_nfds > 0) { 212 struct uloop_fd_stack stack_cur; 213 unsigned int events; 214 215 cur = &cur_fds[cur_fd++]; 216 cur_nfds--; 217 218 fd = cur->fd; 219 events = cur->events; 220 if (!fd) 221 continue; 222 223 if (!fd->cb) 224 continue; 225 226 if (uloop_fd_stack_event(fd, cur->events)) 227 continue; 228 229 stack_cur.next = fd_stack; 230 stack_cur.fd = fd; 231 fd_stack = &stack_cur; 232 do { 233 stack_cur.events = 0; 234 fd->cb(fd, events); 235 events = stack_cur.events & ULOOP_EVENT_MASK; 236 } while (stack_cur.fd && events); 237 fd_stack = stack_cur.next; 238 239 return; 240 } 241 } 242 243 int uloop_fd_add(struct uloop_fd *sock, unsigned int flags) 244 { 245 int fl; 246 int ret; 247 248 if (!(flags & (ULOOP_READ | ULOOP_WRITE | ULOOP_PRIORITY))) 249 return uloop_fd_delete(sock); 250 251 if (!sock->registered && !(flags & ULOOP_BLOCKING)) { 252 fl = fcntl(sock->fd, F_GETFL, 0); 253 if (fl >= 0) 254 fcntl(sock->fd, F_SETFL, fl | O_NONBLOCK); 255 } 256 257 ret = register_poll(sock, flags); 258 if (ret < 0) 259 goto out; 260 261 if (uloop_fd_set_cb) 262 uloop_fd_set_cb(sock, flags); 263 264 sock->flags = flags; 265 sock->registered = true; 266 sock->eof = false; 267 sock->error = false; 268 269 out: 270 return ret; 271 } 272 273 int uloop_fd_delete(struct uloop_fd *fd) 274 { 275 int ret; 276 int i; 277 278 for (i = 0; i < cur_nfds; i++) { 279 if (cur_fds[cur_fd + i].fd != fd) 280 continue; 281 282 cur_fds[cur_fd + i].fd = NULL; 283 } 284 285 if (!fd->registered) 286 return 0; 287 288 if (uloop_fd_set_cb) 289 uloop_fd_set_cb(fd, 0); 290 291 fd->registered = false; 292 uloop_fd_stack_event(fd, -1); 293 ret = __uloop_fd_delete(fd); 294 fd->flags = 0; 295 296 return ret; 297 } 298 299 static int64_t tv_diff(struct timeval *t1, struct timeval *t2) 300 { 301 return 302 (t1->tv_sec - t2->tv_sec) * 1000 + 303 (t1->tv_usec - t2->tv_usec) / 1000; 304 } 305 306 int uloop_timeout_add(struct uloop_timeout *timeout) 307 { 308 struct uloop_timeout *tmp; 309 struct list_head *h = &timeouts; 310 311 if (timeout->pending) 312 return -1; 313 314 list_for_each_entry(tmp, &timeouts, list) { 315 if (tv_diff(&tmp->time, &timeout->time) > 0) { 316 h = &tmp->list; 317 break; 318 } 319 } 320 321 list_add_tail(&timeout->list, h); 322 timeout->pending = true; 323 324 return 0; 325 } 326 327 static void uloop_gettime(struct timeval *tv) 328 { 329 struct timespec ts; 330 331 clock_gettime(CLOCK_MONOTONIC, &ts); 332 tv->tv_sec = ts.tv_sec; 333 tv->tv_usec = ts.tv_nsec / 1000; 334 } 335 336 int uloop_timeout_set(struct uloop_timeout *timeout, int msecs) 337 { 338 struct timeval *time = &timeout->time; 339 340 if (timeout->pending) 341 uloop_timeout_cancel(timeout); 342 343 uloop_gettime(time); 344 345 time->tv_sec += msecs / 1000; 346 time->tv_usec += (msecs % 1000) * 1000; 347 348 if (time->tv_usec > 1000000) { 349 time->tv_sec++; 350 time->tv_usec -= 1000000; 351 } 352 353 return uloop_timeout_add(timeout); 354 } 355 356 int uloop_timeout_cancel(struct uloop_timeout *timeout) 357 { 358 if (!timeout->pending) 359 return -1; 360 361 list_del(&timeout->list); 362 timeout->pending = false; 363 364 return 0; 365 } 366 367 int uloop_timeout_remaining(struct uloop_timeout *timeout) 368 { 369 int64_t td; 370 struct timeval now; 371 372 if (!timeout->pending) 373 return -1; 374 375 uloop_gettime(&now); 376 377 td = tv_diff(&timeout->time, &now); 378 379 if (td > INT_MAX) 380 return INT_MAX; 381 else if (td < INT_MIN) 382 return INT_MIN; 383 else 384 return (int)td; 385 } 386 387 int64_t uloop_timeout_remaining64(struct uloop_timeout *timeout) 388 { 389 struct timeval now; 390 391 if (!timeout->pending) 392 return -1; 393 394 uloop_gettime(&now); 395 396 return tv_diff(&timeout->time, &now); 397 } 398 399 int uloop_process_add(struct uloop_process *p) 400 { 401 struct uloop_process *tmp; 402 struct list_head *h = &processes; 403 404 if (p->pending) 405 return -1; 406 407 list_for_each_entry(tmp, &processes, list) { 408 if (tmp->pid > p->pid) { 409 h = &tmp->list; 410 break; 411 } 412 } 413 414 list_add_tail(&p->list, h); 415 p->pending = true; 416 417 return 0; 418 } 419 420 int uloop_process_delete(struct uloop_process *p) 421 { 422 if (!p->pending) 423 return -1; 424 425 list_del(&p->list); 426 p->pending = false; 427 428 return 0; 429 } 430 431 static void uloop_handle_processes(void) 432 { 433 struct uloop_process *p, *tmp; 434 pid_t pid; 435 int ret; 436 437 do_sigchld = 0; 438 439 while (1) { 440 pid = waitpid(-1, &ret, WNOHANG); 441 if (pid < 0 && errno == EINTR) 442 continue; 443 444 if (pid <= 0) 445 return; 446 447 list_for_each_entry_safe(p, tmp, &processes, list) { 448 if (p->pid < pid) 449 continue; 450 451 if (p->pid > pid) 452 break; 453 454 uloop_process_delete(p); 455 p->cb(p, ret); 456 } 457 } 458 459 } 460 461 int uloop_interval_set(struct uloop_interval *timer, unsigned int msecs) 462 { 463 return timer_register(timer, msecs); 464 } 465 466 int uloop_interval_cancel(struct uloop_interval *timer) 467 { 468 return timer_remove(timer); 469 } 470 471 int64_t uloop_interval_remaining(struct uloop_interval *timer) 472 { 473 return timer_next(timer); 474 } 475 476 static void uloop_signal_wake(int signo) 477 { 478 uint8_t sigbyte = signo; 479 480 if (signo == SIGCHLD) 481 do_sigchld = 1; 482 483 do { 484 if (write(waker_pipe, &sigbyte, 1) < 0) { 485 if (errno == EINTR) 486 continue; 487 } 488 break; 489 } while (1); 490 } 491 492 static void uloop_handle_sigint(int signo) 493 { 494 uloop_status = signo; 495 uloop_cancelled = true; 496 uloop_signal_wake(signo); 497 } 498 499 static void uloop_install_handler(int signum, void (*handler)(int), struct sigaction* old, bool add) 500 { 501 struct sigaction s; 502 struct sigaction *act; 503 504 act = NULL; 505 sigaction(signum, NULL, &s); 506 507 if (add) { 508 if (s.sa_handler == SIG_DFL) { /* Do not override existing custom signal handlers */ 509 memcpy(old, &s, sizeof(struct sigaction)); 510 s.sa_handler = handler; 511 s.sa_flags = 0; 512 act = &s; 513 } 514 } 515 else if (s.sa_handler == handler) { /* Do not restore if someone modified our handler */ 516 act = old; 517 } 518 519 if (act != NULL) 520 sigaction(signum, act, NULL); 521 } 522 523 static void uloop_ignore_signal(int signum, bool ignore) 524 { 525 struct sigaction s; 526 void *new_handler = NULL; 527 528 sigaction(signum, NULL, &s); 529 530 if (ignore) { 531 if (s.sa_handler == SIG_DFL) /* Ignore only if there isn't any custom handler */ 532 new_handler = SIG_IGN; 533 } else { 534 if (s.sa_handler == SIG_IGN) /* Restore only if noone modified our SIG_IGN */ 535 new_handler = SIG_DFL; 536 } 537 538 if (new_handler) { 539 s.sa_handler = new_handler; 540 s.sa_flags = 0; 541 sigaction(signum, &s, NULL); 542 } 543 } 544 545 static void uloop_setup_signals(bool add) 546 { 547 static struct sigaction old_sigint, old_sigchld, old_sigterm; 548 549 uloop_install_handler(SIGINT, uloop_handle_sigint, &old_sigint, add); 550 uloop_install_handler(SIGTERM, uloop_handle_sigint, &old_sigterm, add); 551 552 if (uloop_handle_sigchld) 553 uloop_install_handler(SIGCHLD, uloop_signal_wake, &old_sigchld, add); 554 555 uloop_ignore_signal(SIGPIPE, add); 556 } 557 558 int uloop_signal_add(struct uloop_signal *s) 559 { 560 struct list_head *h = &signals; 561 struct uloop_signal *tmp; 562 struct sigaction sa; 563 564 if (s->pending) 565 return -1; 566 567 list_for_each_entry(tmp, &signals, list) { 568 if (tmp->signo > s->signo) { 569 h = &tmp->list; 570 break; 571 } 572 } 573 574 list_add_tail(&s->list, h); 575 s->pending = true; 576 577 sigaction(s->signo, NULL, &s->orig); 578 579 if (s->orig.sa_handler != uloop_signal_wake) { 580 sa.sa_handler = uloop_signal_wake; 581 sa.sa_flags = 0; 582 sigemptyset(&sa.sa_mask); 583 sigaction(s->signo, &sa, NULL); 584 } 585 586 return 0; 587 } 588 589 int uloop_signal_delete(struct uloop_signal *s) 590 { 591 if (!s->pending) 592 return -1; 593 594 list_del(&s->list); 595 s->pending = false; 596 597 if (s->orig.sa_handler != uloop_signal_wake) 598 sigaction(s->signo, &s->orig, NULL); 599 600 return 0; 601 } 602 603 int uloop_get_next_timeout(void) 604 { 605 struct uloop_timeout *timeout; 606 struct timeval tv; 607 int64_t diff; 608 609 if (list_empty(&timeouts)) 610 return -1; 611 612 uloop_gettime(&tv); 613 614 timeout = list_first_entry(&timeouts, struct uloop_timeout, list); 615 diff = tv_diff(&timeout->time, &tv); 616 if (diff < 0) 617 return 0; 618 if (diff > INT_MAX) 619 return INT_MAX; 620 621 return diff; 622 } 623 624 static void uloop_process_timeouts(void) 625 { 626 struct uloop_timeout *t; 627 struct timeval tv; 628 629 if (list_empty(&timeouts)) 630 return; 631 632 uloop_gettime(&tv); 633 while (!list_empty(&timeouts)) { 634 t = list_first_entry(&timeouts, struct uloop_timeout, list); 635 636 if (tv_diff(&t->time, &tv) > 0) 637 break; 638 639 uloop_timeout_cancel(t); 640 if (t->cb) 641 t->cb(t); 642 } 643 } 644 645 static void uloop_clear_timeouts(void) 646 { 647 struct uloop_timeout *t, *tmp; 648 649 list_for_each_entry_safe(t, tmp, &timeouts, list) 650 uloop_timeout_cancel(t); 651 } 652 653 static void uloop_clear_processes(void) 654 { 655 struct uloop_process *p, *tmp; 656 657 list_for_each_entry_safe(p, tmp, &processes, list) 658 uloop_process_delete(p); 659 } 660 661 bool uloop_cancelling(void) 662 { 663 return uloop_run_depth > 0 && uloop_cancelled; 664 } 665 666 int uloop_run_timeout(int timeout) 667 { 668 int next_time = 0; 669 670 uloop_run_depth++; 671 672 uloop_status = 0; 673 uloop_cancelled = false; 674 do { 675 uloop_process_timeouts(); 676 677 if (do_sigchld) 678 uloop_handle_processes(); 679 680 if (uloop_cancelled) 681 break; 682 683 next_time = uloop_get_next_timeout(); 684 if (timeout >= 0 && (next_time < 0 || timeout < next_time)) 685 next_time = timeout; 686 uloop_run_events(next_time); 687 } while (!uloop_cancelled && timeout < 0); 688 689 --uloop_run_depth; 690 691 return uloop_status; 692 } 693 694 void uloop_done(void) 695 { 696 uloop_setup_signals(false); 697 698 if (poll_fd >= 0) { 699 close(poll_fd); 700 poll_fd = -1; 701 } 702 703 if (waker_pipe >= 0) { 704 uloop_fd_delete(&waker_fd); 705 close(waker_pipe); 706 close(waker_fd.fd); 707 waker_pipe = -1; 708 } 709 710 uloop_clear_timeouts(); 711 uloop_clear_processes(); 712 } 713
This page was automatically generated by LXR 0.3.1. • OpenWrt