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