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>
49 struct pollfd
*pollfd
, *pollfd2
;
50 unsigned n_pollfd_alloc
, n_pollfd_used
;
53 struct timespec next_elapse
;
57 int running
, installed
, rebuild_needed
;
61 sigset_t sigset_unblocked
;
68 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
71 struct pa_rtpoll_item
{
75 struct pollfd
*pollfd
;
78 int (*before_cb
)(pa_rtpoll_item
*i
);
79 void (*after_cb
)(pa_rtpoll_item
*i
);
82 PA_LLIST_FIELDS(pa_rtpoll_item
);
85 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
87 static void signal_handler_noop(int s
) { }
89 pa_rtpoll
*pa_rtpoll_new(void) {
92 p
= pa_xnew(pa_rtpoll
, 1);
97 /* ppoll is broken on Linux < 2.6.16 */
99 p
->dont_use_ppoll
= 0;
103 unsigned major
, minor
, micro
;
105 pa_assert_se(uname(&u
) == 0);
107 if (sscanf(u
.release
, "%u.%u.%u", &major
, &minor
, µ
) != 3 ||
109 (major
== 2 && minor
< 6) ||
110 (major
== 2 && minor
== 6 && micro
< 16))
112 p
->dont_use_ppoll
= 1;
118 sigemptyset(&p
->sigset_unblocked
);
119 p
->timer
= (timer_t
) -1;
123 p
->n_pollfd_alloc
= 32;
124 p
->pollfd
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
125 p
->pollfd2
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
126 p
->n_pollfd_used
= 0;
129 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
130 p
->timer_enabled
= 0;
134 p
->scan_for_dead
= 0;
135 p
->rebuild_needed
= 0;
137 PA_LLIST_HEAD_INIT(pa_rtpoll_item
, p
->items
);
142 void pa_rtpoll_install(pa_rtpoll
*p
) {
144 pa_assert(!p
->installed
);
149 if (p
->dont_use_ppoll
)
152 if ((p
->rtsig
= pa_rtsig_get_for_thread()) < 0) {
153 pa_log_warn("Failed to reserve POSIX realtime signal.");
157 pa_log_debug("Acquired POSIX realtime signal SIGRTMIN+%i", p
->rtsig
- SIGRTMIN
);
163 pa_assert_se(sigemptyset(&ss
) == 0);
164 pa_assert_se(sigaddset(&ss
, p
->rtsig
) == 0);
165 pa_assert_se(pthread_sigmask(SIG_BLOCK
, &ss
, &p
->sigset_unblocked
) == 0);
166 pa_assert_se(sigdelset(&p
->sigset_unblocked
, p
->rtsig
) == 0);
168 memset(&sa
, 0, sizeof(sa
));
169 sa
.sa_handler
= signal_handler_noop
;
170 pa_assert_se(sigemptyset(&sa
.sa_mask
) == 0);
172 pa_assert_se(sigaction(p
->rtsig
, &sa
, NULL
) == 0);
174 /* We never reset the signal handler. Why should we? */
180 static void rtpoll_rebuild(pa_rtpoll
*p
) {
182 struct pollfd
*e
, *t
;
188 p
->rebuild_needed
= 0;
190 if (p
->n_pollfd_used
> p
->n_pollfd_alloc
) {
191 /* Hmm, we have to allocate some more space */
192 p
->n_pollfd_alloc
= p
->n_pollfd_used
* 2;
193 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
199 for (i
= p
->items
; i
; i
= i
->next
) {
201 if (i
->n_pollfd
> 0) {
202 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
205 memcpy(e
, i
->pollfd
, l
);
216 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
218 p
->pollfd
= p
->pollfd2
;
222 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
226 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
233 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
235 p
->n_pollfd_used
-= i
->n_pollfd
;
237 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
240 p
->rebuild_needed
= 1;
243 void pa_rtpoll_free(pa_rtpoll
*p
) {
247 rtpoll_item_destroy(p
->items
);
250 pa_xfree(p
->pollfd2
);
253 if (p
->timer
!= (timer_t
) -1)
254 timer_delete(p
->timer
);
260 int pa_rtpoll_run(pa_rtpoll
*p
, int wait
) {
265 struct timespec timeout
;
268 pa_assert(!p
->running
);
269 pa_assert(p
->installed
);
273 for (i
= p
->items
; i
; i
= i
->next
) {
281 if (i
->before_cb(i
) < 0) {
283 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
285 for (i
= i
->prev
; i
; i
= i
->prev
) {
300 if (p
->rebuild_needed
)
303 /* Calculate timeout */
307 } else if (p
->timer_enabled
) {
309 pa_rtclock_get(&now
);
311 if (pa_timespec_cmp(&p
->next_elapse
, &now
) <= 0)
312 memset(&timeout
, 0, sizeof(timeout
));
314 pa_timespec_store(&timeout
, pa_timespec_diff(&p
->next_elapse
, &now
));
317 /* OK, now let's sleep */
321 if (!p
->dont_use_ppoll
)
323 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
> 0 ? &timeout
: NULL
, p
->rtsig
< 0 ? NULL
: &p
->sigset_unblocked
);
329 r
= poll(p
->pollfd
, p
->n_pollfd_used
, p
->timer_enabled
> 0 ? (timeout
.tv_sec
*1000) + (timeout
.tv_nsec
/ 1000000) : -1);
334 if (p
->timer_enabled
) {
337 pa_rtclock_get(&now
);
339 pa_timespec_add(&p
->next_elapse
, p
->period
);
341 /* Guarantee that the next timeout will happen in the future */
342 if (pa_timespec_cmp(&p
->next_elapse
, &now
) < 0)
343 pa_timespec_add(&p
->next_elapse
, (pa_timespec_diff(&now
, &p
->next_elapse
) / p
->period
+ 1) * p
->period
);
346 p
->timer_enabled
= 0;
349 if (r
== 0 || (r
< 0 && (errno
== EAGAIN
|| errno
== EINTR
))) {
354 for (i
= p
->items
; i
; i
= i
->next
) {
365 for (j
= 0; j
< i
->n_pollfd
; j
++)
366 i
->pollfd
[j
].revents
= 0;
376 if (p
->scan_for_dead
) {
379 p
->scan_for_dead
= 0;
381 for (i
= p
->items
; i
; i
= n
) {
385 rtpoll_item_destroy(i
);
395 static void update_timer(pa_rtpoll
*p
) {
401 if (!p
->dont_use_ppoll
) {
404 if (p
->timer
== (timer_t
) -1) {
407 memset(&se
, 0, sizeof(se
));
408 se
.sigev_notify
= SIGEV_SIGNAL
;
409 se
.sigev_signo
= p
->rtsig
;
411 if (timer_create(CLOCK_MONOTONIC
, &se
, &p
->timer
) < 0)
412 if (timer_create(CLOCK_REALTIME
, &se
, &p
->timer
) < 0) {
413 pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno
));
414 p
->timer
= (timer_t
) -1;
418 if (p
->timer
!= (timer_t
) -1) {
419 struct itimerspec its
;
420 memset(&its
, 0, sizeof(its
));
422 if (p
->timer_enabled
) {
423 its
.it_value
= p
->next_elapse
;
425 /* Make sure that 0,0 is not understood as
427 if (its
.it_value
.tv_sec
== 0)
428 its
.it_value
.tv_nsec
= 1;
431 pa_timespec_store(&its
.it_interval
, p
->period
);
434 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
444 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, const struct timespec
*ts
) {
448 p
->next_elapse
= *ts
;
450 p
->timer_enabled
= 1;
455 void pa_rtpoll_set_timer_periodic(pa_rtpoll
*p
, pa_usec_t usec
) {
459 pa_rtclock_get(&p
->next_elapse
);
460 pa_timespec_add(&p
->next_elapse
, usec
);
461 p
->timer_enabled
= 1;
466 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
470 pa_rtclock_get(&p
->next_elapse
);
471 pa_timespec_add(&p
->next_elapse
, usec
);
472 p
->timer_enabled
= 1;
477 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
481 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
482 p
->timer_enabled
= 0;
487 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, unsigned n_fds
) {
491 pa_assert(n_fds
> 0);
493 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
494 i
= pa_xnew(pa_rtpoll_item
, 1);
505 PA_LLIST_PREPEND(pa_rtpoll_item
, p
->items
, i
);
507 p
->rebuild_needed
= 1;
508 p
->n_pollfd_used
+= n_fds
;
513 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
516 if (i
->rtpoll
->running
) {
518 i
->rtpoll
->scan_for_dead
= 1;
522 rtpoll_item_destroy(i
);
525 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
528 if (i
->rtpoll
->rebuild_needed
)
529 rtpoll_rebuild(i
->rtpoll
);
532 *n_fds
= i
->n_pollfd
;
537 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
540 i
->before_cb
= before_cb
;
543 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
546 i
->after_cb
= after_cb
;
549 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
552 i
->userdata
= userdata
;
555 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
561 static int fdsem_before(pa_rtpoll_item
*i
) {
562 return pa_fdsem_before_poll(i
->userdata
);
565 static void fdsem_after(pa_rtpoll_item
*i
) {
566 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
567 pa_fdsem_after_poll(i
->userdata
);
570 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_fdsem
*f
) {
572 struct pollfd
*pollfd
;
577 i
= pa_rtpoll_item_new(p
, 1);
579 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
581 pollfd
->fd
= pa_fdsem_get(f
);
582 pollfd
->events
= POLLIN
;
584 i
->before_cb
= fdsem_before
;
585 i
->after_cb
= fdsem_after
;
591 static int asyncmsgq_before(pa_rtpoll_item
*i
) {
592 return pa_asyncmsgq_before_poll(i
->userdata
);
595 static void asyncmsgq_after(pa_rtpoll_item
*i
) {
596 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
597 pa_asyncmsgq_after_poll(i
->userdata
);
600 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq(pa_rtpoll
*p
, pa_asyncmsgq
*q
) {
602 struct pollfd
*pollfd
;
607 i
= pa_rtpoll_item_new(p
, 1);
609 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
610 pollfd
->fd
= pa_asyncmsgq_get_fd(q
);
611 pollfd
->events
= POLLIN
;
613 i
->before_cb
= asyncmsgq_before
;
614 i
->after_cb
= asyncmsgq_after
;