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
, const struct timeval
*ts
) {
509 p
->next_elapse
= *ts
;
510 p
->timer_enabled
= TRUE
;
515 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
518 pa_rtclock_get(&p
->next_elapse
);
519 pa_timeval_add(&p
->next_elapse
, usec
);
520 p
->timer_enabled
= TRUE
;
525 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
528 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
529 p
->timer_enabled
= FALSE
;
534 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
535 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
539 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
540 i
= pa_xnew(pa_rtpoll_item
, 1);
553 for (j
= p
->items
; j
; j
= j
->next
) {
554 if (prio
<= j
->priority
)
560 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
563 p
->rebuild_needed
= 1;
564 p
->n_pollfd_used
+= n_fds
;
570 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
573 if (i
->rtpoll
->running
) {
575 i
->rtpoll
->scan_for_dead
= TRUE
;
579 rtpoll_item_destroy(i
);
582 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
586 if (i
->rtpoll
->rebuild_needed
)
587 rtpoll_rebuild(i
->rtpoll
);
590 *n_fds
= i
->n_pollfd
;
595 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
597 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
599 i
->before_cb
= before_cb
;
602 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
604 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
606 i
->after_cb
= after_cb
;
609 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
611 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
613 i
->work_cb
= work_cb
;
616 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
619 i
->userdata
= userdata
;
622 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
628 static int fdsem_before(pa_rtpoll_item
*i
) {
630 if (pa_fdsem_before_poll(i
->userdata
) < 0)
631 return 1; /* 1 means immediate restart of the loop */
636 static void fdsem_after(pa_rtpoll_item
*i
) {
639 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
640 pa_fdsem_after_poll(i
->userdata
);
643 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
645 struct pollfd
*pollfd
;
650 i
= pa_rtpoll_item_new(p
, prio
, 1);
652 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
654 pollfd
->fd
= pa_fdsem_get(f
);
655 pollfd
->events
= POLLIN
;
657 i
->before_cb
= fdsem_before
;
658 i
->after_cb
= fdsem_after
;
664 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
667 if (pa_asyncmsgq_before_poll(i
->userdata
) < 0)
668 return 1; /* 1 means immediate restart of the loop */
673 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
676 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
677 pa_asyncmsgq_after_poll(i
->userdata
);
680 static int asyncmsgq_work(pa_rtpoll_item
*i
) {
681 pa_msgobject
*object
;
689 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
692 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
693 pa_asyncmsgq_done(i
->userdata
, 0);
694 pa_rtpoll_quit(i
->rtpoll
);
698 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
699 pa_asyncmsgq_done(i
->userdata
, ret
);
706 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
708 struct pollfd
*pollfd
;
713 i
= pa_rtpoll_item_new(p
, prio
, 1);
715 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
716 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
717 pollfd
->events
= POLLIN
;
719 i
->before_cb
= asyncmsgq_before
;
720 i
->after_cb
= asyncmsgq_after
;
721 i
->work_cb
= asyncmsgq_work
;
727 void pa_rtpoll_quit(pa_rtpoll
*p
) {