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>
33 #include <pulse/xmalloc.h>
34 #include <pulse/timeval.h>
36 #include <pulsecore/poll.h>
37 #include <pulsecore/core-error.h>
38 #include <pulsecore/core-rtclock.h>
39 #include <pulsecore/macro.h>
40 #include <pulsecore/llist.h>
41 #include <pulsecore/flist.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/winsock.h>
44 #include <pulsecore/ratelimit.h>
48 /* #define DEBUG_TIMING */
51 struct pollfd
*pollfd
, *pollfd2
;
52 unsigned n_pollfd_alloc
, n_pollfd_used
;
54 struct timeval next_elapse
;
55 pa_bool_t timer_enabled
:1;
57 pa_bool_t scan_for_dead
:1;
59 pa_bool_t rebuild_needed
:1;
61 pa_bool_t timer_elapsed
:1;
65 pa_usec_t slept
, awake
;
68 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
71 struct pa_rtpoll_item
{
75 pa_rtpoll_priority_t priority
;
77 struct pollfd
*pollfd
;
80 int (*work_cb
)(pa_rtpoll_item
*i
);
81 int (*before_cb
)(pa_rtpoll_item
*i
);
82 void (*after_cb
)(pa_rtpoll_item
*i
);
85 PA_LLIST_FIELDS(pa_rtpoll_item
);
88 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
90 pa_rtpoll
*pa_rtpoll_new(void) {
93 p
= pa_xnew0(pa_rtpoll
, 1);
95 p
->n_pollfd_alloc
= 32;
96 p
->pollfd
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
97 p
->pollfd2
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
100 p
->timestamp
= pa_rtclock_now();
106 static void rtpoll_rebuild(pa_rtpoll
*p
) {
108 struct pollfd
*e
, *t
;
114 p
->rebuild_needed
= FALSE
;
116 if (p
->n_pollfd_used
> p
->n_pollfd_alloc
) {
117 /* Hmm, we have to allocate some more space */
118 p
->n_pollfd_alloc
= p
->n_pollfd_used
* 2;
119 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
125 for (i
= p
->items
; i
; i
= i
->next
) {
127 if (i
->n_pollfd
> 0) {
128 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
131 memcpy(e
, i
->pollfd
, l
);
142 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
144 p
->pollfd
= p
->pollfd2
;
148 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
151 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
158 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
160 p
->n_pollfd_used
-= i
->n_pollfd
;
162 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
165 p
->rebuild_needed
= TRUE
;
168 void pa_rtpoll_free(pa_rtpoll
*p
) {
172 rtpoll_item_destroy(p
->items
);
175 pa_xfree(p
->pollfd2
);
180 static void reset_revents(pa_rtpoll_item
*i
) {
186 if (!(f
= pa_rtpoll_item_get_pollfd(i
, &n
)))
193 static void reset_all_revents(pa_rtpoll
*p
) {
198 for (i
= p
->items
; i
; i
= i
->next
) {
207 int pa_rtpoll_run(pa_rtpoll
*p
, pa_bool_t wait_op
) {
210 struct timeval timeout
;
213 pa_assert(!p
->running
);
216 p
->timer_elapsed
= FALSE
;
218 /* First, let's do some work */
219 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
231 if ((k
= i
->work_cb(i
)) != 0) {
239 /* Now let's prepare for entering the sleep */
240 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
249 if (p
->quit
|| (k
= i
->before_cb(i
)) != 0) {
251 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
253 for (i
= i
->prev
; i
; i
= i
->prev
) {
271 if (p
->rebuild_needed
)
276 /* Calculate timeout */
277 if (wait_op
&& !p
->quit
&& p
->timer_enabled
) {
279 pa_rtclock_get(&now
);
281 if (pa_timeval_cmp(&p
->next_elapse
, &now
) > 0)
282 pa_timeval_add(&timeout
, pa_timeval_diff(&p
->next_elapse
, &now
));
287 pa_usec_t now
= pa_rtclock_now();
288 p
->awake
= now
- p
->timestamp
;
293 /* OK, now let's sleep */
297 ts
.tv_sec
= timeout
.tv_sec
;
298 ts
.tv_nsec
= timeout
.tv_usec
* 1000;
299 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, (!wait_op
|| p
->quit
|| p
->timer_enabled
) ? &ts
: NULL
, NULL
);
302 r
= pa_poll(p
->pollfd
, p
->n_pollfd_used
, (!wait_op
|| p
->quit
|| p
->timer_enabled
) ? (int) ((timeout
.tv_sec
*1000) + (timeout
.tv_usec
/ 1000)) : -1);
305 p
->timer_elapsed
= r
== 0;
309 pa_usec_t now
= pa_rtclock_now();
310 p
->slept
= now
- p
->timestamp
;
313 pa_log("Process time %llu ms; sleep time %llu ms",
314 (unsigned long long) (p
->awake
/ PA_USEC_PER_MSEC
),
315 (unsigned long long) (p
->slept
/ PA_USEC_PER_MSEC
));
320 if (errno
== EAGAIN
|| errno
== EINTR
)
323 pa_log_error("poll(): %s", pa_cstrerror(errno
));
325 reset_all_revents(p
);
328 /* Let's tell everyone that we left the sleep */
329 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
344 if (p
->scan_for_dead
) {
347 p
->scan_for_dead
= FALSE
;
349 for (i
= p
->items
; i
; i
= n
) {
353 rtpoll_item_destroy(i
);
357 return r
< 0 ? r
: !p
->quit
;
360 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, pa_usec_t usec
) {
363 pa_timeval_store(&p
->next_elapse
, usec
);
364 p
->timer_enabled
= TRUE
;
367 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
370 /* Scheduling a timeout for more than an hour is very very suspicious */
371 pa_assert(usec
<= PA_USEC_PER_SEC
*60ULL*60ULL);
373 pa_rtclock_get(&p
->next_elapse
);
374 pa_timeval_add(&p
->next_elapse
, usec
);
375 p
->timer_enabled
= TRUE
;
378 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
381 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
382 p
->timer_enabled
= FALSE
;
385 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
386 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
390 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
391 i
= pa_xnew(pa_rtpoll_item
, 1);
404 for (j
= p
->items
; j
; j
= j
->next
) {
405 if (prio
<= j
->priority
)
411 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
414 p
->rebuild_needed
= 1;
415 p
->n_pollfd_used
+= n_fds
;
421 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
424 if (i
->rtpoll
->running
) {
426 i
->rtpoll
->scan_for_dead
= TRUE
;
430 rtpoll_item_destroy(i
);
433 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
437 if (i
->rtpoll
->rebuild_needed
)
438 rtpoll_rebuild(i
->rtpoll
);
441 *n_fds
= i
->n_pollfd
;
446 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
448 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
450 i
->before_cb
= before_cb
;
453 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
455 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
457 i
->after_cb
= after_cb
;
460 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
462 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
464 i
->work_cb
= work_cb
;
467 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
470 i
->userdata
= userdata
;
473 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
479 static int fdsem_before(pa_rtpoll_item
*i
) {
481 if (pa_fdsem_before_poll(i
->userdata
) < 0)
482 return 1; /* 1 means immediate restart of the loop */
487 static void fdsem_after(pa_rtpoll_item
*i
) {
490 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
491 pa_fdsem_after_poll(i
->userdata
);
494 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
496 struct pollfd
*pollfd
;
501 i
= pa_rtpoll_item_new(p
, prio
, 1);
503 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
505 pollfd
->fd
= pa_fdsem_get(f
);
506 pollfd
->events
= POLLIN
;
508 i
->before_cb
= fdsem_before
;
509 i
->after_cb
= fdsem_after
;
515 static int asyncmsgq_read_before(pa_rtpoll_item
*i
) {
518 if (pa_asyncmsgq_read_before_poll(i
->userdata
) < 0)
519 return 1; /* 1 means immediate restart of the loop */
524 static void asyncmsgq_read_after(pa_rtpoll_item
*i
) {
527 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
528 pa_asyncmsgq_read_after_poll(i
->userdata
);
531 static int asyncmsgq_read_work(pa_rtpoll_item
*i
) {
532 pa_msgobject
*object
;
540 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
543 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
544 pa_asyncmsgq_done(i
->userdata
, 0);
545 pa_rtpoll_quit(i
->rtpoll
);
549 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
550 pa_asyncmsgq_done(i
->userdata
, ret
);
557 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
559 struct pollfd
*pollfd
;
564 i
= pa_rtpoll_item_new(p
, prio
, 1);
566 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
567 pollfd
->fd
= pa_asyncmsgq_read_fd(q
);
568 pollfd
->events
= POLLIN
;
570 i
->before_cb
= asyncmsgq_read_before
;
571 i
->after_cb
= asyncmsgq_read_after
;
572 i
->work_cb
= asyncmsgq_read_work
;
578 static int asyncmsgq_write_before(pa_rtpoll_item
*i
) {
581 pa_asyncmsgq_write_before_poll(i
->userdata
);
585 static void asyncmsgq_write_after(pa_rtpoll_item
*i
) {
588 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
589 pa_asyncmsgq_write_after_poll(i
->userdata
);
592 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
594 struct pollfd
*pollfd
;
599 i
= pa_rtpoll_item_new(p
, prio
, 1);
601 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
602 pollfd
->fd
= pa_asyncmsgq_write_fd(q
);
603 pollfd
->events
= POLLIN
;
605 i
->before_cb
= asyncmsgq_write_before
;
606 i
->after_cb
= asyncmsgq_write_after
;
613 void pa_rtpoll_quit(pa_rtpoll
*p
) {
619 pa_bool_t
pa_rtpoll_timer_elapsed(pa_rtpoll
*p
) {
622 return p
->timer_elapsed
;