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