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 memset(&its
, 0, sizeof(its
));
467 if (p
->timer_enabled
) {
468 its
.it_value
.tv_sec
= p
->next_elapse
.tv_sec
;
469 its
.it_value
.tv_nsec
= p
->next_elapse
.tv_usec
*1000;
471 /* Make sure that 0,0 is not understood as
473 if (its
.it_value
.tv_sec
== 0 && its
.it_value
.tv_nsec
== 0)
474 its
.it_value
.tv_nsec
= 1;
477 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
487 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timeval
*ts
) {
491 p
->next_elapse
= *ts
;
492 p
->timer_enabled
= TRUE
;
497 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
500 pa_rtclock_get(&p
->next_elapse
);
501 pa_timeval_add(&p
->next_elapse
, usec
);
502 p
->timer_enabled
= TRUE
;
507 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
510 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
511 p
->timer_enabled
= FALSE
;
516 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
517 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
521 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
522 i
= pa_xnew(pa_rtpoll_item
, 1);
535 for (j
= p
->items
; j
; j
= j
->next
) {
536 if (prio
<= j
->priority
)
542 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
545 p
->rebuild_needed
= 1;
546 p
->n_pollfd_used
+= n_fds
;
552 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
555 if (i
->rtpoll
->running
) {
557 i
->rtpoll
->scan_for_dead
= TRUE
;
561 rtpoll_item_destroy(i
);
564 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
568 if (i
->rtpoll
->rebuild_needed
)
569 rtpoll_rebuild(i
->rtpoll
);
572 *n_fds
= i
->n_pollfd
;
577 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
579 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
581 i
->before_cb
= before_cb
;
584 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
586 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
588 i
->after_cb
= after_cb
;
591 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
593 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
595 i
->work_cb
= work_cb
;
598 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
601 i
->userdata
= userdata
;
604 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
610 static int fdsem_before(pa_rtpoll_item
*i
) {
612 if (pa_fdsem_before_poll(i
->userdata
) < 0)
613 return 1; /* 1 means immediate restart of the loop */
618 static void fdsem_after(pa_rtpoll_item
*i
) {
621 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
622 pa_fdsem_after_poll(i
->userdata
);
625 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
627 struct pollfd
*pollfd
;
632 i
= pa_rtpoll_item_new(p
, prio
, 1);
634 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
636 pollfd
->fd
= pa_fdsem_get(f
);
637 pollfd
->events
= POLLIN
;
639 i
->before_cb
= fdsem_before
;
640 i
->after_cb
= fdsem_after
;
646 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
649 if (pa_asyncmsgq_before_poll(i
->userdata
) < 0)
650 return 1; /* 1 means immediate restart of the loop */
655 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
658 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
659 pa_asyncmsgq_after_poll(i
->userdata
);
662 static int asyncmsgq_work(pa_rtpoll_item
*i
) {
663 pa_msgobject
*object
;
671 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
674 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
675 pa_asyncmsgq_done(i
->userdata
, 0);
676 pa_rtpoll_quit(i
->rtpoll
);
680 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
681 pa_asyncmsgq_done(i
->userdata
, ret
);
688 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
690 struct pollfd
*pollfd
;
695 i
= pa_rtpoll_item_new(p
, prio
, 1);
697 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
698 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
699 pollfd
->events
= POLLIN
;
701 i
->before_cb
= asyncmsgq_before
;
702 i
->after_cb
= asyncmsgq_after
;
703 i
->work_cb
= asyncmsgq_work
;
709 void pa_rtpoll_quit(pa_rtpoll
*p
) {