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