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
) { }
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
);
164 if (p
->dont_use_ppoll
)
167 if ((p
->rtsig
= pa_rtsig_get_for_thread()) < 0) {
168 pa_log_warn("Failed to reserve POSIX realtime signal.");
172 pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p
->rtsig
));
178 pa_assert_se(sigemptyset(&ss
) == 0);
179 pa_assert_se(sigaddset(&ss
, p
->rtsig
) == 0);
180 pa_assert_se(pthread_sigmask(SIG_BLOCK
, &ss
, &p
->sigset_unblocked
) == 0);
181 pa_assert_se(sigdelset(&p
->sigset_unblocked
, p
->rtsig
) == 0);
183 memset(&sa
, 0, sizeof(sa
));
184 sa
.sa_handler
= signal_handler_noop
;
185 pa_assert_se(sigemptyset(&sa
.sa_mask
) == 0);
187 pa_assert_se(sigaction(p
->rtsig
, &sa
, NULL
) == 0);
189 /* We never reset the signal handler. Why should we? */
195 static void rtpoll_rebuild(pa_rtpoll
*p
) {
197 struct pollfd
*e
, *t
;
203 p
->rebuild_needed
= FALSE
;
205 if (p
->n_pollfd_used
> p
->n_pollfd_alloc
) {
206 /* Hmm, we have to allocate some more space */
207 p
->n_pollfd_alloc
= p
->n_pollfd_used
* 2;
208 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
214 for (i
= p
->items
; i
; i
= i
->next
) {
216 if (i
->n_pollfd
> 0) {
217 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
220 memcpy(e
, i
->pollfd
, l
);
231 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
233 p
->pollfd
= p
->pollfd2
;
237 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
241 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
248 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
250 p
->n_pollfd_used
-= i
->n_pollfd
;
252 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
255 p
->rebuild_needed
= TRUE
;
258 void pa_rtpoll_free(pa_rtpoll
*p
) {
262 rtpoll_item_destroy(p
->items
);
265 pa_xfree(p
->pollfd2
);
268 if (p
->timer
!= (timer_t
) -1)
269 timer_delete(p
->timer
);
275 static void reset_revents(pa_rtpoll_item
*i
) {
281 if (!(f
= pa_rtpoll_item_get_pollfd(i
, &n
)))
288 static void reset_all_revents(pa_rtpoll
*p
) {
293 for (i
= p
->items
; i
; i
= i
->next
) {
302 int pa_rtpoll_run(pa_rtpoll
*p
, pa_bool_t wait
) {
305 struct timeval timeout
;
308 pa_assert(!p
->running
);
309 pa_assert(p
->installed
);
313 /* First, let's do some work */
314 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
326 if ((k
= i
->work_cb(i
)) != 0) {
334 /* Now let's prepare for entering the sleep */
335 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
344 if (p
->quit
|| (k
= i
->before_cb(i
)) != 0) {
346 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
348 for (i
= i
->prev
; i
; i
= i
->prev
) {
366 if (p
->rebuild_needed
)
369 /* Calculate timeout */
370 if (!wait
|| p
->quit
) {
373 } else if (p
->timer_enabled
) {
375 pa_rtclock_get(&now
);
377 memset(&timeout
, 0, sizeof(timeout
));
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
, p
->timer_enabled
? &ts
: NULL
, p
->rtsig
< 0 ? NULL
: &p
->sigset_unblocked
);
399 r
= poll(p
->pollfd
, p
->n_pollfd_used
, 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 if (p
->timer_enabled
) {
413 pa_rtclock_get(&now
);
415 pa_timeval_add(&p
->next_elapse
, p
->period
);
417 /* Guarantee that the next timeout will happen in the future */
418 if (pa_timeval_cmp(&p
->next_elapse
, &now
) < 0)
419 pa_timeval_add(&p
->next_elapse
, (pa_timeval_diff(&now
, &p
->next_elapse
) / p
->period
+ 1) * p
->period
);
422 p
->timer_enabled
= FALSE
;
425 /* Let's tell everyone that we left the sleep */
426 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
441 if (p
->scan_for_dead
) {
444 p
->scan_for_dead
= FALSE
;
446 for (i
= p
->items
; i
; i
= n
) {
450 rtpoll_item_destroy(i
);
454 return r
< 0 ? r
: !p
->quit
;
457 static void update_timer(pa_rtpoll
*p
) {
463 if (!p
->dont_use_ppoll
) {
466 if (p
->timer
== (timer_t
) -1) {
469 memset(&se
, 0, sizeof(se
));
470 se
.sigev_notify
= SIGEV_SIGNAL
;
471 se
.sigev_signo
= p
->rtsig
;
473 if (timer_create(CLOCK_MONOTONIC
, &se
, &p
->timer
) < 0)
474 if (timer_create(CLOCK_REALTIME
, &se
, &p
->timer
) < 0) {
475 pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno
));
476 p
->timer
= (timer_t
) -1;
480 if (p
->timer
!= (timer_t
) -1) {
481 struct itimerspec its
;
482 memset(&its
, 0, sizeof(its
));
484 if (p
->timer_enabled
) {
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)
491 its
.it_value
.tv_nsec
= 1;
495 pa_timeval_store(&tv
, p
->period
);
496 its
.it_interval
.tv_sec
= tv
.tv_sec
;
497 its
.it_interval
.tv_nsec
= tv
.tv_usec
*1000;
501 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
511 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timeval
*ts
) {
515 p
->next_elapse
= *ts
;
517 p
->timer_enabled
= TRUE
;
522 void pa_rtpoll_set_timer_periodic(pa_rtpoll
*p
, pa_usec_t usec
) {
526 pa_rtclock_get(&p
->next_elapse
);
527 pa_timeval_add(&p
->next_elapse
, usec
);
528 p
->timer_enabled
= TRUE
;
533 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
537 pa_rtclock_get(&p
->next_elapse
);
538 pa_timeval_add(&p
->next_elapse
, usec
);
539 p
->timer_enabled
= TRUE
;
544 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
548 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
549 p
->timer_enabled
= FALSE
;
554 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
555 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
559 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
560 i
= pa_xnew(pa_rtpoll_item
, 1);
573 for (j
= p
->items
; j
; j
= j
->next
) {
574 if (prio
<= j
->priority
)
580 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
583 p
->rebuild_needed
= 1;
584 p
->n_pollfd_used
+= n_fds
;
590 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
593 if (i
->rtpoll
->running
) {
595 i
->rtpoll
->scan_for_dead
= TRUE
;
599 rtpoll_item_destroy(i
);
602 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
606 if (i
->rtpoll
->rebuild_needed
)
607 rtpoll_rebuild(i
->rtpoll
);
610 *n_fds
= i
->n_pollfd
;
615 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
617 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
619 i
->before_cb
= before_cb
;
622 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
624 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
626 i
->after_cb
= after_cb
;
629 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
631 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
633 i
->work_cb
= work_cb
;
636 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
639 i
->userdata
= userdata
;
642 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
648 static int fdsem_before(pa_rtpoll_item
*i
) {
650 if (pa_fdsem_before_poll(i
->userdata
) < 0)
651 return 1; /* 1 means immediate restart of the loop */
656 static void fdsem_after(pa_rtpoll_item
*i
) {
659 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
660 pa_fdsem_after_poll(i
->userdata
);
663 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
665 struct pollfd
*pollfd
;
670 i
= pa_rtpoll_item_new(p
, prio
, 1);
672 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
674 pollfd
->fd
= pa_fdsem_get(f
);
675 pollfd
->events
= POLLIN
;
677 i
->before_cb
= fdsem_before
;
678 i
->after_cb
= fdsem_after
;
684 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
687 if (pa_asyncmsgq_before_poll(i
->userdata
) < 0)
688 return 1; /* 1 means immediate restart of the loop */
693 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
696 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
697 pa_asyncmsgq_after_poll(i
->userdata
);
700 static int asyncmsgq_work(pa_rtpoll_item
*i
) {
701 pa_msgobject
*object
;
709 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
712 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
713 pa_asyncmsgq_done(i
->userdata
, 0);
714 pa_rtpoll_quit(i
->rtpoll
);
718 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
719 pa_asyncmsgq_done(i
->userdata
, ret
);
726 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
728 struct pollfd
*pollfd
;
733 i
= pa_rtpoll_item_new(p
, prio
, 1);
735 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
736 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
737 pollfd
->events
= POLLIN
;
739 i
->before_cb
= asyncmsgq_before
;
740 i
->after_cb
= asyncmsgq_after
;
741 i
->work_cb
= asyncmsgq_work
;
747 void pa_rtpoll_quit(pa_rtpoll
*p
) {