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