2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <sys/types.h>
34 #include <sys/utsname.h>
40 #include <pulsecore/poll.h>
43 #include <pulse/xmalloc.h>
44 #include <pulse/timeval.h>
46 #include <pulsecore/core-error.h>
47 #include <pulsecore/rtclock.h>
48 #include <pulsecore/macro.h>
49 #include <pulsecore/llist.h>
50 #include <pulsecore/rtsig.h>
51 #include <pulsecore/flist.h>
52 #include <pulsecore/core-util.h>
54 #include <pulsecore/winsock.h>
59 struct pollfd
*pollfd
, *pollfd2
;
60 unsigned n_pollfd_alloc
, n_pollfd_used
;
62 pa_bool_t timer_enabled
;
63 struct timeval next_elapse
;
65 pa_bool_t scan_for_dead
;
66 pa_bool_t running
, installed
, rebuild_needed
, quit
;
70 sigset_t sigset_unblocked
;
72 pa_bool_t timer_armed
;
74 pa_bool_t dont_use_ppoll
;
78 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
81 struct pa_rtpoll_item
{
85 pa_rtpoll_priority_t priority
;
87 struct pollfd
*pollfd
;
90 int (*work_cb
)(pa_rtpoll_item
*i
);
91 int (*before_cb
)(pa_rtpoll_item
*i
);
92 void (*after_cb
)(pa_rtpoll_item
*i
);
95 PA_LLIST_FIELDS(pa_rtpoll_item
);
98 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
100 static void signal_handler_noop(int s
) { /* write(2, "signal\n", 7); */ }
102 pa_rtpoll
*pa_rtpoll_new(void) {
105 p
= pa_xnew(pa_rtpoll
, 1);
110 /* ppoll is broken on Linux < 2.6.16 */
111 p
->dont_use_ppoll
= FALSE
;
115 unsigned major
, minor
, micro
;
117 pa_assert_se(uname(&u
) == 0);
119 if (sscanf(u
.release
, "%u.%u.%u", &major
, &minor
, µ
) != 3 ||
121 (major
== 2 && minor
< 6) ||
122 (major
== 2 && minor
== 6 && micro
< 16))
124 p
->dont_use_ppoll
= TRUE
;
130 sigemptyset(&p
->sigset_unblocked
);
131 p
->timer
= (timer_t
) -1;
132 p
->timer_armed
= FALSE
;
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 if (p
->timer_armed
) {
469 /* First disarm timer */
470 memset(&its
, 0, sizeof(its
));
471 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
473 /* Remove a signal that might be waiting in the signal q */
474 pa_assert_se(sigemptyset(&ss
) == 0);
475 pa_assert_se(sigaddset(&ss
, p
->rtsig
) == 0);
476 sigtimedwait(&ss
, NULL
, &ts
);
479 /* And install the new timer */
480 if (p
->timer_enabled
) {
481 memset(&its
, 0, sizeof(its
));
483 its
.it_value
.tv_sec
= p
->next_elapse
.tv_sec
;
484 its
.it_value
.tv_nsec
= p
->next_elapse
.tv_usec
*1000;
486 /* Make sure that 0,0 is not understood as
488 if (its
.it_value
.tv_sec
== 0 && its
.it_value
.tv_nsec
== 0)
489 its
.it_value
.tv_nsec
= 1;
490 pa_assert_se(timer_settime(p
->timer
, TIMER_ABSTIME
, &its
, NULL
) == 0);
493 p
->timer_armed
= p
->timer_enabled
;
503 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, pa_usec_t usec
) {
506 pa_timeval_store(&p
->next_elapse
, usec
);
507 p
->timer_enabled
= TRUE
;
512 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
515 /* Scheduling a timeout for more than an hour is very very suspicious */
516 pa_assert(usec
<= PA_USEC_PER_SEC
*60ULL*60ULL);
518 pa_rtclock_get(&p
->next_elapse
);
519 pa_timeval_add(&p
->next_elapse
, usec
);
520 p
->timer_enabled
= TRUE
;
525 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
528 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
529 p
->timer_enabled
= FALSE
;
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
= TRUE
;
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_read_before(pa_rtpoll_item
*i
) {
667 if (pa_asyncmsgq_read_before_poll(i
->userdata
) < 0)
668 return 1; /* 1 means immediate restart of the loop */
673 static void asyncmsgq_read_after(pa_rtpoll_item
*i
) {
676 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
677 pa_asyncmsgq_read_after_poll(i
->userdata
);
680 static int asyncmsgq_read_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_read(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_read_fd(q
);
717 pollfd
->events
= POLLIN
;
719 i
->before_cb
= asyncmsgq_read_before
;
720 i
->after_cb
= asyncmsgq_read_after
;
721 i
->work_cb
= asyncmsgq_read_work
;
727 static int asyncmsgq_write_before(pa_rtpoll_item
*i
) {
730 pa_asyncmsgq_write_before_poll(i
->userdata
);
734 static void asyncmsgq_write_after(pa_rtpoll_item
*i
) {
737 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
738 pa_asyncmsgq_write_after_poll(i
->userdata
);
741 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
743 struct pollfd
*pollfd
;
748 i
= pa_rtpoll_item_new(p
, prio
, 1);
750 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
751 pollfd
->fd
= pa_asyncmsgq_write_fd(q
);
752 pollfd
->events
= POLLIN
;
754 i
->before_cb
= asyncmsgq_write_before
;
755 i
->after_cb
= asyncmsgq_write_after
;
762 void pa_rtpoll_quit(pa_rtpoll
*p
) {