4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
29 #include <sys/utsname.h>
30 #include <sys/types.h>
36 #include <pulse/xmalloc.h>
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>
48 struct pollfd
*pollfd
, *pollfd2
;
49 unsigned n_pollfd_alloc
, n_pollfd_used
;
52 struct timespec next_elapse
;
56 int running
, installed
, rebuild_needed
;
60 sigset_t sigset_unblocked
;
67 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
70 struct pa_rtpoll_item
{
74 pa_rtpoll_priority_t priority
;
76 struct pollfd
*pollfd
;
79 int (*before_cb
)(pa_rtpoll_item
*i
);
80 void (*after_cb
)(pa_rtpoll_item
*i
);
83 PA_LLIST_FIELDS(pa_rtpoll_item
);
86 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
88 static void signal_handler_noop(int s
) { }
90 pa_rtpoll
*pa_rtpoll_new(void) {
93 p
= pa_xnew(pa_rtpoll
, 1);
98 /* ppoll is broken on Linux < 2.6.16 */
100 p
->dont_use_ppoll
= 0;
104 unsigned major
, minor
, micro
;
106 pa_assert_se(uname(&u
) == 0);
108 if (sscanf(u
.release
, "%u.%u.%u", &major
, &minor
, µ
) != 3 ||
110 (major
== 2 && minor
< 6) ||
111 (major
== 2 && minor
== 6 && micro
< 16))
113 p
->dont_use_ppoll
= 1;
119 sigemptyset(&p
->sigset_unblocked
);
120 p
->timer
= (timer_t
) -1;
124 p
->n_pollfd_alloc
= 32;
125 p
->pollfd
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
126 p
->pollfd2
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
127 p
->n_pollfd_used
= 0;
130 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
131 p
->timer_enabled
= 0;
135 p
->scan_for_dead
= 0;
136 p
->rebuild_needed
= 0;
138 PA_LLIST_HEAD_INIT(pa_rtpoll_item
, p
->items
);
143 void pa_rtpoll_install(pa_rtpoll
*p
) {
145 pa_assert(!p
->installed
);
150 if (p
->dont_use_ppoll
)
153 if ((p
->rtsig
= pa_rtsig_get_for_thread()) < 0) {
154 pa_log_warn("Failed to reserve POSIX realtime signal.");
158 pa_log_debug("Acquired POSIX realtime signal SIGRTMIN+%i", p
->rtsig
- SIGRTMIN
);
164 pa_assert_se(sigemptyset(&ss
) == 0);
165 pa_assert_se(sigaddset(&ss
, p
->rtsig
) == 0);
166 pa_assert_se(pthread_sigmask(SIG_BLOCK
, &ss
, &p
->sigset_unblocked
) == 0);
167 pa_assert_se(sigdelset(&p
->sigset_unblocked
, p
->rtsig
) == 0);
169 memset(&sa
, 0, sizeof(sa
));
170 sa
.sa_handler
= signal_handler_noop
;
171 pa_assert_se(sigemptyset(&sa
.sa_mask
) == 0);
173 pa_assert_se(sigaction(p
->rtsig
, &sa
, NULL
) == 0);
175 /* We never reset the signal handler. Why should we? */
181 static void rtpoll_rebuild(pa_rtpoll
*p
) {
183 struct pollfd
*e
, *t
;
189 p
->rebuild_needed
= 0;
191 if (p
->n_pollfd_used
> p
->n_pollfd_alloc
) {
192 /* Hmm, we have to allocate some more space */
193 p
->n_pollfd_alloc
= p
->n_pollfd_used
* 2;
194 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
200 for (i
= p
->items
; i
; i
= i
->next
) {
202 if (i
->n_pollfd
> 0) {
203 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
206 memcpy(e
, i
->pollfd
, l
);
217 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
219 p
->pollfd
= p
->pollfd2
;
223 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
227 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
234 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
236 p
->n_pollfd_used
-= i
->n_pollfd
;
238 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
241 p
->rebuild_needed
= 1;
244 void pa_rtpoll_free(pa_rtpoll
*p
) {
248 rtpoll_item_destroy(p
->items
);
251 pa_xfree(p
->pollfd2
);
254 if (p
->timer
!= (timer_t
) -1)
255 timer_delete(p
->timer
);
261 static void reset_revents(pa_rtpoll_item
*i
) {
267 if (!(f
= pa_rtpoll_item_get_pollfd(i
, &n
)))
274 static void reset_all_revents(pa_rtpoll
*p
) {
279 for (i
= p
->items
; i
; i
= i
->next
) {
288 int pa_rtpoll_run(pa_rtpoll
*p
, int wait
) {
292 struct timespec timeout
;
295 pa_assert(!p
->running
);
296 pa_assert(p
->installed
);
300 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
309 if ((k
= i
->before_cb(i
)) != 0) {
311 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
313 reset_all_revents(p
);
315 for (i
= i
->prev
; i
; i
= i
->prev
) {
333 if (p
->rebuild_needed
)
336 /* Calculate timeout */
340 } else if (p
->timer_enabled
) {
342 pa_rtclock_get(&now
);
344 if (pa_timespec_cmp(&p
->next_elapse
, &now
) <= 0)
345 memset(&timeout
, 0, sizeof(timeout
));
347 pa_timespec_store(&timeout
, pa_timespec_diff(&p
->next_elapse
, &now
));
350 /* OK, now let's sleep */
354 if (!p
->dont_use_ppoll
)
356 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
> 0 ? &timeout
: NULL
, p
->rtsig
< 0 ? NULL
: &p
->sigset_unblocked
);
362 r
= poll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
> 0 ? (timeout
.tv_sec
*1000) + (timeout
.tv_nsec
/ 1000000) : -1);
366 reset_all_revents(p
);
368 if (r
< 0 && (errno
== EAGAIN
|| errno
== EINTR
))
371 saved_errno
= r
< 0 ? errno
: 0;
373 if (p
->timer_enabled
) {
376 pa_rtclock_get(&now
);
378 pa_timespec_add(&p
->next_elapse
, p
->period
);
380 /* Guarantee that the next timeout will happen in the future */
381 if (pa_timespec_cmp(&p
->next_elapse
, &now
) < 0)
382 pa_timespec_add(&p
->next_elapse
, (pa_timespec_diff(&now
, &p
->next_elapse
) / p
->period
+ 1) * p
->period
);
385 p
->timer_enabled
= 0;
388 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
403 if (p
->scan_for_dead
) {
406 p
->scan_for_dead
= 0;
408 for (i
= p
->items
; i
; i
= n
) {
412 rtpoll_item_destroy(i
);
416 if (saved_errno
!= 0)
422 static void update_timer(pa_rtpoll
*p
) {
428 if (!p
->dont_use_ppoll
) {
431 if (p
->timer
== (timer_t
) -1) {
434 memset(&se
, 0, sizeof(se
));
435 se
.sigev_notify
= SIGEV_SIGNAL
;
436 se
.sigev_signo
= p
->rtsig
;
438 if (timer_create(CLOCK_MONOTONIC
, &se
, &p
->timer
) < 0)
439 if (timer_create(CLOCK_REALTIME
, &se
, &p
->timer
) < 0) {
440 pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno
));
441 p
->timer
= (timer_t
) -1;
445 if (p
->timer
!= (timer_t
) -1) {
446 struct itimerspec its
;
447 memset(&its
, 0, sizeof(its
));
449 if (p
->timer_enabled
) {
450 its
.it_value
= p
->next_elapse
;
452 /* Make sure that 0,0 is not understood as
454 if (its
.it_value
.tv_sec
== 0)
455 its
.it_value
.tv_nsec
= 1;
458 pa_timespec_store(&its
.it_interval
, p
->period
);
461 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
471 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timespec
*ts
) {
475 p
->next_elapse
= *ts
;
477 p
->timer_enabled
= 1;
482 void pa_rtpoll_set_timer_periodic(pa_rtpoll
*p
, pa_usec_t usec
) {
486 pa_rtclock_get(&p
->next_elapse
);
487 pa_timespec_add(&p
->next_elapse
, usec
);
488 p
->timer_enabled
= 1;
493 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
497 pa_rtclock_get(&p
->next_elapse
);
498 pa_timespec_add(&p
->next_elapse
, usec
);
499 p
->timer_enabled
= 1;
504 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
508 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
509 p
->timer_enabled
= 0;
514 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
515 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
519 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
520 i
= pa_xnew(pa_rtpoll_item
, 1);
532 for (j
= p
->items
; j
; j
= j
->next
) {
533 if (prio
<= j
->priority
)
539 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
542 p
->rebuild_needed
= 1;
543 p
->n_pollfd_used
+= n_fds
;
549 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
552 if (i
->rtpoll
->running
) {
554 i
->rtpoll
->scan_for_dead
= 1;
558 rtpoll_item_destroy(i
);
561 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
565 if (i
->rtpoll
->rebuild_needed
)
566 rtpoll_rebuild(i
->rtpoll
);
569 *n_fds
= i
->n_pollfd
;
574 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
576 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
578 i
->before_cb
= before_cb
;
581 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
583 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
585 i
->after_cb
= after_cb
;
588 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
591 i
->userdata
= userdata
;
594 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
600 static int fdsem_before(pa_rtpoll_item
*i
) {
602 if (pa_fdsem_before_poll(i
->userdata
) < 0)
603 return 1; /* 1 means immediate restart of the loop */
608 static void fdsem_after(pa_rtpoll_item
*i
) {
611 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
612 pa_fdsem_after_poll(i
->userdata
);
615 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
617 struct pollfd
*pollfd
;
622 i
= pa_rtpoll_item_new(p
, prio
, 1);
624 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
626 pollfd
->fd
= pa_fdsem_get(f
);
627 pollfd
->events
= POLLIN
;
629 i
->before_cb
= fdsem_before
;
630 i
->after_cb
= fdsem_after
;
636 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
639 if (pa_asyncmsgq_before_poll(i
->userdata
) < 0)
640 return 1; /* 1 means immediate restart of the loop */
645 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
648 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
649 pa_asyncmsgq_after_poll(i
->userdata
);
652 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
654 struct pollfd
*pollfd
;
659 i
= pa_rtpoll_item_new(p
, prio
, 1);
661 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
662 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
663 pollfd
->events
= POLLIN
;
665 i
->before_cb
= asyncmsgq_before
;
666 i
->after_cb
= asyncmsgq_after
;