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>
36 #include <pulsecore/poll.h>
39 #include <pulse/xmalloc.h>
40 #include <pulse/timeval.h>
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/core-rtclock.h>
44 #include <pulsecore/macro.h>
45 #include <pulsecore/llist.h>
46 #include <pulsecore/flist.h>
47 #include <pulsecore/core-util.h>
48 #include <pulsecore/winsock.h>
49 #include <pulsecore/ratelimit.h>
53 /* #define DEBUG_TIMING */
56 struct pollfd
*pollfd
, *pollfd2
;
57 unsigned n_pollfd_alloc
, n_pollfd_used
;
59 struct timeval next_elapse
;
60 pa_bool_t timer_enabled
:1;
62 pa_bool_t scan_for_dead
:1;
64 pa_bool_t rebuild_needed
:1;
66 pa_bool_t timer_elapsed
:1;
70 pa_usec_t slept
, awake
;
73 PA_LLIST_HEAD(pa_rtpoll_item
, items
);
76 struct pa_rtpoll_item
{
80 pa_rtpoll_priority_t priority
;
82 struct pollfd
*pollfd
;
85 int (*work_cb
)(pa_rtpoll_item
*i
);
86 int (*before_cb
)(pa_rtpoll_item
*i
);
87 void (*after_cb
)(pa_rtpoll_item
*i
);
90 PA_LLIST_FIELDS(pa_rtpoll_item
);
93 PA_STATIC_FLIST_DECLARE(items
, 0, pa_xfree
);
95 pa_rtpoll
*pa_rtpoll_new(void) {
98 p
= pa_xnew0(pa_rtpoll
, 1);
100 p
->n_pollfd_alloc
= 32;
101 p
->pollfd
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
102 p
->pollfd2
= pa_xnew(struct pollfd
, p
->n_pollfd_alloc
);
105 p
->timestamp
= pa_rtclock_now();
111 static void rtpoll_rebuild(pa_rtpoll
*p
) {
113 struct pollfd
*e
, *t
;
119 p
->rebuild_needed
= FALSE
;
121 if (p
->n_pollfd_used
> p
->n_pollfd_alloc
) {
122 /* Hmm, we have to allocate some more space */
123 p
->n_pollfd_alloc
= p
->n_pollfd_used
* 2;
124 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
130 for (i
= p
->items
; i
; i
= i
->next
) {
132 if (i
->n_pollfd
> 0) {
133 size_t l
= i
->n_pollfd
* sizeof(struct pollfd
);
136 memcpy(e
, i
->pollfd
, l
);
147 pa_assert((unsigned) (e
- p
->pollfd2
) == p
->n_pollfd_used
);
149 p
->pollfd
= p
->pollfd2
;
153 p
->pollfd2
= pa_xrealloc(p
->pollfd2
, p
->n_pollfd_alloc
* sizeof(struct pollfd
));
156 static void rtpoll_item_destroy(pa_rtpoll_item
*i
) {
163 PA_LLIST_REMOVE(pa_rtpoll_item
, p
->items
, i
);
165 p
->n_pollfd_used
-= i
->n_pollfd
;
167 if (pa_flist_push(PA_STATIC_FLIST_GET(items
), i
) < 0)
170 p
->rebuild_needed
= TRUE
;
173 void pa_rtpoll_free(pa_rtpoll
*p
) {
177 rtpoll_item_destroy(p
->items
);
180 pa_xfree(p
->pollfd2
);
185 static void reset_revents(pa_rtpoll_item
*i
) {
191 if (!(f
= pa_rtpoll_item_get_pollfd(i
, &n
)))
198 static void reset_all_revents(pa_rtpoll
*p
) {
203 for (i
= p
->items
; i
; i
= i
->next
) {
212 int pa_rtpoll_run(pa_rtpoll
*p
, pa_bool_t wait_op
) {
215 struct timeval timeout
;
218 pa_assert(!p
->running
);
221 p
->timer_elapsed
= FALSE
;
223 /* First, let's do some work */
224 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
236 if ((k
= i
->work_cb(i
)) != 0) {
244 /* Now let's prepare for entering the sleep */
245 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
254 if (p
->quit
|| (k
= i
->before_cb(i
)) != 0) {
256 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
258 for (i
= i
->prev
; i
; i
= i
->prev
) {
276 if (p
->rebuild_needed
)
281 /* Calculate timeout */
282 if (wait_op
&& !p
->quit
&& p
->timer_enabled
) {
284 pa_rtclock_get(&now
);
286 if (pa_timeval_cmp(&p
->next_elapse
, &now
) > 0)
287 pa_timeval_add(&timeout
, pa_timeval_diff(&p
->next_elapse
, &now
));
292 pa_usec_t now
= pa_rtclock_now();
293 p
->awake
= now
- p
->timestamp
;
298 /* OK, now let's sleep */
302 ts
.tv_sec
= timeout
.tv_sec
;
303 ts
.tv_nsec
= timeout
.tv_usec
* 1000;
304 r
= ppoll(p
->pollfd
, p
->n_pollfd_used
, (!wait_op
|| p
->quit
|| p
->timer_enabled
) ? &ts
: NULL
, NULL
);
307 r
= poll(p
->pollfd
, p
->n_pollfd_used
, (!wait_op
|| p
->quit
|| p
->timer_enabled
) ? (int) ((timeout
.tv_sec
*1000) + (timeout
.tv_usec
/ 1000)) : -1);
310 p
->timer_elapsed
= r
== 0;
314 pa_usec_t now
= pa_rtclock_now();
315 p
->slept
= now
- p
->timestamp
;
318 pa_log("Process time %llu ms; sleep time %llu ms",
319 (unsigned long long) (p
->awake
/ PA_USEC_PER_MSEC
),
320 (unsigned long long) (p
->slept
/ PA_USEC_PER_MSEC
));
325 if (errno
== EAGAIN
|| errno
== EINTR
)
328 pa_log_error("poll(): %s", pa_cstrerror(errno
));
330 reset_all_revents(p
);
333 /* Let's tell everyone that we left the sleep */
334 for (i
= p
->items
; i
&& i
->priority
< PA_RTPOLL_NEVER
; i
= i
->next
) {
349 if (p
->scan_for_dead
) {
352 p
->scan_for_dead
= FALSE
;
354 for (i
= p
->items
; i
; i
= n
) {
358 rtpoll_item_destroy(i
);
362 return r
< 0 ? r
: !p
->quit
;
365 void pa_rtpoll_set_timer_absolute(pa_rtpoll
*p
, pa_usec_t usec
) {
368 pa_timeval_store(&p
->next_elapse
, usec
);
369 p
->timer_enabled
= TRUE
;
372 void pa_rtpoll_set_timer_relative(pa_rtpoll
*p
, pa_usec_t usec
) {
375 /* Scheduling a timeout for more than an hour is very very suspicious */
376 pa_assert(usec
<= PA_USEC_PER_SEC
*60ULL*60ULL);
378 pa_rtclock_get(&p
->next_elapse
);
379 pa_timeval_add(&p
->next_elapse
, usec
);
380 p
->timer_enabled
= TRUE
;
383 void pa_rtpoll_set_timer_disabled(pa_rtpoll
*p
) {
386 memset(&p
->next_elapse
, 0, sizeof(p
->next_elapse
));
387 p
->timer_enabled
= FALSE
;
390 pa_rtpoll_item
*pa_rtpoll_item_new(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, unsigned n_fds
) {
391 pa_rtpoll_item
*i
, *j
, *l
= NULL
;
395 if (!(i
= pa_flist_pop(PA_STATIC_FLIST_GET(items
))))
396 i
= pa_xnew(pa_rtpoll_item
, 1);
409 for (j
= p
->items
; j
; j
= j
->next
) {
410 if (prio
<= j
->priority
)
416 PA_LLIST_INSERT_AFTER(pa_rtpoll_item
, p
->items
, j
? j
->prev
: l
, i
);
419 p
->rebuild_needed
= 1;
420 p
->n_pollfd_used
+= n_fds
;
426 void pa_rtpoll_item_free(pa_rtpoll_item
*i
) {
429 if (i
->rtpoll
->running
) {
431 i
->rtpoll
->scan_for_dead
= TRUE
;
435 rtpoll_item_destroy(i
);
438 struct pollfd
*pa_rtpoll_item_get_pollfd(pa_rtpoll_item
*i
, unsigned *n_fds
) {
442 if (i
->rtpoll
->rebuild_needed
)
443 rtpoll_rebuild(i
->rtpoll
);
446 *n_fds
= i
->n_pollfd
;
451 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item
*i
, int (*before_cb
)(pa_rtpoll_item
*i
)) {
453 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
455 i
->before_cb
= before_cb
;
458 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item
*i
, void (*after_cb
)(pa_rtpoll_item
*i
)) {
460 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
462 i
->after_cb
= after_cb
;
465 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item
*i
, int (*work_cb
)(pa_rtpoll_item
*i
)) {
467 pa_assert(i
->priority
< PA_RTPOLL_NEVER
);
469 i
->work_cb
= work_cb
;
472 void pa_rtpoll_item_set_userdata(pa_rtpoll_item
*i
, void *userdata
) {
475 i
->userdata
= userdata
;
478 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item
*i
) {
484 static int fdsem_before(pa_rtpoll_item
*i
) {
486 if (pa_fdsem_before_poll(i
->userdata
) < 0)
487 return 1; /* 1 means immediate restart of the loop */
492 static void fdsem_after(pa_rtpoll_item
*i
) {
495 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
496 pa_fdsem_after_poll(i
->userdata
);
499 pa_rtpoll_item
*pa_rtpoll_item_new_fdsem(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_fdsem
*f
) {
501 struct pollfd
*pollfd
;
506 i
= pa_rtpoll_item_new(p
, prio
, 1);
508 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
510 pollfd
->fd
= pa_fdsem_get(f
);
511 pollfd
->events
= POLLIN
;
513 i
->before_cb
= fdsem_before
;
514 i
->after_cb
= fdsem_after
;
520 static int asyncmsgq_read_before(pa_rtpoll_item
*i
) {
523 if (pa_asyncmsgq_read_before_poll(i
->userdata
) < 0)
524 return 1; /* 1 means immediate restart of the loop */
529 static void asyncmsgq_read_after(pa_rtpoll_item
*i
) {
532 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
533 pa_asyncmsgq_read_after_poll(i
->userdata
);
536 static int asyncmsgq_read_work(pa_rtpoll_item
*i
) {
537 pa_msgobject
*object
;
545 if (pa_asyncmsgq_get(i
->userdata
, &object
, &code
, &data
, &offset
, &chunk
, 0) == 0) {
548 if (!object
&& code
== PA_MESSAGE_SHUTDOWN
) {
549 pa_asyncmsgq_done(i
->userdata
, 0);
550 pa_rtpoll_quit(i
->rtpoll
);
554 ret
= pa_asyncmsgq_dispatch(object
, code
, data
, offset
, &chunk
);
555 pa_asyncmsgq_done(i
->userdata
, ret
);
562 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
564 struct pollfd
*pollfd
;
569 i
= pa_rtpoll_item_new(p
, prio
, 1);
571 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
572 pollfd
->fd
= pa_asyncmsgq_read_fd(q
);
573 pollfd
->events
= POLLIN
;
575 i
->before_cb
= asyncmsgq_read_before
;
576 i
->after_cb
= asyncmsgq_read_after
;
577 i
->work_cb
= asyncmsgq_read_work
;
583 static int asyncmsgq_write_before(pa_rtpoll_item
*i
) {
586 pa_asyncmsgq_write_before_poll(i
->userdata
);
590 static void asyncmsgq_write_after(pa_rtpoll_item
*i
) {
593 pa_assert((i
->pollfd
[0].revents
& ~POLLIN
) == 0);
594 pa_asyncmsgq_write_after_poll(i
->userdata
);
597 pa_rtpoll_item
*pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll
*p
, pa_rtpoll_priority_t prio
, pa_asyncmsgq
*q
) {
599 struct pollfd
*pollfd
;
604 i
= pa_rtpoll_item_new(p
, prio
, 1);
606 pollfd
= pa_rtpoll_item_get_pollfd(i
, NULL
);
607 pollfd
->fd
= pa_asyncmsgq_write_fd(q
);
608 pollfd
->events
= POLLIN
;
610 i
->before_cb
= asyncmsgq_write_before
;
611 i
->after_cb
= asyncmsgq_write_after
;
618 void pa_rtpoll_quit(pa_rtpoll
*p
) {
624 pa_bool_t
pa_rtpoll_timer_elapsed(pa_rtpoll
*p
) {
627 return p
->timer_elapsed
;