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