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
;
67 pa_bool_t scan_for_dead
;
68 pa_bool_t running
, installed
, rebuild_needed
, quit
;
72 sigset_t sigset_unblocked
;
74 pa_bool_t timer_armed
;
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;
134 p
->timer_armed
= FALSE
;
138 p
->n_pollfd_alloc
= 32;
139 p
->pollfd
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
140 p
->pollfd2
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
141 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 memset(&timeout
, 0, sizeof(timeout
));
373 /* Calculate timeout */
374 if (wait
&& !p
->quit
&& p
->timer_enabled
) {
376 pa_rtclock_get(&now
);
378 if (pa_timeval_cmp(&p
->next_elapse
, &now
) > 0)
379 pa_timeval_add(&timeout
, pa_timeval_diff(&p
->next_elapse
, &now
));
382 /* OK, now let's sleep */
386 if (!p
->dont_use_ppoll
)
390 ts
.tv_sec
= timeout
.tv_sec
;
391 ts
.tv_nsec
= timeout
.tv_usec
* 1000;
392 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, (!wait
|| p
->quit
|| p
->timer_enabled
) ? &ts
: NULL
, p
->rtsig
< 0 ? NULL
: &p
->sigset_unblocked
);
399 r
= poll(p
->pollfd
, p
->n_pollfd_used
, (!wait
|| p
->quit
|| p
->timer_enabled
) ? (timeout
.tv_sec
*1000) + (timeout
.tv_usec
/ 1000) : -1);
402 if (errno
== EAGAIN
|| errno
== EINTR
)
405 pa_log_error("poll(): %s", pa_cstrerror(errno
));
407 reset_all_revents(p
);
410 /* Let's tell everyone that we left the sleep */
411 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
426 if (p
->scan_for_dead
) {
429 p
->scan_for_dead
= FALSE
;
431 for (i
= p
->items
; i
; i
= n
) {
435 rtpoll_item_destroy(i
);
439 return r
< 0 ? r
: !p
->quit
;
442 static void update_timer(pa_rtpoll
*p
) {
448 if (!p
->dont_use_ppoll
) {
451 if (p
->timer
== (timer_t
) -1) {
454 memset(&se
, 0, sizeof(se
));
455 se
.sigev_notify
= SIGEV_SIGNAL
;
456 se
.sigev_signo
= p
->rtsig
;
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;
465 if (p
->timer
!= (timer_t
) -1) {
466 struct itimerspec its
;
467 struct timespec ts
= { .tv_sec
= 0, .tv_nsec
= 0 };
470 if (p
->timer_armed
) {
471 /* First disarm timer */
472 memset(&its
, 0, sizeof(its
));
473 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
475 /* Remove a signal that might be waiting in the signal q */
476 pa_assert_se(sigemptyset(&ss
) == 0);
477 pa_assert_se(sigaddset(&ss
, p
->rtsig
) == 0);
478 sigtimedwait(&ss
, NULL
, &ts
);
481 /* And install the new timer */
482 if (p
->timer_enabled
) {
483 memset(&its
, 0, sizeof(its
));
485 its
.it_value
.tv_sec
= p
->next_elapse
.tv_sec
;
486 its
.it_value
.tv_nsec
= p
->next_elapse
.tv_usec
*1000;
488 /* Make sure that 0,0 is not understood as
490 if (its
.it_value
.tv_sec
== 0 && its
.it_value
.tv_nsec
== 0)
491 its
.it_value
.tv_nsec
= 1;
492 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
495 p
->timer_armed
= p
->timer_enabled
;
505 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, pa_usec_t usec
) {
508 pa_timeval_store(&p
->next_elapse
, usec
);
509 p
->timer_enabled
= TRUE
;
514 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
517 pa_rtclock_get(&p
->next_elapse
);
518 pa_timeval_add(&p
->next_elapse
, usec
);
519 p
->timer_enabled
= TRUE
;
524 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_read_before(pa_rtpoll_item
*i
) {
666 if (pa_asyncmsgq_read_before_poll(i
->userdata
) < 0)
667 return 1; /* 1 means immediate restart of the loop */
672 static void asyncmsgq_read_after(pa_rtpoll_item
*i
) {
675 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
676 pa_asyncmsgq_read_after_poll(i
->userdata
);
679 static int asyncmsgq_read_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_read(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_read_fd(q
);
716 pollfd
->events
= POLLIN
;
718 i
->before_cb
= asyncmsgq_read_before
;
719 i
->after_cb
= asyncmsgq_read_after
;
720 i
->work_cb
= asyncmsgq_read_work
;
726 static int asyncmsgq_write_before(pa_rtpoll_item
*i
) {
729 pa_asyncmsgq_write_before_poll(i
->userdata
);
733 static void asyncmsgq_write_after(pa_rtpoll_item
*i
) {
736 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
737 pa_asyncmsgq_write_after_poll(i
->userdata
);
740 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
742 struct pollfd
*pollfd
;
747 i
= pa_rtpoll_item_new(p
, prio
, 1);
749 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
750 pollfd
->fd
= pa_asyncmsgq_write_fd(q
);
751 pollfd
->events
= POLLIN
;
753 i
->before_cb
= asyncmsgq_write_before
;
754 i
->after_cb
= asyncmsgq_write_after
;
761 void pa_rtpoll_quit(pa_rtpoll
*p
) {