]> code.delx.au - pulseaudio/blob - src/pulsecore/rtpoll.c
commit glitch-free work
[pulseaudio] / src / pulsecore / rtpoll.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as
11 published by the Free Software Foundation; either version 2.1 of the
12 License, or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <signal.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #ifdef __linux__
36 #include <sys/utsname.h>
37 #endif
38
39 #ifdef HAVE_POLL_H
40 #include <poll.h>
41 #else
42 #include <pulsecore/poll.h>
43 #endif
44
45 #include <pulse/xmalloc.h>
46 #include <pulse/timeval.h>
47
48 #include <pulsecore/core-error.h>
49 #include <pulsecore/rtclock.h>
50 #include <pulsecore/macro.h>
51 #include <pulsecore/llist.h>
52 #include <pulsecore/rtsig.h>
53 #include <pulsecore/flist.h>
54 #include <pulsecore/core-util.h>
55
56 #include <pulsecore/winsock.h>
57
58 #include "rtpoll.h"
59
60 struct pa_rtpoll {
61 struct pollfd *pollfd, *pollfd2;
62 unsigned n_pollfd_alloc, n_pollfd_used;
63
64 pa_bool_t timer_enabled;
65 struct timeval next_elapse;
66 pa_usec_t period;
67
68 pa_bool_t scan_for_dead;
69 pa_bool_t running, installed, rebuild_needed, quit;
70
71 #ifdef HAVE_PPOLL
72 int rtsig;
73 sigset_t sigset_unblocked;
74 timer_t timer;
75 #ifdef __linux__
76 pa_bool_t dont_use_ppoll;
77 #endif
78 #endif
79
80 PA_LLIST_HEAD(pa_rtpoll_item, items);
81 };
82
83 struct pa_rtpoll_item {
84 pa_rtpoll *rtpoll;
85 pa_bool_t dead;
86
87 pa_rtpoll_priority_t priority;
88
89 struct pollfd *pollfd;
90 unsigned n_pollfd;
91
92 int (*work_cb)(pa_rtpoll_item *i);
93 int (*before_cb)(pa_rtpoll_item *i);
94 void (*after_cb)(pa_rtpoll_item *i);
95 void *userdata;
96
97 PA_LLIST_FIELDS(pa_rtpoll_item);
98 };
99
100 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
101
102 static void signal_handler_noop(int s) { write(2, "signal\n", 7); }
103
104 pa_rtpoll *pa_rtpoll_new(void) {
105 pa_rtpoll *p;
106
107 p = pa_xnew(pa_rtpoll, 1);
108
109 #ifdef HAVE_PPOLL
110
111 #ifdef __linux__
112 /* ppoll is broken on Linux < 2.6.16 */
113 p->dont_use_ppoll = FALSE;
114
115 {
116 struct utsname u;
117 unsigned major, minor, micro;
118
119 pa_assert_se(uname(&u) == 0);
120
121 if (sscanf(u.release, "%u.%u.%u", &major, &minor, &micro) != 3 ||
122 (major < 2) ||
123 (major == 2 && minor < 6) ||
124 (major == 2 && minor == 6 && micro < 16))
125
126 p->dont_use_ppoll = TRUE;
127 }
128
129 #endif
130
131 p->rtsig = -1;
132 sigemptyset(&p->sigset_unblocked);
133 p->timer = (timer_t) -1;
134
135 #endif
136
137 p->n_pollfd_alloc = 32;
138 p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc);
139 p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
140 p->n_pollfd_used = 0;
141
142 p->period = 0;
143 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
144 p->timer_enabled = FALSE;
145
146 p->running = FALSE;
147 p->installed = FALSE;
148 p->scan_for_dead = FALSE;
149 p->rebuild_needed = FALSE;
150 p->quit = FALSE;
151
152 PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items);
153
154 return p;
155 }
156
157 void pa_rtpoll_install(pa_rtpoll *p) {
158 pa_assert(p);
159 pa_assert(!p->installed);
160
161 p->installed = 1;
162
163 #ifdef HAVE_PPOLL
164 # ifdef __linux__
165 if (p->dont_use_ppoll)
166 return;
167 # endif
168
169 if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) {
170 pa_log_warn("Failed to reserve POSIX realtime signal.");
171 return;
172 }
173
174 pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig));
175
176 {
177 sigset_t ss;
178 struct sigaction sa;
179
180 pa_assert_se(sigemptyset(&ss) == 0);
181 pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
182 pa_assert_se(pthread_sigmask(SIG_BLOCK, &ss, &p->sigset_unblocked) == 0);
183 pa_assert_se(sigdelset(&p->sigset_unblocked, p->rtsig) == 0);
184
185 memset(&sa, 0, sizeof(sa));
186 sa.sa_handler = signal_handler_noop;
187 pa_assert_se(sigemptyset(&sa.sa_mask) == 0);
188
189 pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0);
190
191 /* We never reset the signal handler. Why should we? */
192 }
193
194 #endif
195 }
196
197 static void rtpoll_rebuild(pa_rtpoll *p) {
198
199 struct pollfd *e, *t;
200 pa_rtpoll_item *i;
201 int ra = 0;
202
203 pa_assert(p);
204
205 p->rebuild_needed = FALSE;
206
207 if (p->n_pollfd_used > p->n_pollfd_alloc) {
208 /* Hmm, we have to allocate some more space */
209 p->n_pollfd_alloc = p->n_pollfd_used * 2;
210 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
211 ra = 1;
212 }
213
214 e = p->pollfd2;
215
216 for (i = p->items; i; i = i->next) {
217
218 if (i->n_pollfd > 0) {
219 size_t l = i->n_pollfd * sizeof(struct pollfd);
220
221 if (i->pollfd)
222 memcpy(e, i->pollfd, l);
223 else
224 memset(e, 0, l);
225
226 i->pollfd = e;
227 } else
228 i->pollfd = NULL;
229
230 e += i->n_pollfd;
231 }
232
233 pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used);
234 t = p->pollfd;
235 p->pollfd = p->pollfd2;
236 p->pollfd2 = t;
237
238 if (ra)
239 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
240
241 }
242
243 static void rtpoll_item_destroy(pa_rtpoll_item *i) {
244 pa_rtpoll *p;
245
246 pa_assert(i);
247
248 p = i->rtpoll;
249
250 PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
251
252 p->n_pollfd_used -= i->n_pollfd;
253
254 if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
255 pa_xfree(i);
256
257 p->rebuild_needed = TRUE;
258 }
259
260 void pa_rtpoll_free(pa_rtpoll *p) {
261 pa_assert(p);
262
263 while (p->items)
264 rtpoll_item_destroy(p->items);
265
266 pa_xfree(p->pollfd);
267 pa_xfree(p->pollfd2);
268
269 #ifdef HAVE_PPOLL
270 if (p->timer != (timer_t) -1)
271 timer_delete(p->timer);
272 #endif
273
274 pa_xfree(p);
275 }
276
277 static void reset_revents(pa_rtpoll_item *i) {
278 struct pollfd *f;
279 unsigned n;
280
281 pa_assert(i);
282
283 if (!(f = pa_rtpoll_item_get_pollfd(i, &n)))
284 return;
285
286 for (; n > 0; n--)
287 f[n-1].revents = 0;
288 }
289
290 static void reset_all_revents(pa_rtpoll *p) {
291 pa_rtpoll_item *i;
292
293 pa_assert(p);
294
295 for (i = p->items; i; i = i->next) {
296
297 if (i->dead)
298 continue;
299
300 reset_revents(i);
301 }
302 }
303
304 int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
305 pa_rtpoll_item *i;
306 int r = 0;
307 struct timeval timeout;
308
309 pa_assert(p);
310 pa_assert(!p->running);
311 pa_assert(p->installed);
312
313 p->running = TRUE;
314
315 /* First, let's do some work */
316 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
317 int k;
318
319 if (i->dead)
320 continue;
321
322 if (!i->work_cb)
323 continue;
324
325 if (p->quit)
326 goto finish;
327
328 if ((k = i->work_cb(i)) != 0) {
329 if (k < 0)
330 r = k;
331
332 goto finish;
333 }
334 }
335
336 /* Now let's prepare for entering the sleep */
337 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
338 int k = 0;
339
340 if (i->dead)
341 continue;
342
343 if (!i->before_cb)
344 continue;
345
346 if (p->quit || (k = i->before_cb(i)) != 0) {
347
348 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
349
350 for (i = i->prev; i; i = i->prev) {
351
352 if (i->dead)
353 continue;
354
355 if (!i->after_cb)
356 continue;
357
358 i->after_cb(i);
359 }
360
361 if (k < 0)
362 r = k;
363
364 goto finish;
365 }
366 }
367
368 if (p->rebuild_needed)
369 rtpoll_rebuild(p);
370
371 /* Calculate timeout */
372 if (!wait || p->quit) {
373 timeout.tv_sec = 0;
374 timeout.tv_usec = 0;
375 } else if (p->timer_enabled) {
376 struct timeval now;
377 pa_rtclock_get(&now);
378
379 memset(&timeout, 0, sizeof(timeout));
380 if (pa_timeval_cmp(&p->next_elapse, &now) > 0)
381 pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now));
382 }
383
384 /* OK, now let's sleep */
385 #ifdef HAVE_PPOLL
386
387 #ifdef __linux__
388 if (!p->dont_use_ppoll)
389 #endif
390 {
391 struct timespec ts;
392 ts.tv_sec = timeout.tv_sec;
393 ts.tv_nsec = timeout.tv_usec * 1000;
394 r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? &ts : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
395 }
396 #ifdef __linux__
397 else
398 #endif
399
400 #endif
401 r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? (timeout.tv_sec*1000) + (timeout.tv_usec / 1000) : -1);
402
403 if (r < 0) {
404 if (errno == EAGAIN || errno == EINTR)
405 r = 0;
406 else
407 pa_log_error("poll(): %s", pa_cstrerror(errno));
408
409 reset_all_revents(p);
410 }
411
412 if (p->timer_enabled) {
413 if (p->period > 0) {
414 struct timeval now;
415 pa_rtclock_get(&now);
416
417 pa_timeval_add(&p->next_elapse, p->period);
418
419 /* Guarantee that the next timeout will happen in the future */
420 if (pa_timeval_cmp(&p->next_elapse, &now) < 0)
421 pa_timeval_add(&p->next_elapse, (pa_timeval_diff(&now, &p->next_elapse) / p->period + 1) * p->period);
422
423 } else
424 p->timer_enabled = FALSE;
425 }
426
427 /* Let's tell everyone that we left the sleep */
428 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
429
430 if (i->dead)
431 continue;
432
433 if (!i->after_cb)
434 continue;
435
436 i->after_cb(i);
437 }
438
439 finish:
440
441 p->running = FALSE;
442
443 if (p->scan_for_dead) {
444 pa_rtpoll_item *n;
445
446 p->scan_for_dead = FALSE;
447
448 for (i = p->items; i; i = n) {
449 n = i->next;
450
451 if (i->dead)
452 rtpoll_item_destroy(i);
453 }
454 }
455
456 return r < 0 ? r : !p->quit;
457 }
458
459 static void update_timer(pa_rtpoll *p) {
460 pa_assert(p);
461
462 #ifdef HAVE_PPOLL
463
464 #ifdef __linux__
465 if (!p->dont_use_ppoll) {
466 #endif
467
468 if (p->timer == (timer_t) -1) {
469 struct sigevent se;
470
471 memset(&se, 0, sizeof(se));
472 se.sigev_notify = SIGEV_SIGNAL;
473 se.sigev_signo = p->rtsig;
474
475 if (timer_create(CLOCK_MONOTONIC, &se, &p->timer) < 0)
476 if (timer_create(CLOCK_REALTIME, &se, &p->timer) < 0) {
477 pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno));
478 p->timer = (timer_t) -1;
479 }
480 }
481
482 if (p->timer != (timer_t) -1) {
483 struct itimerspec its;
484 memset(&its, 0, sizeof(its));
485
486 if (p->timer_enabled) {
487 its.it_value.tv_sec = p->next_elapse.tv_sec;
488 its.it_value.tv_nsec = p->next_elapse.tv_usec*1000;
489
490 /* Make sure that 0,0 is not understood as
491 * "disarming" */
492 if (its.it_value.tv_sec == 0)
493 its.it_value.tv_nsec = 1;
494
495 if (p->period > 0) {
496 struct timeval tv;
497 pa_timeval_store(&tv, p->period);
498 its.it_interval.tv_sec = tv.tv_sec;
499 its.it_interval.tv_nsec = tv.tv_usec*1000;
500 }
501 }
502
503 pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
504 }
505
506 #ifdef __linux__
507 }
508 #endif
509
510 #endif
511 }
512
513 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts) {
514 pa_assert(p);
515 pa_assert(ts);
516
517 p->next_elapse = *ts;
518 p->period = 0;
519 p->timer_enabled = TRUE;
520
521 update_timer(p);
522 }
523
524 void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec) {
525 pa_assert(p);
526
527 p->period = usec;
528 pa_rtclock_get(&p->next_elapse);
529 pa_timeval_add(&p->next_elapse, usec);
530 p->timer_enabled = TRUE;
531
532 update_timer(p);
533 }
534
535 void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
536 pa_assert(p);
537
538 p->period = 0;
539 pa_rtclock_get(&p->next_elapse);
540 pa_timeval_add(&p->next_elapse, usec);
541 p->timer_enabled = TRUE;
542
543 update_timer(p);
544 }
545
546 void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
547 pa_assert(p);
548
549 p->period = 0;
550 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
551 p->timer_enabled = FALSE;
552
553 update_timer(p);
554 }
555
556 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
557 pa_rtpoll_item *i, *j, *l = NULL;
558
559 pa_assert(p);
560
561 if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
562 i = pa_xnew(pa_rtpoll_item, 1);
563
564 i->rtpoll = p;
565 i->dead = FALSE;
566 i->n_pollfd = n_fds;
567 i->pollfd = NULL;
568 i->priority = prio;
569
570 i->userdata = NULL;
571 i->before_cb = NULL;
572 i->after_cb = NULL;
573 i->work_cb = NULL;
574
575 for (j = p->items; j; j = j->next) {
576 if (prio <= j->priority)
577 break;
578
579 l = j;
580 }
581
582 PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i);
583
584 if (n_fds > 0) {
585 p->rebuild_needed = 1;
586 p->n_pollfd_used += n_fds;
587 }
588
589 return i;
590 }
591
592 void pa_rtpoll_item_free(pa_rtpoll_item *i) {
593 pa_assert(i);
594
595 if (i->rtpoll->running) {
596 i->dead = TRUE;
597 i->rtpoll->scan_for_dead = TRUE;
598 return;
599 }
600
601 rtpoll_item_destroy(i);
602 }
603
604 struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
605 pa_assert(i);
606
607 if (i->n_pollfd > 0)
608 if (i->rtpoll->rebuild_needed)
609 rtpoll_rebuild(i->rtpoll);
610
611 if (n_fds)
612 *n_fds = i->n_pollfd;
613
614 return i->pollfd;
615 }
616
617 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) {
618 pa_assert(i);
619 pa_assert(i->priority < PA_RTPOLL_NEVER);
620
621 i->before_cb = before_cb;
622 }
623
624 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) {
625 pa_assert(i);
626 pa_assert(i->priority < PA_RTPOLL_NEVER);
627
628 i->after_cb = after_cb;
629 }
630
631 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)) {
632 pa_assert(i);
633 pa_assert(i->priority < PA_RTPOLL_NEVER);
634
635 i->work_cb = work_cb;
636 }
637
638 void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
639 pa_assert(i);
640
641 i->userdata = userdata;
642 }
643
644 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
645 pa_assert(i);
646
647 return i->userdata;
648 }
649
650 static int fdsem_before(pa_rtpoll_item *i) {
651
652 if (pa_fdsem_before_poll(i->userdata) < 0)
653 return 1; /* 1 means immediate restart of the loop */
654
655 return 0;
656 }
657
658 static void fdsem_after(pa_rtpoll_item *i) {
659 pa_assert(i);
660
661 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
662 pa_fdsem_after_poll(i->userdata);
663 }
664
665 pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) {
666 pa_rtpoll_item *i;
667 struct pollfd *pollfd;
668
669 pa_assert(p);
670 pa_assert(f);
671
672 i = pa_rtpoll_item_new(p, prio, 1);
673
674 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
675
676 pollfd->fd = pa_fdsem_get(f);
677 pollfd->events = POLLIN;
678
679 i->before_cb = fdsem_before;
680 i->after_cb = fdsem_after;
681 i->userdata = f;
682
683 return i;
684 }
685
686 static int asyncmsgq_before(pa_rtpoll_item *i) {
687 pa_assert(i);
688
689 if (pa_asyncmsgq_before_poll(i->userdata) < 0)
690 return 1; /* 1 means immediate restart of the loop */
691
692 return 0;
693 }
694
695 static void asyncmsgq_after(pa_rtpoll_item *i) {
696 pa_assert(i);
697
698 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
699 pa_asyncmsgq_after_poll(i->userdata);
700 }
701
702 static int asyncmsgq_work(pa_rtpoll_item *i) {
703 pa_msgobject *object;
704 int code;
705 void *data;
706 pa_memchunk chunk;
707 int64_t offset;
708
709 pa_assert(i);
710
711 if (pa_asyncmsgq_get(i->userdata, &object, &code, &data, &offset, &chunk, 0) == 0) {
712 int ret;
713
714 if (!object && code == PA_MESSAGE_SHUTDOWN) {
715 pa_asyncmsgq_done(i->userdata, 0);
716 pa_rtpoll_quit(i->rtpoll);
717 return 1;
718 }
719
720 ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
721 pa_asyncmsgq_done(i->userdata, ret);
722 return 1;
723 }
724
725 return 0;
726 }
727
728 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
729 pa_rtpoll_item *i;
730 struct pollfd *pollfd;
731
732 pa_assert(p);
733 pa_assert(q);
734
735 i = pa_rtpoll_item_new(p, prio, 1);
736
737 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
738 pollfd->fd = pa_asyncmsgq_get_fd(q);
739 pollfd->events = POLLIN;
740
741 i->before_cb = asyncmsgq_before;
742 i->after_cb = asyncmsgq_after;
743 i->work_cb = asyncmsgq_work;
744 i->userdata = q;
745
746 return i;
747 }
748
749 void pa_rtpoll_quit(pa_rtpoll *p) {
750 pa_assert(p);
751
752 p->quit = TRUE;
753 }