1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2006 Lennart Poettering 5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 6 7 PulseAudio is free software; you can redistribute it and/or modify 8 it under the terms of the GNU Lesser General Public License as published 9 by the Free Software Foundation; either version 2.1 of the License, 10 or (at your option) any later version. 11 12 PulseAudio is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 19***/ 20 21#ifdef HAVE_CONFIG_H 22#include <config.h> 23#endif 24 25#include <stdio.h> 26#include <unistd.h> 27#include <stdlib.h> 28#include <fcntl.h> 29#include <errno.h> 30 31#ifndef HAVE_PIPE 32#include <pulsecore/pipe.h> 33#endif 34 35#ifdef OS_IS_WIN32 36#include <winsock2.h> 37#endif 38 39#include <pulse/rtclock.h> 40#include <pulse/timeval.h> 41#include <pulse/xmalloc.h> 42 43#include <pulsecore/poll.h> 44#include <pulsecore/core-rtclock.h> 45#include <pulsecore/core-util.h> 46#include <pulsecore/i18n.h> 47#include <pulsecore/llist.h> 48#include <pulsecore/log.h> 49#include <pulsecore/core-error.h> 50#include <pulsecore/socket.h> 51#include <pulsecore/macro.h> 52 53#include "mainloop.h" 54#include "internal.h" 55 56struct pa_io_event { 57 pa_mainloop *mainloop; 58 bool dead:1; 59 60 int fd; 61 pa_io_event_flags_t events; 62 struct pollfd *pollfd; 63 64 pa_io_event_cb_t callback; 65 void *userdata; 66 pa_io_event_destroy_cb_t destroy_callback; 67 68 PA_LLIST_FIELDS(pa_io_event); 69}; 70 71struct pa_time_event { 72 pa_mainloop *mainloop; 73 bool dead:1; 74 75 bool enabled:1; 76 bool use_rtclock:1; 77 pa_usec_t time; 78 79 pa_time_event_cb_t callback; 80 void *userdata; 81 pa_time_event_destroy_cb_t destroy_callback; 82 83 PA_LLIST_FIELDS(pa_time_event); 84}; 85 86struct pa_defer_event { 87 pa_mainloop *mainloop; 88 bool dead:1; 89 90 bool enabled:1; 91 92 pa_defer_event_cb_t callback; 93 void *userdata; 94 pa_defer_event_destroy_cb_t destroy_callback; 95 96 PA_LLIST_FIELDS(pa_defer_event); 97}; 98 99struct pa_mainloop { 100 PA_LLIST_HEAD(pa_io_event, io_events); 101 PA_LLIST_HEAD(pa_time_event, time_events); 102 PA_LLIST_HEAD(pa_defer_event, defer_events); 103 104 unsigned n_enabled_defer_events, n_enabled_time_events, n_io_events; 105 unsigned io_events_please_scan, time_events_please_scan, defer_events_please_scan; 106 107 bool rebuild_pollfds:1; 108 struct pollfd *pollfds; 109 unsigned max_pollfds, n_pollfds; 110 111 pa_usec_t prepared_timeout; 112 pa_time_event *cached_next_time_event; 113 114 pa_mainloop_api api; 115 116 int retval; 117 bool quit:1; 118 119 int wakeup_pipe[2]; 120 int wakeup_pipe_type; 121 122 enum { 123 STATE_PASSIVE, 124 STATE_PREPARED, 125 STATE_POLLING, 126 STATE_POLLED, 127 STATE_QUIT 128 } state; 129 130 pa_poll_func poll_func; 131 void *poll_func_userdata; 132 int poll_func_ret; 133}; 134 135static short map_flags_to_libc(pa_io_event_flags_t flags) { 136 return (short) 137 ((flags & PA_IO_EVENT_INPUT ? POLLIN : 0) | 138 (flags & PA_IO_EVENT_OUTPUT ? POLLOUT : 0) | 139 (flags & PA_IO_EVENT_ERROR ? POLLERR : 0) | 140 (flags & PA_IO_EVENT_HANGUP ? POLLHUP : 0)); 141} 142 143static pa_io_event_flags_t map_flags_from_libc(short flags) { 144 return 145 (flags & POLLIN ? PA_IO_EVENT_INPUT : 0) | 146 (flags & POLLOUT ? PA_IO_EVENT_OUTPUT : 0) | 147 (flags & POLLERR ? PA_IO_EVENT_ERROR : 0) | 148 (flags & POLLHUP ? PA_IO_EVENT_HANGUP : 0); 149} 150 151/* IO events */ 152static pa_io_event* mainloop_io_new( 153 pa_mainloop_api *a, 154 int fd, 155 pa_io_event_flags_t events, 156 pa_io_event_cb_t callback, 157 void *userdata) { 158 159 pa_mainloop *m; 160 pa_io_event *e; 161 162 pa_assert(a); 163 pa_assert(a->userdata); 164 pa_assert(fd >= 0); 165 pa_assert(callback); 166 167 m = a->userdata; 168 pa_assert(a == &m->api); 169 170 e = pa_xnew0(pa_io_event, 1); 171 e->mainloop = m; 172 173 e->fd = fd; 174 e->events = events; 175 176 e->callback = callback; 177 e->userdata = userdata; 178 179 PA_LLIST_PREPEND(pa_io_event, m->io_events, e); 180 m->rebuild_pollfds = true; 181 m->n_io_events ++; 182 183 pa_mainloop_wakeup(m); 184 185 return e; 186} 187 188static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) { 189 pa_assert(e); 190 pa_assert(!e->dead); 191 192 if (e->events == events) 193 return; 194 195 e->events = events; 196 197 if (e->pollfd) 198 e->pollfd->events = map_flags_to_libc(events); 199 else 200 e->mainloop->rebuild_pollfds = true; 201 202 pa_mainloop_wakeup(e->mainloop); 203} 204 205static void mainloop_io_free(pa_io_event *e) { 206 pa_assert(e); 207 pa_assert(!e->dead); 208 209 e->dead = true; 210 e->mainloop->io_events_please_scan ++; 211 212 e->mainloop->n_io_events --; 213 e->mainloop->rebuild_pollfds = true; 214 215 pa_mainloop_wakeup(e->mainloop); 216} 217 218static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) { 219 pa_assert(e); 220 221 e->destroy_callback = callback; 222} 223 224/* Defer events */ 225static pa_defer_event* mainloop_defer_new( 226 pa_mainloop_api *a, 227 pa_defer_event_cb_t callback, 228 void *userdata) { 229 230 pa_mainloop *m; 231 pa_defer_event *e; 232 233 pa_assert(a); 234 pa_assert(a->userdata); 235 pa_assert(callback); 236 237 m = a->userdata; 238 pa_assert(a == &m->api); 239 240 e = pa_xnew0(pa_defer_event, 1); 241 e->mainloop = m; 242 243 e->enabled = true; 244 m->n_enabled_defer_events++; 245 246 e->callback = callback; 247 e->userdata = userdata; 248 249 PA_LLIST_PREPEND(pa_defer_event, m->defer_events, e); 250 251 pa_mainloop_wakeup(e->mainloop); 252 253 return e; 254} 255 256static void mainloop_defer_enable(pa_defer_event *e, int b) { 257 pa_assert(e); 258 pa_assert(!e->dead); 259 260 if (e->enabled && !b) { 261 pa_assert(e->mainloop->n_enabled_defer_events > 0); 262 e->mainloop->n_enabled_defer_events--; 263 } else if (!e->enabled && b) { 264 e->mainloop->n_enabled_defer_events++; 265 pa_mainloop_wakeup(e->mainloop); 266 } 267 268 e->enabled = b; 269} 270 271static void mainloop_defer_free(pa_defer_event *e) { 272 pa_assert(e); 273 pa_assert(!e->dead); 274 275 e->dead = true; 276 e->mainloop->defer_events_please_scan ++; 277 278 if (e->enabled) { 279 pa_assert(e->mainloop->n_enabled_defer_events > 0); 280 e->mainloop->n_enabled_defer_events--; 281 e->enabled = false; 282 } 283} 284 285static void mainloop_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t callback) { 286 pa_assert(e); 287 pa_assert(!e->dead); 288 289 e->destroy_callback = callback; 290} 291 292/* Time events */ 293static pa_usec_t make_rt(const struct timeval *tv, bool *use_rtclock) { 294 struct timeval ttv; 295 296 if (!tv) { 297 *use_rtclock = false; 298 return PA_USEC_INVALID; 299 } 300 301 ttv = *tv; 302 *use_rtclock = !!(ttv.tv_usec & PA_TIMEVAL_RTCLOCK); 303 304 if (*use_rtclock) 305 ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK; 306 else 307 pa_rtclock_from_wallclock(&ttv); 308 309 return pa_timeval_load(&ttv); 310} 311 312static pa_time_event* mainloop_time_new( 313 pa_mainloop_api *a, 314 const struct timeval *tv, 315 pa_time_event_cb_t callback, 316 void *userdata) { 317 318 pa_mainloop *m; 319 pa_time_event *e; 320 pa_usec_t t; 321 bool use_rtclock = false; 322 323 pa_assert(a); 324 pa_assert(a->userdata); 325 pa_assert(callback); 326 327 t = make_rt(tv, &use_rtclock); 328 329 m = a->userdata; 330 pa_assert(a == &m->api); 331 332 e = pa_xnew0(pa_time_event, 1); 333 e->mainloop = m; 334 335 if ((e->enabled = (t != PA_USEC_INVALID))) { 336 e->time = t; 337 e->use_rtclock = use_rtclock; 338 339 m->n_enabled_time_events++; 340 341 if (m->cached_next_time_event) { 342 pa_assert(m->cached_next_time_event->enabled); 343 344 if (t < m->cached_next_time_event->time) 345 m->cached_next_time_event = e; 346 } 347 } 348 349 e->callback = callback; 350 e->userdata = userdata; 351 352 PA_LLIST_PREPEND(pa_time_event, m->time_events, e); 353 354 if (e->enabled) 355 pa_mainloop_wakeup(m); 356 357 return e; 358} 359 360static void mainloop_time_restart(pa_time_event *e, const struct timeval *tv) { 361 bool valid; 362 pa_usec_t t; 363 bool use_rtclock = false; 364 365 pa_assert(e); 366 pa_assert(!e->dead); 367 368 t = make_rt(tv, &use_rtclock); 369 370 valid = (t != PA_USEC_INVALID); 371 if (e->enabled && !valid) { 372 pa_assert(e->mainloop->n_enabled_time_events > 0); 373 e->mainloop->n_enabled_time_events--; 374 } else if (!e->enabled && valid) 375 e->mainloop->n_enabled_time_events++; 376 377 if ((e->enabled = valid)) { 378 e->time = t; 379 e->use_rtclock = use_rtclock; 380 pa_mainloop_wakeup(e->mainloop); 381 } 382 383 if (e->mainloop->cached_next_time_event == e) 384 e->mainloop->cached_next_time_event = NULL; 385 386 if (e->mainloop->cached_next_time_event && e->enabled) { 387 pa_assert(e->mainloop->cached_next_time_event->enabled); 388 389 if (t < e->mainloop->cached_next_time_event->time) 390 e->mainloop->cached_next_time_event = e; 391 } 392} 393 394static void mainloop_time_free(pa_time_event *e) { 395 pa_assert(e); 396 pa_assert(!e->dead); 397 398 e->dead = true; 399 e->mainloop->time_events_please_scan ++; 400 401 if (e->enabled) { 402 pa_assert(e->mainloop->n_enabled_time_events > 0); 403 e->mainloop->n_enabled_time_events--; 404 e->enabled = false; 405 } 406 407 if (e->mainloop->cached_next_time_event == e) 408 e->mainloop->cached_next_time_event = NULL; 409 410 /* no wakeup needed here. Think about it! */ 411} 412 413static void mainloop_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t callback) { 414 pa_assert(e); 415 pa_assert(!e->dead); 416 417 e->destroy_callback = callback; 418} 419 420/* quit() */ 421 422static void mainloop_quit(pa_mainloop_api *a, int retval) { 423 pa_mainloop *m; 424 425 pa_assert(a); 426 pa_assert(a->userdata); 427 m = a->userdata; 428 pa_assert(a == &m->api); 429 430 pa_mainloop_quit(m, retval); 431} 432 433static const pa_mainloop_api vtable = { 434 .userdata = NULL, 435 436 .io_new = mainloop_io_new, 437 .io_enable = mainloop_io_enable, 438 .io_free = mainloop_io_free, 439 .io_set_destroy = mainloop_io_set_destroy, 440 441 .time_new = mainloop_time_new, 442 .time_restart = mainloop_time_restart, 443 .time_free = mainloop_time_free, 444 .time_set_destroy = mainloop_time_set_destroy, 445 446 .defer_new = mainloop_defer_new, 447 .defer_enable = mainloop_defer_enable, 448 .defer_free = mainloop_defer_free, 449 .defer_set_destroy = mainloop_defer_set_destroy, 450 451 .quit = mainloop_quit, 452}; 453 454pa_mainloop *pa_mainloop_new(void) { 455 pa_mainloop *m; 456 457#ifdef OS_IS_WIN32 458 { 459 int r; 460 WSADATA data; 461 if ((r = WSAStartup(MAKEWORD(2, 0), &data))) { 462 pa_log_error("ERROR: cannot initialize Winsock2 (%d)", r); 463 return NULL; 464 } 465 } 466#endif 467 468 pa_init_i18n(); 469 470 m = pa_xnew0(pa_mainloop, 1); 471 472 if (pa_pipe_cloexec(m->wakeup_pipe) < 0) { 473 pa_log_error("ERROR: cannot create wakeup pipe"); 474 pa_xfree(m); 475 return NULL; 476 } 477 478 pa_make_fd_nonblock(m->wakeup_pipe[0]); 479 pa_make_fd_nonblock(m->wakeup_pipe[1]); 480 481 m->rebuild_pollfds = true; 482 483 m->api = vtable; 484 m->api.userdata = m; 485 486 m->state = STATE_PASSIVE; 487 488 m->poll_func_ret = -1; 489 490 return m; 491} 492 493static void cleanup_io_events(pa_mainloop *m, bool force) { 494 pa_io_event *e, *n; 495 496 PA_LLIST_FOREACH_SAFE(e, n, m->io_events) { 497 498 if (!force && m->io_events_please_scan <= 0) 499 break; 500 501 if (force || e->dead) { 502 PA_LLIST_REMOVE(pa_io_event, m->io_events, e); 503 504 if (e->dead) { 505 pa_assert(m->io_events_please_scan > 0); 506 m->io_events_please_scan--; 507 } 508 509 if (e->destroy_callback) 510 e->destroy_callback(&m->api, e, e->userdata); 511 512 pa_xfree(e); 513 514 m->rebuild_pollfds = true; 515 } 516 } 517 518 pa_assert(m->io_events_please_scan == 0); 519} 520 521static void cleanup_time_events(pa_mainloop *m, bool force) { 522 pa_time_event *e, *n; 523 524 PA_LLIST_FOREACH_SAFE(e, n, m->time_events) { 525 526 if (!force && m->time_events_please_scan <= 0) 527 break; 528 529 if (force || e->dead) { 530 PA_LLIST_REMOVE(pa_time_event, m->time_events, e); 531 532 if (e->dead) { 533 pa_assert(m->time_events_please_scan > 0); 534 m->time_events_please_scan--; 535 } 536 537 if (!e->dead && e->enabled) { 538 pa_assert(m->n_enabled_time_events > 0); 539 m->n_enabled_time_events--; 540 e->enabled = false; 541 } 542 543 if (e->destroy_callback) 544 e->destroy_callback(&m->api, e, e->userdata); 545 546 pa_xfree(e); 547 } 548 } 549 550 pa_assert(m->time_events_please_scan == 0); 551} 552 553static void cleanup_defer_events(pa_mainloop *m, bool force) { 554 pa_defer_event *e, *n; 555 556 PA_LLIST_FOREACH_SAFE(e, n, m->defer_events) { 557 558 if (!force && m->defer_events_please_scan <= 0) 559 break; 560 561 if (force || e->dead) { 562 PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e); 563 564 if (e->dead) { 565 pa_assert(m->defer_events_please_scan > 0); 566 m->defer_events_please_scan--; 567 } 568 569 if (!e->dead && e->enabled) { 570 pa_assert(m->n_enabled_defer_events > 0); 571 m->n_enabled_defer_events--; 572 e->enabled = false; 573 } 574 575 if (e->destroy_callback) 576 e->destroy_callback(&m->api, e, e->userdata); 577 578 pa_xfree(e); 579 } 580 } 581 582 pa_assert(m->defer_events_please_scan == 0); 583} 584 585void pa_mainloop_free(pa_mainloop *m) { 586 pa_assert(m); 587 588 cleanup_io_events(m, true); 589 cleanup_defer_events(m, true); 590 cleanup_time_events(m, true); 591 592 pa_xfree(m->pollfds); 593 594 pa_close_pipe(m->wakeup_pipe); 595 596 pa_xfree(m); 597 598#ifdef OS_IS_WIN32 599 { 600 WSACleanup(); 601 } 602#endif 603} 604 605static void scan_dead(pa_mainloop *m) { 606 pa_assert(m); 607 608 if (m->io_events_please_scan) 609 cleanup_io_events(m, false); 610 611 if (m->time_events_please_scan) 612 cleanup_time_events(m, false); 613 614 if (m->defer_events_please_scan) 615 cleanup_defer_events(m, false); 616} 617 618static void rebuild_pollfds(pa_mainloop *m) { 619 pa_io_event*e; 620 struct pollfd *p; 621 unsigned l; 622 623 l = m->n_io_events + 1; 624 if (m->max_pollfds < l) { 625 l *= 2; 626 m->pollfds = pa_xrealloc(m->pollfds, sizeof(struct pollfd)*l); 627 m->max_pollfds = l; 628 } 629 630 m->n_pollfds = 0; 631 p = m->pollfds; 632 633 m->pollfds[0].fd = m->wakeup_pipe[0]; 634 m->pollfds[0].events = POLLIN; 635 m->pollfds[0].revents = 0; 636 p++; 637 m->n_pollfds++; 638 639 PA_LLIST_FOREACH(e, m->io_events) { 640 if (e->dead) { 641 e->pollfd = NULL; 642 continue; 643 } 644 645 e->pollfd = p; 646 p->fd = e->fd; 647 p->events = map_flags_to_libc(e->events); 648 p->revents = 0; 649 650 p++; 651 m->n_pollfds++; 652 } 653 654 m->rebuild_pollfds = false; 655} 656 657static unsigned dispatch_pollfds(pa_mainloop *m) { 658 pa_io_event *e; 659 unsigned r = 0, k; 660 661 pa_assert(m->poll_func_ret > 0); 662 663 k = m->poll_func_ret; 664 665 PA_LLIST_FOREACH(e, m->io_events) { 666 667 if (k <= 0 || m->quit) 668 break; 669 670 if (e->dead || !e->pollfd || !e->pollfd->revents) 671 continue; 672 673 pa_assert(e->pollfd->fd == e->fd); 674 pa_assert(e->callback); 675 676 e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata); 677 e->pollfd->revents = 0; 678 r++; 679 k--; 680 } 681 682 return r; 683} 684 685static unsigned dispatch_defer(pa_mainloop *m) { 686 pa_defer_event *e; 687 unsigned r = 0; 688 689 if (m->n_enabled_defer_events <= 0) 690 return 0; 691 692 PA_LLIST_FOREACH(e, m->defer_events) { 693 694 if (m->quit) 695 break; 696 697 if (e->dead || !e->enabled) 698 continue; 699 700 pa_assert(e->callback); 701 e->callback(&m->api, e, e->userdata); 702 r++; 703 } 704 705 return r; 706} 707 708static pa_time_event* find_next_time_event(pa_mainloop *m) { 709 pa_time_event *t, *n = NULL; 710 pa_assert(m); 711 712 if (m->cached_next_time_event) 713 return m->cached_next_time_event; 714 715 PA_LLIST_FOREACH(t, m->time_events) { 716 717 if (t->dead || !t->enabled) 718 continue; 719 720 if (!n || t->time < n->time) { 721 n = t; 722 723 /* Shortcut for time == 0 */ 724 if (n->time == 0) 725 break; 726 } 727 } 728 729 m->cached_next_time_event = n; 730 return n; 731} 732 733static pa_usec_t calc_next_timeout(pa_mainloop *m) { 734 pa_time_event *t; 735 pa_usec_t clock_now; 736 737 if (m->n_enabled_time_events <= 0) 738 return PA_USEC_INVALID; 739 740 pa_assert_se(t = find_next_time_event(m)); 741 742 if (t->time <= 0) 743 return 0; 744 745 clock_now = pa_rtclock_now(); 746 747 if (t->time <= clock_now) 748 return 0; 749 750 return t->time - clock_now; 751} 752 753static unsigned dispatch_timeout(pa_mainloop *m) { 754 pa_time_event *e; 755 pa_usec_t now; 756 unsigned r = 0; 757 pa_assert(m); 758 759 if (m->n_enabled_time_events <= 0) 760 return 0; 761 762 now = pa_rtclock_now(); 763 764 PA_LLIST_FOREACH(e, m->time_events) { 765 766 if (m->quit) 767 break; 768 769 if (e->dead || !e->enabled) 770 continue; 771 772 if (e->time <= now) { 773 struct timeval tv; 774 pa_assert(e->callback); 775 776 /* Disable time event */ 777 mainloop_time_restart(e, NULL); 778 779 e->callback(&m->api, e, pa_timeval_rtstore(&tv, e->time, e->use_rtclock), e->userdata); 780 781 r++; 782 } 783 } 784 785 return r; 786} 787 788void pa_mainloop_wakeup(pa_mainloop *m) { 789 char c = 'W'; 790 pa_assert(m); 791 792 if (pa_write(m->wakeup_pipe[1], &c, sizeof(c), &m->wakeup_pipe_type) < 0) 793 /* Not many options for recovering from the error. Let's at least log something. */ 794 pa_log("pa_write() failed while trying to wake up the mainloop: %s", pa_cstrerror(errno)); 795} 796 797static void clear_wakeup(pa_mainloop *m) { 798 char c[10]; 799 800 pa_assert(m); 801 802 while (pa_read(m->wakeup_pipe[0], &c, sizeof(c), &m->wakeup_pipe_type) == sizeof(c)) 803 ; 804} 805 806int pa_mainloop_prepare(pa_mainloop *m, int timeout) { 807 pa_assert(m); 808 pa_assert(m->state == STATE_PASSIVE); 809 810 clear_wakeup(m); 811 scan_dead(m); 812 813 if (m->quit) 814 goto quit; 815 816 if (m->n_enabled_defer_events <= 0) { 817 818 if (m->rebuild_pollfds) 819 rebuild_pollfds(m); 820 821 m->prepared_timeout = calc_next_timeout(m); 822 if (timeout >= 0) { 823 if (timeout < m->prepared_timeout || m->prepared_timeout == PA_USEC_INVALID) 824 m->prepared_timeout = timeout; 825 } 826 } 827 828 m->state = STATE_PREPARED; 829 return 0; 830 831quit: 832 m->state = STATE_QUIT; 833 return -2; 834} 835 836static int usec_to_timeout(pa_usec_t u) { 837 int timeout; 838 839 if (u == PA_USEC_INVALID) 840 return -1; 841 842 timeout = (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC; 843 pa_assert(timeout >= 0); 844 845 return timeout; 846} 847 848int pa_mainloop_poll(pa_mainloop *m) { 849 pa_assert(m); 850 pa_assert(m->state == STATE_PREPARED); 851 852 if (m->quit) 853 goto quit; 854 855 m->state = STATE_POLLING; 856 857 if (m->n_enabled_defer_events) 858 m->poll_func_ret = 0; 859 else { 860 pa_assert(!m->rebuild_pollfds); 861 862 if (m->poll_func) 863 m->poll_func_ret = m->poll_func( 864 m->pollfds, m->n_pollfds, 865 usec_to_timeout(m->prepared_timeout), 866 m->poll_func_userdata); 867 else { 868#ifdef HAVE_PPOLL 869 struct timespec ts; 870 871 m->poll_func_ret = ppoll( 872 m->pollfds, m->n_pollfds, 873 m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout), 874 NULL); 875#else 876 m->poll_func_ret = pa_poll( 877 m->pollfds, m->n_pollfds, 878 usec_to_timeout(m->prepared_timeout)); 879#endif 880 } 881 882 if (m->poll_func_ret < 0) { 883 if (errno == EINTR) 884 m->poll_func_ret = 0; 885 else 886 pa_log("poll(): %s", pa_cstrerror(errno)); 887 } 888 } 889 890 m->state = m->poll_func_ret < 0 ? STATE_PASSIVE : STATE_POLLED; 891 return m->poll_func_ret; 892 893quit: 894 m->state = STATE_QUIT; 895 return -2; 896} 897 898int pa_mainloop_dispatch(pa_mainloop *m) { 899 unsigned dispatched = 0; 900 901 pa_assert(m); 902 pa_assert(m->state == STATE_POLLED); 903 904 if (m->quit) 905 goto quit; 906 907 if (m->n_enabled_defer_events) 908 dispatched += dispatch_defer(m); 909 else { 910 if (m->n_enabled_time_events) 911 dispatched += dispatch_timeout(m); 912 913 if (m->quit) 914 goto quit; 915 916 if (m->poll_func_ret > 0) 917 dispatched += dispatch_pollfds(m); 918 } 919 920 if (m->quit) 921 goto quit; 922 923 m->state = STATE_PASSIVE; 924 925 return (int) dispatched; 926 927quit: 928 m->state = STATE_QUIT; 929 return -2; 930} 931 932int pa_mainloop_get_retval(const pa_mainloop *m) { 933 pa_assert(m); 934 935 return m->retval; 936} 937 938int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval) { 939 int r; 940 pa_assert(m); 941 942 if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0) 943 goto quit; 944 945 if ((r = pa_mainloop_poll(m)) < 0) 946 goto quit; 947 948 if ((r = pa_mainloop_dispatch(m)) < 0) 949 goto quit; 950 951 return r; 952 953quit: 954 955 if ((r == -2) && retval) 956 *retval = pa_mainloop_get_retval(m); 957 return r; 958} 959 960int pa_mainloop_run(pa_mainloop *m, int *retval) { 961 int r; 962 963 while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0) 964 ; 965 966 if (r == -2) { 967 pa_log_error("mainloop exit with code -2"); 968 return 1; 969 } else { 970 pa_log_error("mainloop exit with code -1"); 971 return -1; 972 } 973} 974 975void pa_mainloop_quit(pa_mainloop *m, int retval) { 976 pa_assert(m); 977 978 m->quit = true; 979 m->retval = retval; 980 pa_mainloop_wakeup(m); 981} 982 983pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) { 984 pa_assert(m); 985 986 return &m->api; 987} 988 989void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) { 990 pa_assert(m); 991 992 m->poll_func = poll_func; 993 m->poll_func_userdata = userdata; 994} 995 996bool pa_mainloop_is_our_api(const pa_mainloop_api *m) { 997 pa_assert(m); 998 999 return m->io_new == mainloop_io_new; 1000} 1001