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