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
;
75 pa_bool_t dont_use_ppoll
;
79 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
82 struct pa_rtpoll_item
{
86 pa_rtpoll_priority_t priority
;
88 struct pollfd
*pollfd
;
91 int (*work_cb
)(pa_rtpoll_item
*i
);
92 int (*before_cb
)(pa_rtpoll_item
*i
);
93 void (*after_cb
)(pa_rtpoll_item
*i
);
96 PA_LLIST_FIELDS(pa_rtpoll_item
);
99 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
101 static void signal_handler_noop(int s
) { /* write(2, "signal\n", 7); */ }
103 pa_rtpoll
*pa_rtpoll_new(void) {
106 p
= pa_xnew(pa_rtpoll
, 1);
111 /* ppoll is broken on Linux < 2.6.16 */
112 p
->dont_use_ppoll
= FALSE
;
116 unsigned major
, minor
, micro
;
118 pa_assert_se(uname(&u
) == 0);
120 if (sscanf(u
.release
, "%u.%u.%u", &major
, &minor
, µ
) != 3 ||
122 (major
== 2 && minor
< 6) ||
123 (major
== 2 && minor
== 6 && micro
< 16))
125 p
->dont_use_ppoll
= TRUE
;
131 sigemptyset(&p
->sigset_unblocked
);
132 p
->timer
= (timer_t
) -1;
136 p
->n_pollfd_alloc
= 32;
137 p
->pollfd
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
138 p
->pollfd2
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
139 p
->n_pollfd_used
= 0;
141 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
142 p
->timer_enabled
= FALSE
;
145 p
->installed
= FALSE
;
146 p
->scan_for_dead
= FALSE
;
147 p
->rebuild_needed
= FALSE
;
150 PA_LLIST_HEAD_INIT(pa_rtpoll_item
, p
->items
);
155 void pa_rtpoll_install(pa_rtpoll
*p
) {
157 pa_assert(!p
->installed
);
163 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 memset(&timeout
, 0, sizeof(timeout
));
371 /* Calculate timeout */
372 if (wait
&& !p
->quit
&& p
->timer_enabled
) {
374 pa_rtclock_get(&now
);
376 if (pa_timeval_cmp(&p
->next_elapse
, &now
) > 0)
377 pa_timeval_add(&timeout
, pa_timeval_diff(&p
->next_elapse
, &now
));
380 /* OK, now let's sleep */
384 if (!p
->dont_use_ppoll
)
388 ts
.tv_sec
= timeout
.tv_sec
;
389 ts
.tv_nsec
= timeout
.tv_usec
* 1000;
390 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, (!wait
|| p
->quit
|| p
->timer_enabled
) ? &ts
: NULL
, p
->rtsig
< 0 ? NULL
: &p
->sigset_unblocked
);
397 r
= poll(p
->pollfd
, p
->n_pollfd_used
, (!wait
|| p
->quit
|| p
->timer_enabled
) ? (timeout
.tv_sec
*1000) + (timeout
.tv_usec
/ 1000) : -1);
400 if (errno
== EAGAIN
|| errno
== EINTR
)
403 pa_log_error("poll(): %s", pa_cstrerror(errno
));
405 reset_all_revents(p
);
408 /* Let's tell everyone that we left the sleep */
409 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
424 if (p
->scan_for_dead
) {
427 p
->scan_for_dead
= FALSE
;
429 for (i
= p
->items
; i
; i
= n
) {
433 rtpoll_item_destroy(i
);
437 return r
< 0 ? r
: !p
->quit
;
440 static void update_timer(pa_rtpoll
*p
) {
446 if (!p
->dont_use_ppoll
) {
449 if (p
->timer
== (timer_t
) -1) {
452 memset(&se
, 0, sizeof(se
));
453 se
.sigev_notify
= SIGEV_SIGNAL
;
454 se
.sigev_signo
= p
->rtsig
;
456 if (timer_create(CLOCK_MONOTONIC
, &se
, &p
->timer
) < 0)
457 if (timer_create(CLOCK_REALTIME
, &se
, &p
->timer
) < 0) {
458 pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno
));
459 p
->timer
= (timer_t
) -1;
463 if (p
->timer
!= (timer_t
) -1) {
464 struct itimerspec its
;
465 struct timespec ts
= { .tv_sec
= 0, .tv_nsec
= 0 };
468 /* First disarm timer */
469 memset(&its
, 0, sizeof(its
));
470 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
472 /* Remove a signal that might be waiting in the signal q */
473 pa_assert_se(sigemptyset(&ss
) == 0);
474 pa_assert_se(sigaddset(&ss
, p
->rtsig
) == 0);
475 sigtimedwait(&ss
, NULL
, &ts
);
477 /* And install the new timer */
478 if (p
->timer_enabled
) {
479 memset(&its
, 0, sizeof(its
));
481 its
.it_value
.tv_sec
= p
->next_elapse
.tv_sec
;
482 its
.it_value
.tv_nsec
= p
->next_elapse
.tv_usec
*1000;
484 /* Make sure that 0,0 is not understood as
486 if (its
.it_value
.tv_sec
== 0 && its
.it_value
.tv_nsec
== 0)
487 its
.it_value
.tv_nsec
= 1;
488 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
499 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timeval
*ts
) {
503 p
->next_elapse
= *ts
;
504 p
->timer_enabled
= TRUE
;
509 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
512 pa_rtclock_get(&p
->next_elapse
);
513 pa_timeval_add(&p
->next_elapse
, usec
);
514 p
->timer_enabled
= TRUE
;
519 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
522 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
523 p
->timer_enabled
= FALSE
;
528 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
529 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
533 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
534 i
= pa_xnew(pa_rtpoll_item
, 1);
547 for (j
= p
->items
; j
; j
= j
->next
) {
548 if (prio
<= j
->priority
)
554 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
557 p
->rebuild_needed
= 1;
558 p
->n_pollfd_used
+= n_fds
;
564 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
567 if (i
->rtpoll
->running
) {
569 i
->rtpoll
->scan_for_dead
= TRUE
;
573 rtpoll_item_destroy(i
);
576 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
580 if (i
->rtpoll
->rebuild_needed
)
581 rtpoll_rebuild(i
->rtpoll
);
584 *n_fds
= i
->n_pollfd
;
589 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
591 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
593 i
->before_cb
= before_cb
;
596 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
598 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
600 i
->after_cb
= after_cb
;
603 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
605 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
607 i
->work_cb
= work_cb
;
610 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
613 i
->userdata
= userdata
;
616 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
622 static int fdsem_before(pa_rtpoll_item
*i
) {
624 if (pa_fdsem_before_poll(i
->userdata
) < 0)
625 return 1; /* 1 means immediate restart of the loop */
630 static void fdsem_after(pa_rtpoll_item
*i
) {
633 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
634 pa_fdsem_after_poll(i
->userdata
);
637 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
639 struct pollfd
*pollfd
;
644 i
= pa_rtpoll_item_new(p
, prio
, 1);
646 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
648 pollfd
->fd
= pa_fdsem_get(f
);
649 pollfd
->events
= POLLIN
;
651 i
->before_cb
= fdsem_before
;
652 i
->after_cb
= fdsem_after
;
658 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
661 if (pa_asyncmsgq_before_poll(i
->userdata
) < 0)
662 return 1; /* 1 means immediate restart of the loop */
667 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
670 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
671 pa_asyncmsgq_after_poll(i
->userdata
);
674 static int asyncmsgq_work(pa_rtpoll_item
*i
) {
675 pa_msgobject
*object
;
683 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
686 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
687 pa_asyncmsgq_done(i
->userdata
, 0);
688 pa_rtpoll_quit(i
->rtpoll
);
692 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
693 pa_asyncmsgq_done(i
->userdata
, ret
);
700 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
702 struct pollfd
*pollfd
;
707 i
= pa_rtpoll_item_new(p
, prio
, 1);
709 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
710 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
711 pollfd
->events
= POLLIN
;
713 i
->before_cb
= asyncmsgq_before
;
714 i
->after_cb
= asyncmsgq_after
;
715 i
->work_cb
= asyncmsgq_work
;
721 void pa_rtpoll_quit(pa_rtpoll
*p
) {