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
56 struct 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
71 struct 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
86 struct 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
99 struct 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
map_flags_to_libc(pa_io_event_flags_t flags)135 static 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
map_flags_from_libc(short flags)143 static 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 */
mainloop_io_new(pa_mainloop_api * a,int fd,pa_io_event_flags_t events,pa_io_event_cb_t callback,void * userdata)152 static 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
mainloop_io_enable(pa_io_event * e,pa_io_event_flags_t events)188 static 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
mainloop_io_free(pa_io_event * e)205 static 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
mainloop_io_set_destroy(pa_io_event * e,pa_io_event_destroy_cb_t callback)218 static 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 */
mainloop_defer_new(pa_mainloop_api * a,pa_defer_event_cb_t callback,void * userdata)225 static 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
mainloop_defer_enable(pa_defer_event * e,int b)256 static 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
mainloop_defer_free(pa_defer_event * e)271 static 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
mainloop_defer_set_destroy(pa_defer_event * e,pa_defer_event_destroy_cb_t callback)285 static 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 */
make_rt(const struct timeval * tv,bool * use_rtclock)293 static 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
mainloop_time_new(pa_mainloop_api * a,const struct timeval * tv,pa_time_event_cb_t callback,void * userdata)312 static 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
mainloop_time_restart(pa_time_event * e,const struct timeval * tv)360 static 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
mainloop_time_free(pa_time_event * e)394 static 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
mainloop_time_set_destroy(pa_time_event * e,pa_time_event_destroy_cb_t callback)413 static 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
mainloop_quit(pa_mainloop_api * a,int retval)422 static 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
433 static 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
pa_mainloop_new(void)454 pa_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
cleanup_io_events(pa_mainloop * m,bool force)493 static 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
cleanup_time_events(pa_mainloop * m,bool force)521 static 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
cleanup_defer_events(pa_mainloop * m,bool force)553 static 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
pa_mainloop_free(pa_mainloop * m)585 void 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
scan_dead(pa_mainloop * m)605 static 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
rebuild_pollfds(pa_mainloop * m)618 static 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
dispatch_pollfds(pa_mainloop * m)657 static 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
dispatch_defer(pa_mainloop * m)685 static 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
find_next_time_event(pa_mainloop * m)708 static 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
calc_next_timeout(pa_mainloop * m)733 static 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
dispatch_timeout(pa_mainloop * m)753 static 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
pa_mainloop_wakeup(pa_mainloop * m)788 void 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
clear_wakeup(pa_mainloop * m)797 static 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
pa_mainloop_prepare(pa_mainloop * m,int timeout)806 int 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
831 quit:
832 m->state = STATE_QUIT;
833 return -2;
834 }
835
usec_to_timeout(pa_usec_t u)836 static 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
pa_mainloop_poll(pa_mainloop * m)848 int 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
893 quit:
894 m->state = STATE_QUIT;
895 return -2;
896 }
897
pa_mainloop_dispatch(pa_mainloop * m)898 int 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
927 quit:
928 m->state = STATE_QUIT;
929 return -2;
930 }
931
pa_mainloop_get_retval(const pa_mainloop * m)932 int pa_mainloop_get_retval(const pa_mainloop *m) {
933 pa_assert(m);
934
935 return m->retval;
936 }
937
pa_mainloop_iterate(pa_mainloop * m,int block,int * retval)938 int 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
953 quit:
954
955 if ((r == -2) && retval)
956 *retval = pa_mainloop_get_retval(m);
957 return r;
958 }
959
pa_mainloop_run(pa_mainloop * m,int * retval)960 int 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 return 1;
968 else
969 return -1;
970 }
971
pa_mainloop_quit(pa_mainloop * m,int retval)972 void pa_mainloop_quit(pa_mainloop *m, int retval) {
973 pa_assert(m);
974
975 m->quit = true;
976 m->retval = retval;
977 pa_mainloop_wakeup(m);
978 }
979
pa_mainloop_get_api(pa_mainloop * m)980 pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) {
981 pa_assert(m);
982
983 return &m->api;
984 }
985
pa_mainloop_set_poll_func(pa_mainloop * m,pa_poll_func poll_func,void * userdata)986 void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
987 pa_assert(m);
988
989 m->poll_func = poll_func;
990 m->poll_func_userdata = userdata;
991 }
992
pa_mainloop_is_our_api(const pa_mainloop_api * m)993 bool pa_mainloop_is_our_api(const pa_mainloop_api *m) {
994 pa_assert(m);
995
996 return m->io_new == mainloop_io_new;
997 }
998