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