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/types.h>
36 #include <sys/utsname.h>
42 #include <pulsecore/poll.h>
45 #include <pulse/xmalloc.h>
46 #include <pulse/timeval.h>
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>
56 #include <pulsecore/winsock.h>
61 struct pollfd
*pollfd
, *pollfd2
;
62 unsigned n_pollfd_alloc
, n_pollfd_used
;
64 pa_bool_t timer_enabled
;
65 struct timeval next_elapse
;
68 pa_bool_t scan_for_dead
;
69 pa_bool_t running
, installed
, rebuild_needed
, quit
;
73 sigset_t sigset_unblocked
;
76 pa_bool_t dont_use_ppoll
;
80 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
83 struct pa_rtpoll_item
{
87 pa_rtpoll_priority_t priority
;
89 struct pollfd
*pollfd
;
92 int (*work_cb
)(pa_rtpoll_item
*i
);
93 int (*before_cb
)(pa_rtpoll_item
*i
);
94 void (*after_cb
)(pa_rtpoll_item
*i
);
97 PA_LLIST_FIELDS(pa_rtpoll_item
);
100 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
102 static void signal_handler_noop(int s
) { write(2, "signal\n", 7); }
104 pa_rtpoll
*pa_rtpoll_new(void) {
107 p
= pa_xnew(pa_rtpoll
, 1);
112 /* ppoll is broken on Linux < 2.6.16 */
113 p
->dont_use_ppoll
= FALSE
;
117 unsigned major
, minor
, micro
;
119 pa_assert_se(uname(&u
) == 0);
121 if (sscanf(u
.release
, "%u.%u.%u", &major
, &minor
, µ
) != 3 ||
123 (major
== 2 && minor
< 6) ||
124 (major
== 2 && minor
== 6 && micro
< 16))
126 p
->dont_use_ppoll
= TRUE
;
132 sigemptyset(&p
->sigset_unblocked
);
133 p
->timer
= (timer_t
) -1;
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;
143 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
144 p
->timer_enabled
= FALSE
;
147 p
->installed
= FALSE
;
148 p
->scan_for_dead
= FALSE
;
149 p
->rebuild_needed
= FALSE
;
152 PA_LLIST_HEAD_INIT(pa_rtpoll_item
, p
->items
);
157 void pa_rtpoll_install(pa_rtpoll
*p
) {
159 pa_assert(!p
->installed
);
165 if (p
->dont_use_ppoll
)
169 if ((p
->rtsig
= pa_rtsig_get_for_thread()) < 0) {
170 pa_log_warn("Failed to reserve POSIX realtime signal.");
174 pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p
->rtsig
));
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);
185 memset(&sa
, 0, sizeof(sa
));
186 sa
.sa_handler
= signal_handler_noop
;
187 pa_assert_se(sigemptyset(&sa
.sa_mask
) == 0);
189 pa_assert_se(sigaction(p
->rtsig
, &sa
, NULL
) == 0);
191 /* We never reset the signal handler. Why should we? */
197 static void rtpoll_rebuild(pa_rtpoll
*p
) {
199 struct pollfd
*e
, *t
;
205 p
->rebuild_needed
= FALSE
;
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
));
216 for (i
= p
->items
; i
; i
= i
->next
) {
218 if (i
->n_pollfd
> 0) {
219 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
222 memcpy(e
, i
->pollfd
, l
);
233 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
235 p
->pollfd
= p
->pollfd2
;
239 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
243 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
250 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
252 p
->n_pollfd_used
-= i
->n_pollfd
;
254 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
257 p
->rebuild_needed
= TRUE
;
260 void pa_rtpoll_free(pa_rtpoll
*p
) {
264 rtpoll_item_destroy(p
->items
);
267 pa_xfree(p
->pollfd2
);
270 if (p
->timer
!= (timer_t
) -1)
271 timer_delete(p
->timer
);
277 static void reset_revents(pa_rtpoll_item
*i
) {
283 if (!(f
= pa_rtpoll_item_get_pollfd(i
, &n
)))
290 static void reset_all_revents(pa_rtpoll
*p
) {
295 for (i
= p
->items
; i
; i
= i
->next
) {
304 int pa_rtpoll_run(pa_rtpoll
*p
, pa_bool_t wait
) {
307 struct timeval timeout
;
310 pa_assert(!p
->running
);
311 pa_assert(p
->installed
);
315 /* First, let's do some work */
316 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
328 if ((k
= i
->work_cb(i
)) != 0) {
336 /* Now let's prepare for entering the sleep */
337 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
346 if (p
->quit
|| (k
= i
->before_cb(i
)) != 0) {
348 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
350 for (i
= i
->prev
; i
; i
= i
->prev
) {
368 if (p
->rebuild_needed
)
371 /* Calculate timeout */
372 if (!wait
|| p
->quit
) {
375 } else if (p
->timer_enabled
) {
377 pa_rtclock_get(&now
);
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
));
384 /* OK, now let's sleep */
388 if (!p
->dont_use_ppoll
)
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
);
401 r
= poll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
? (timeout
.tv_sec
*1000) + (timeout
.tv_usec
/ 1000) : -1);
404 if (errno
== EAGAIN
|| errno
== EINTR
)
407 pa_log_error("poll(): %s", pa_cstrerror(errno
));
409 reset_all_revents(p
);
412 if (p
->timer_enabled
) {
415 pa_rtclock_get(&now
);
417 pa_timeval_add(&p
->next_elapse
, p
->period
);
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
);
424 p
->timer_enabled
= FALSE
;
427 /* Let's tell everyone that we left the sleep */
428 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
443 if (p
->scan_for_dead
) {
446 p
->scan_for_dead
= FALSE
;
448 for (i
= p
->items
; i
; i
= n
) {
452 rtpoll_item_destroy(i
);
456 return r
< 0 ? r
: !p
->quit
;
459 static void update_timer(pa_rtpoll
*p
) {
465 if (!p
->dont_use_ppoll
) {
468 if (p
->timer
== (timer_t
) -1) {
471 memset(&se
, 0, sizeof(se
));
472 se
.sigev_notify
= SIGEV_SIGNAL
;
473 se
.sigev_signo
= p
->rtsig
;
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;
482 if (p
->timer
!= (timer_t
) -1) {
483 struct itimerspec its
;
484 memset(&its
, 0, sizeof(its
));
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;
490 /* Make sure that 0,0 is not understood as
492 if (its
.it_value
.tv_sec
== 0)
493 its
.it_value
.tv_nsec
= 1;
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;
503 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
513 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timeval
*ts
) {
517 p
->next_elapse
= *ts
;
519 p
->timer_enabled
= TRUE
;
524 void pa_rtpoll_set_timer_periodic(pa_rtpoll
*p
, pa_usec_t usec
) {
528 pa_rtclock_get(&p
->next_elapse
);
529 pa_timeval_add(&p
->next_elapse
, usec
);
530 p
->timer_enabled
= TRUE
;
535 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
539 pa_rtclock_get(&p
->next_elapse
);
540 pa_timeval_add(&p
->next_elapse
, usec
);
541 p
->timer_enabled
= TRUE
;
546 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
550 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
551 p
->timer_enabled
= FALSE
;
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
;
561 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
562 i
= pa_xnew(pa_rtpoll_item
, 1);
575 for (j
= p
->items
; j
; j
= j
->next
) {
576 if (prio
<= j
->priority
)
582 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
585 p
->rebuild_needed
= 1;
586 p
->n_pollfd_used
+= n_fds
;
592 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
595 if (i
->rtpoll
->running
) {
597 i
->rtpoll
->scan_for_dead
= TRUE
;
601 rtpoll_item_destroy(i
);
604 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
608 if (i
->rtpoll
->rebuild_needed
)
609 rtpoll_rebuild(i
->rtpoll
);
612 *n_fds
= i
->n_pollfd
;
617 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
619 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
621 i
->before_cb
= before_cb
;
624 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
626 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
628 i
->after_cb
= after_cb
;
631 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
633 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
635 i
->work_cb
= work_cb
;
638 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
641 i
->userdata
= userdata
;
644 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
650 static int fdsem_before(pa_rtpoll_item
*i
) {
652 if (pa_fdsem_before_poll(i
->userdata
) < 0)
653 return 1; /* 1 means immediate restart of the loop */
658 static void fdsem_after(pa_rtpoll_item
*i
) {
661 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
662 pa_fdsem_after_poll(i
->userdata
);
665 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
667 struct pollfd
*pollfd
;
672 i
= pa_rtpoll_item_new(p
, prio
, 1);
674 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
676 pollfd
->fd
= pa_fdsem_get(f
);
677 pollfd
->events
= POLLIN
;
679 i
->before_cb
= fdsem_before
;
680 i
->after_cb
= fdsem_after
;
686 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
689 if (pa_asyncmsgq_before_poll(i
->userdata
) < 0)
690 return 1; /* 1 means immediate restart of the loop */
695 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
698 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
699 pa_asyncmsgq_after_poll(i
->userdata
);
702 static int asyncmsgq_work(pa_rtpoll_item
*i
) {
703 pa_msgobject
*object
;
711 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
714 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
715 pa_asyncmsgq_done(i
->userdata
, 0);
716 pa_rtpoll_quit(i
->rtpoll
);
720 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
721 pa_asyncmsgq_done(i
->userdata
, ret
);
728 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
730 struct pollfd
*pollfd
;
735 i
= pa_rtpoll_item_new(p
, prio
, 1);
737 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
738 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
739 pollfd
->events
= POLLIN
;
741 i
->before_cb
= asyncmsgq_before
;
742 i
->after_cb
= asyncmsgq_after
;
743 i
->work_cb
= asyncmsgq_work
;
749 void pa_rtpoll_quit(pa_rtpoll
*p
) {