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