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>
44 #include <pulsecore/core-util.h>
49 struct pollfd
*pollfd
, *pollfd2
;
50 unsigned n_pollfd_alloc
, n_pollfd_used
;
52 pa_bool_t timer_enabled
;
53 struct timespec next_elapse
;
56 pa_bool_t scan_for_dead
;
57 pa_bool_t running
, installed
, rebuild_needed
, quit
;
61 sigset_t sigset_unblocked
;
64 pa_bool_t dont_use_ppoll
;
68 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
71 struct pa_rtpoll_item
{
75 pa_rtpoll_priority_t priority
;
77 struct pollfd
*pollfd
;
80 int (*work_cb
)(pa_rtpoll_item
*i
);
81 int (*before_cb
)(pa_rtpoll_item
*i
);
82 void (*after_cb
)(pa_rtpoll_item
*i
);
85 PA_LLIST_FIELDS(pa_rtpoll_item
);
88 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
90 static void signal_handler_noop(int s
) { }
92 pa_rtpoll
*pa_rtpoll_new(void) {
95 p
= pa_xnew(pa_rtpoll
, 1);
100 /* ppoll is broken on Linux < 2.6.16 */
101 p
->dont_use_ppoll
= FALSE
;
105 unsigned major
, minor
, micro
;
107 pa_assert_se(uname(&u
) == 0);
109 if (sscanf(u
.release
, "%u.%u.%u", &major
, &minor
, µ
) != 3 ||
111 (major
== 2 && minor
< 6) ||
112 (major
== 2 && minor
== 6 && micro
< 16))
114 p
->dont_use_ppoll
= TRUE
;
120 sigemptyset(&p
->sigset_unblocked
);
121 p
->timer
= (timer_t
) -1;
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;
131 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
132 p
->timer_enabled
= FALSE
;
135 p
->installed
= FALSE
;
136 p
->scan_for_dead
= FALSE
;
137 p
->rebuild_needed
= FALSE
;
140 PA_LLIST_HEAD_INIT(pa_rtpoll_item
, p
->items
);
145 void pa_rtpoll_install(pa_rtpoll
*p
) {
147 pa_assert(!p
->installed
);
152 if (p
->dont_use_ppoll
)
155 if ((p
->rtsig
= pa_rtsig_get_for_thread()) < 0) {
156 pa_log_warn("Failed to reserve POSIX realtime signal.");
160 pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p
->rtsig
));
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);
171 memset(&sa
, 0, sizeof(sa
));
172 sa
.sa_handler
= signal_handler_noop
;
173 pa_assert_se(sigemptyset(&sa
.sa_mask
) == 0);
175 pa_assert_se(sigaction(p
->rtsig
, &sa
, NULL
) == 0);
177 /* We never reset the signal handler. Why should we? */
183 static void rtpoll_rebuild(pa_rtpoll
*p
) {
185 struct pollfd
*e
, *t
;
191 p
->rebuild_needed
= FALSE
;
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
));
202 for (i
= p
->items
; i
; i
= i
->next
) {
204 if (i
->n_pollfd
> 0) {
205 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
208 memcpy(e
, i
->pollfd
, l
);
219 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
221 p
->pollfd
= p
->pollfd2
;
225 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
229 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
236 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
238 p
->n_pollfd_used
-= i
->n_pollfd
;
240 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
243 p
->rebuild_needed
= TRUE
;
246 void pa_rtpoll_free(pa_rtpoll
*p
) {
250 rtpoll_item_destroy(p
->items
);
253 pa_xfree(p
->pollfd2
);
256 if (p
->timer
!= (timer_t
) -1)
257 timer_delete(p
->timer
);
263 static void reset_revents(pa_rtpoll_item
*i
) {
269 if (!(f
= pa_rtpoll_item_get_pollfd(i
, &n
)))
276 static void reset_all_revents(pa_rtpoll
*p
) {
281 for (i
= p
->items
; i
; i
= i
->next
) {
290 int pa_rtpoll_run(pa_rtpoll
*p
, pa_bool_t wait
) {
293 struct timespec timeout
;
296 pa_assert(!p
->running
);
297 pa_assert(p
->installed
);
301 /* First, let's do some work */
302 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
314 if ((k
= i
->work_cb(i
)) != 0) {
322 /* Now let's prepare for entering the sleep */
323 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
332 if (p
->quit
|| (k
= i
->before_cb(i
)) != 0) {
334 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
336 for (i
= i
->prev
; i
; i
= i
->prev
) {
354 if (p
->rebuild_needed
)
357 /* Calculate timeout */
358 if (!wait
|| p
->quit
) {
361 } else if (p
->timer_enabled
) {
363 pa_rtclock_get(&now
);
365 if (pa_timespec_cmp(&p
->next_elapse
, &now
) <= 0)
366 memset(&timeout
, 0, sizeof(timeout
));
368 pa_timespec_store(&timeout
, pa_timespec_diff(&p
->next_elapse
, &now
));
371 /* OK, now let's sleep */
375 if (!p
->dont_use_ppoll
)
377 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
? &timeout
: NULL
, p
->rtsig
< 0 ? NULL
: &p
->sigset_unblocked
);
383 r
= poll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
? (timeout
.tv_sec
*1000) + (timeout
.tv_nsec
/ 1000000) : -1);
386 if (errno
== EAGAIN
|| errno
== EINTR
)
389 pa_log_error("poll(): %s", pa_cstrerror(errno
));
391 reset_all_revents(p
);
394 if (p
->timer_enabled
) {
397 pa_rtclock_get(&now
);
399 pa_timespec_add(&p
->next_elapse
, p
->period
);
401 /* Guarantee that the next timeout will happen in the future */
402 if (pa_timespec_cmp(&p
->next_elapse
, &now
) < 0)
403 pa_timespec_add(&p
->next_elapse
, (pa_timespec_diff(&now
, &p
->next_elapse
) / p
->period
+ 1) * p
->period
);
406 p
->timer_enabled
= FALSE
;
409 /* Let's tell everyone that we left the sleep */
410 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
425 if (p
->scan_for_dead
) {
428 p
->scan_for_dead
= FALSE
;
430 for (i
= p
->items
; i
; i
= n
) {
434 rtpoll_item_destroy(i
);
438 return r
< 0 ? r
: !p
->quit
;
441 static void update_timer(pa_rtpoll
*p
) {
447 if (!p
->dont_use_ppoll
) {
450 if (p
->timer
== (timer_t
) -1) {
453 memset(&se
, 0, sizeof(se
));
454 se
.sigev_notify
= SIGEV_SIGNAL
;
455 se
.sigev_signo
= p
->rtsig
;
457 if (timer_create(CLOCK_MONOTONIC
, &se
, &p
->timer
) < 0)
458 if (timer_create(CLOCK_REALTIME
, &se
, &p
->timer
) < 0) {
459 pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno
));
460 p
->timer
= (timer_t
) -1;
464 if (p
->timer
!= (timer_t
) -1) {
465 struct itimerspec its
;
466 memset(&its
, 0, sizeof(its
));
468 if (p
->timer_enabled
) {
469 its
.it_value
= p
->next_elapse
;
471 /* Make sure that 0,0 is not understood as
473 if (its
.it_value
.tv_sec
== 0)
474 its
.it_value
.tv_nsec
= 1;
477 pa_timespec_store(&its
.it_interval
, p
->period
);
480 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
490 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timespec
*ts
) {
494 p
->next_elapse
= *ts
;
496 p
->timer_enabled
= TRUE
;
501 void pa_rtpoll_set_timer_periodic(pa_rtpoll
*p
, pa_usec_t usec
) {
505 pa_rtclock_get(&p
->next_elapse
);
506 pa_timespec_add(&p
->next_elapse
, usec
);
507 p
->timer_enabled
= TRUE
;
512 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
516 pa_rtclock_get(&p
->next_elapse
);
517 pa_timespec_add(&p
->next_elapse
, usec
);
518 p
->timer_enabled
= TRUE
;
523 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
527 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
528 p
->timer_enabled
= FALSE
;
533 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
534 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
538 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
539 i
= pa_xnew(pa_rtpoll_item
, 1);
552 for (j
= p
->items
; j
; j
= j
->next
) {
553 if (prio
<= j
->priority
)
559 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
562 p
->rebuild_needed
= 1;
563 p
->n_pollfd_used
+= n_fds
;
569 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
572 if (i
->rtpoll
->running
) {
574 i
->rtpoll
->scan_for_dead
= TRUE
;
578 rtpoll_item_destroy(i
);
581 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
585 if (i
->rtpoll
->rebuild_needed
)
586 rtpoll_rebuild(i
->rtpoll
);
589 *n_fds
= i
->n_pollfd
;
594 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
596 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
598 i
->before_cb
= before_cb
;
601 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
603 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
605 i
->after_cb
= after_cb
;
608 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
610 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
612 i
->work_cb
= work_cb
;
615 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
618 i
->userdata
= userdata
;
621 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
627 static int fdsem_before(pa_rtpoll_item
*i
) {
629 if (pa_fdsem_before_poll(i
->userdata
) < 0)
630 return 1; /* 1 means immediate restart of the loop */
635 static void fdsem_after(pa_rtpoll_item
*i
) {
638 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
639 pa_fdsem_after_poll(i
->userdata
);
642 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
644 struct pollfd
*pollfd
;
649 i
= pa_rtpoll_item_new(p
, prio
, 1);
651 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
653 pollfd
->fd
= pa_fdsem_get(f
);
654 pollfd
->events
= POLLIN
;
656 i
->before_cb
= fdsem_before
;
657 i
->after_cb
= fdsem_after
;
663 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
666 if (pa_asyncmsgq_before_poll(i
->userdata
) < 0)
667 return 1; /* 1 means immediate restart of the loop */
672 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
675 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
676 pa_asyncmsgq_after_poll(i
->userdata
);
679 static int asyncmsgq_work(pa_rtpoll_item
*i
) {
680 pa_msgobject
*object
;
688 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
691 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
692 pa_asyncmsgq_done(i
->userdata
, 0);
693 pa_rtpoll_quit(i
->rtpoll
);
697 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
698 pa_asyncmsgq_done(i
->userdata
, ret
);
705 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
707 struct pollfd
*pollfd
;
712 i
= pa_rtpoll_item_new(p
, prio
, 1);
714 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
715 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
716 pollfd
->events
= POLLIN
;
718 i
->before_cb
= asyncmsgq_before
;
719 i
->after_cb
= asyncmsgq_after
;
720 i
->work_cb
= asyncmsgq_work
;
726 void pa_rtpoll_quit(pa_rtpoll
*p
) {