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/utsname.h>
30 #include <sys/types.h>
36 #include <pulse/xmalloc.h>
38 #include <pulsecore/core-error.h>
39 #include <pulsecore/rtclock.h>
40 #include <pulsecore/macro.h>
41 #include <pulsecore/llist.h>
42 #include <pulsecore/rtsig.h>
43 #include <pulsecore/flist.h>
48 struct pollfd
*pollfd
, *pollfd2
;
49 unsigned n_pollfd_alloc
, n_pollfd_used
;
52 struct timespec next_elapse
;
56 int running
, installed
, rebuild_needed
, quit
;
60 sigset_t sigset_unblocked
;
67 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
70 struct pa_rtpoll_item
{
74 pa_rtpoll_priority_t priority
;
76 struct pollfd
*pollfd
;
79 int (*work_cb
)(pa_rtpoll_item
*i
);
80 int (*before_cb
)(pa_rtpoll_item
*i
);
81 void (*after_cb
)(pa_rtpoll_item
*i
);
84 PA_LLIST_FIELDS(pa_rtpoll_item
);
87 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
89 static void signal_handler_noop(int s
) { }
91 pa_rtpoll
*pa_rtpoll_new(void) {
94 p
= pa_xnew(pa_rtpoll
, 1);
99 /* ppoll is broken on Linux < 2.6.16 */
101 p
->dont_use_ppoll
= 0;
105 unsigned major
, minor
, micro
;
107 pa_assert_se(uname(&u
) == 0);
109 if (sscanf(u
.release
, "%u.%u.%u", &major
, &minor
, µ
) != 3 ||
111 (major
== 2 && minor
< 6) ||
112 (major
== 2 && minor
== 6 && micro
< 16))
114 p
->dont_use_ppoll
= 1;
120 sigemptyset(&p
->sigset_unblocked
);
121 p
->timer
= (timer_t
) -1;
125 p
->n_pollfd_alloc
= 32;
126 p
->pollfd
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
127 p
->pollfd2
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
128 p
->n_pollfd_used
= 0;
131 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
132 p
->timer_enabled
= 0;
136 p
->scan_for_dead
= 0;
137 p
->rebuild_needed
= 0;
140 PA_LLIST_HEAD_INIT(pa_rtpoll_item
, p
->items
);
145 void pa_rtpoll_install(pa_rtpoll
*p
) {
147 pa_assert(!p
->installed
);
152 if (p
->dont_use_ppoll
)
155 if ((p
->rtsig
= pa_rtsig_get_for_thread()) < 0) {
156 pa_log_warn("Failed to reserve POSIX realtime signal.");
160 pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p
->rtsig
));
166 pa_assert_se(sigemptyset(&ss
) == 0);
167 pa_assert_se(sigaddset(&ss
, p
->rtsig
) == 0);
168 pa_assert_se(pthread_sigmask(SIG_BLOCK
, &ss
, &p
->sigset_unblocked
) == 0);
169 pa_assert_se(sigdelset(&p
->sigset_unblocked
, p
->rtsig
) == 0);
171 memset(&sa
, 0, sizeof(sa
));
172 sa
.sa_handler
= signal_handler_noop
;
173 pa_assert_se(sigemptyset(&sa
.sa_mask
) == 0);
175 pa_assert_se(sigaction(p
->rtsig
, &sa
, NULL
) == 0);
177 /* We never reset the signal handler. Why should we? */
183 static void rtpoll_rebuild(pa_rtpoll
*p
) {
185 struct pollfd
*e
, *t
;
191 p
->rebuild_needed
= 0;
193 if (p
->n_pollfd_used
> p
->n_pollfd_alloc
) {
194 /* Hmm, we have to allocate some more space */
195 p
->n_pollfd_alloc
= p
->n_pollfd_used
* 2;
196 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
202 for (i
= p
->items
; i
; i
= i
->next
) {
204 if (i
->n_pollfd
> 0) {
205 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
208 memcpy(e
, i
->pollfd
, l
);
219 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
221 p
->pollfd
= p
->pollfd2
;
225 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
229 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
236 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
238 p
->n_pollfd_used
-= i
->n_pollfd
;
240 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
243 p
->rebuild_needed
= 1;
246 void pa_rtpoll_free(pa_rtpoll
*p
) {
250 rtpoll_item_destroy(p
->items
);
253 pa_xfree(p
->pollfd2
);
256 if (p
->timer
!= (timer_t
) -1)
257 timer_delete(p
->timer
);
263 static void reset_revents(pa_rtpoll_item
*i
) {
269 if (!(f
= pa_rtpoll_item_get_pollfd(i
, &n
)))
276 static void reset_all_revents(pa_rtpoll
*p
) {
281 for (i
= p
->items
; i
; i
= i
->next
) {
290 int pa_rtpoll_run(pa_rtpoll
*p
, int wait
) {
293 struct timespec timeout
;
296 pa_assert(!p
->running
);
297 pa_assert(p
->installed
);
301 /* First, let's do some work */
302 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
314 if ((k
= i
->work_cb(i
)) != 0) {
322 /* Now let's prepare for entering the sleep */
323 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
332 if (p
->quit
|| (k
= i
->before_cb(i
)) != 0) {
334 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
336 for (i
= i
->prev
; i
; i
= i
->prev
) {
354 if (p
->rebuild_needed
)
357 /* Calculate timeout */
358 if (!wait
|| p
->quit
) {
361 } else if (p
->timer_enabled
) {
363 pa_rtclock_get(&now
);
365 if (pa_timespec_cmp(&p
->next_elapse
, &now
) <= 0)
366 memset(&timeout
, 0, sizeof(timeout
));
368 pa_timespec_store(&timeout
, pa_timespec_diff(&p
->next_elapse
, &now
));
371 /* OK, now let's sleep */
375 if (!p
->dont_use_ppoll
)
377 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
> 0 ? &timeout
: NULL
, p
->rtsig
< 0 ? NULL
: &p
->sigset_unblocked
);
383 r
= poll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
> 0 ? (timeout
.tv_sec
*1000) + (timeout
.tv_nsec
/ 1000000) : -1);
387 reset_all_revents(p
);
389 if (errno
== EAGAIN
|| errno
== EINTR
)
392 pa_log_error("poll(): %s", pa_cstrerror(errno
));
395 if (p
->timer_enabled
) {
398 pa_rtclock_get(&now
);
400 pa_timespec_add(&p
->next_elapse
, p
->period
);
402 /* Guarantee that the next timeout will happen in the future */
403 if (pa_timespec_cmp(&p
->next_elapse
, &now
) < 0)
404 pa_timespec_add(&p
->next_elapse
, (pa_timespec_diff(&now
, &p
->next_elapse
) / p
->period
+ 1) * p
->period
);
407 p
->timer_enabled
= 0;
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
= 0;
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 memset(&its
, 0, sizeof(its
));
469 if (p
->timer_enabled
) {
470 its
.it_value
= p
->next_elapse
;
472 /* Make sure that 0,0 is not understood as
474 if (its
.it_value
.tv_sec
== 0)
475 its
.it_value
.tv_nsec
= 1;
478 pa_timespec_store(&its
.it_interval
, p
->period
);
481 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
491 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timespec
*ts
) {
495 p
->next_elapse
= *ts
;
497 p
->timer_enabled
= 1;
502 void pa_rtpoll_set_timer_periodic(pa_rtpoll
*p
, pa_usec_t usec
) {
506 pa_rtclock_get(&p
->next_elapse
);
507 pa_timespec_add(&p
->next_elapse
, usec
);
508 p
->timer_enabled
= 1;
513 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
517 pa_rtclock_get(&p
->next_elapse
);
518 pa_timespec_add(&p
->next_elapse
, usec
);
519 p
->timer_enabled
= 1;
524 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
528 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
529 p
->timer_enabled
= 0;
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
= 1;
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
) {