xref: /third_party/pulseaudio/src/pulse/mainloop.c (revision 53a5a1b3)
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
56struct 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
71struct 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
86struct 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
99struct 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
135static 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
143static 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 */
152static 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
188static 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
205static 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
218static 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 */
225static 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
256static 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
271static 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
285static 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 */
293static 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
312static 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
360static 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
394static 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
413static 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
422static 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
433static 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
454pa_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
493static 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
521static 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
553static 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
585void 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
605static 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
618static 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
657static 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
685static 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
708static 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
733static 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
753static 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
788void 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
797static 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
806int 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
831quit:
832    m->state = STATE_QUIT;
833    return -2;
834}
835
836static 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
848int 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
893quit:
894    m->state = STATE_QUIT;
895    return -2;
896}
897
898int 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
927quit:
928    m->state = STATE_QUIT;
929    return -2;
930}
931
932int pa_mainloop_get_retval(const pa_mainloop *m) {
933    pa_assert(m);
934
935    return m->retval;
936}
937
938int 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
953quit:
954
955    if ((r == -2) && retval)
956        *retval = pa_mainloop_get_retval(m);
957    return r;
958}
959
960int 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        pa_log_error("mainloop exit with code -2");
968        return 1;
969    } else {
970        pa_log_error("mainloop exit with code -1");
971        return -1;
972    }
973}
974
975void pa_mainloop_quit(pa_mainloop *m, int retval) {
976    pa_assert(m);
977
978    m->quit = true;
979    m->retval = retval;
980    pa_mainloop_wakeup(m);
981}
982
983pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m) {
984    pa_assert(m);
985
986    return &m->api;
987}
988
989void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) {
990    pa_assert(m);
991
992    m->poll_func = poll_func;
993    m->poll_func_userdata = userdata;
994}
995
996bool pa_mainloop_is_our_api(const pa_mainloop_api *m) {
997    pa_assert(m);
998
999    return m->io_new == mainloop_io_new;
1000}
1001