• 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 "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