• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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