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