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>
45 #include <pulse/rtclock.h>
49 /* #define DEBUG_TIMING */
52 struct pollfd *pollfd, *pollfd2;
53 unsigned n_pollfd_alloc, n_pollfd_used;
55 struct timeval next_elapse;
56 pa_bool_t timer_enabled:1;
58 pa_bool_t scan_for_dead:1;
60 pa_bool_t rebuild_needed:1;
62 pa_bool_t timer_elapsed:1;
66 pa_usec_t slept, awake;
69 PA_LLIST_HEAD(pa_rtpoll_item, items);
72 struct pa_rtpoll_item {
76 pa_rtpoll_priority_t priority;
78 struct pollfd *pollfd;
81 int (*work_cb)(pa_rtpoll_item *i);
82 int (*before_cb)(pa_rtpoll_item *i);
83 void (*after_cb)(pa_rtpoll_item *i);
86 PA_LLIST_FIELDS(pa_rtpoll_item);
89 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
91 pa_rtpoll *pa_rtpoll_new(void) {
94 p = pa_xnew0(pa_rtpoll, 1);
96 p->n_pollfd_alloc = 32;
97 p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc);
98 p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
101 p->timestamp = pa_rtclock_now();
107 static void rtpoll_rebuild(pa_rtpoll *p) {
109 struct pollfd *e, *t;
115 p->rebuild_needed = FALSE;
117 if (p->n_pollfd_used > p->n_pollfd_alloc) {
118 /* Hmm, we have to allocate some more space */
119 p->n_pollfd_alloc = p->n_pollfd_used * 2;
120 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
126 for (i = p->items; i; i = i->next) {
128 if (i->n_pollfd > 0) {
129 size_t l = i->n_pollfd * sizeof(struct pollfd);
132 memcpy(e, i->pollfd, l);
143 pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used);
145 p->pollfd = p->pollfd2;
149 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
152 static void rtpoll_item_destroy(pa_rtpoll_item *i) {
159 PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
161 p->n_pollfd_used -= i->n_pollfd;
163 if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
166 p->rebuild_needed = TRUE;
169 void pa_rtpoll_free(pa_rtpoll *p) {
173 rtpoll_item_destroy(p->items);
176 pa_xfree(p->pollfd2);
181 static void reset_revents(pa_rtpoll_item *i) {
187 if (!(f = pa_rtpoll_item_get_pollfd(i, &n)))
194 static void reset_all_revents(pa_rtpoll *p) {
199 for (i = p->items; i; i = i->next) {
208 int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait_op) {
211 struct timeval timeout;
214 pa_assert(!p->running);
217 pa_log("rtpoll_run");
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) {
235 pa_log("rtpoll finish");
240 if ((k = i->work_cb(i)) != 0) {
244 pa_log("rtpoll finish");
250 /* Now let's prepare for entering the sleep */
251 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
260 if (p->quit || (k = i->before_cb(i)) != 0) {
262 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
264 for (i = i->prev; i; i = i->prev) {
278 pa_log("rtpoll finish");
284 if (p->rebuild_needed)
289 /* Calculate timeout */
290 if (wait_op && !p->quit && p->timer_enabled) {
292 pa_rtclock_get(&now);
294 if (pa_timeval_cmp(&p->next_elapse, &now) > 0)
295 pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now));
300 pa_usec_t now = pa_rtclock_now();
301 p->awake = now - p->timestamp;
303 if (!wait_op || p->quit || p->timer_enabled)
304 pa_log("poll timeout: %d ms ",(int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)));
306 pa_log("poll timeout is ZERO");
310 /* OK, now let's sleep */
314 ts.tv_sec = timeout.tv_sec;
315 ts.tv_nsec = timeout.tv_usec * 1000;
316 r = ppoll(p->pollfd, p->n_pollfd_used, (!wait_op || p->quit || p->timer_enabled) ? &ts : NULL, NULL);
319 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);
322 p->timer_elapsed = r == 0;
326 pa_usec_t now = pa_rtclock_now();
327 p->slept = now - p->timestamp;
330 pa_log("Process time %llu ms; sleep time %llu ms",
331 (unsigned long long) (p->awake / PA_USEC_PER_MSEC),
332 (unsigned long long) (p->slept / PA_USEC_PER_MSEC));
337 if (errno == EAGAIN || errno == EINTR)
340 pa_log_error("poll(): %s", pa_cstrerror(errno));
342 reset_all_revents(p);
345 /* Let's tell everyone that we left the sleep */
346 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
361 if (p->scan_for_dead) {
364 p->scan_for_dead = FALSE;
366 for (i = p->items; i; i = n) {
370 rtpoll_item_destroy(i);
374 return r < 0 ? r : !p->quit;
377 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) {
380 pa_timeval_store(&p->next_elapse, usec);
381 p->timer_enabled = TRUE;
384 void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
387 /* Scheduling a timeout for more than an hour is very very suspicious */
388 pa_assert(usec <= PA_USEC_PER_SEC*60ULL*60ULL);
390 pa_rtclock_get(&p->next_elapse);
391 pa_timeval_add(&p->next_elapse, usec);
392 p->timer_enabled = TRUE;
395 void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
398 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
399 p->timer_enabled = FALSE;
402 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
403 pa_rtpoll_item *i, *j, *l = NULL;
407 if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
408 i = pa_xnew(pa_rtpoll_item, 1);
421 for (j = p->items; j; j = j->next) {
422 if (prio <= j->priority)
428 PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i);
431 p->rebuild_needed = 1;
432 p->n_pollfd_used += n_fds;
438 void pa_rtpoll_item_free(pa_rtpoll_item *i) {
441 if (i->rtpoll->running) {
443 i->rtpoll->scan_for_dead = TRUE;
447 rtpoll_item_destroy(i);
450 struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
454 if (i->rtpoll->rebuild_needed)
455 rtpoll_rebuild(i->rtpoll);
458 *n_fds = i->n_pollfd;
463 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) {
465 pa_assert(i->priority < PA_RTPOLL_NEVER);
467 i->before_cb = before_cb;
470 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) {
472 pa_assert(i->priority < PA_RTPOLL_NEVER);
474 i->after_cb = after_cb;
477 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)) {
479 pa_assert(i->priority < PA_RTPOLL_NEVER);
481 i->work_cb = work_cb;
484 void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
487 i->userdata = userdata;
490 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
496 static int fdsem_before(pa_rtpoll_item *i) {
498 if (pa_fdsem_before_poll(i->userdata) < 0)
499 return 1; /* 1 means immediate restart of the loop */
504 static void fdsem_after(pa_rtpoll_item *i) {
507 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
508 pa_fdsem_after_poll(i->userdata);
511 pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) {
513 struct pollfd *pollfd;
518 i = pa_rtpoll_item_new(p, prio, 1);
520 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
522 pollfd->fd = pa_fdsem_get(f);
523 pollfd->events = POLLIN;
525 i->before_cb = fdsem_before;
526 i->after_cb = fdsem_after;
532 static int asyncmsgq_read_before(pa_rtpoll_item *i) {
535 if (pa_asyncmsgq_read_before_poll(i->userdata) < 0)
536 return 1; /* 1 means immediate restart of the loop */
541 static void asyncmsgq_read_after(pa_rtpoll_item *i) {
544 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
545 pa_asyncmsgq_read_after_poll(i->userdata);
548 static int asyncmsgq_read_work(pa_rtpoll_item *i) {
549 pa_msgobject *object;
557 if (pa_asyncmsgq_get(i->userdata, &object, &code, &data, &offset, &chunk, 0) == 0) {
560 if (!object && code == PA_MESSAGE_SHUTDOWN) {
561 pa_asyncmsgq_done(i->userdata, 0);
562 pa_rtpoll_quit(i->rtpoll);
566 ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
567 pa_asyncmsgq_done(i->userdata, ret);
574 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
576 struct pollfd *pollfd;
581 i = pa_rtpoll_item_new(p, prio, 1);
583 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
584 pollfd->fd = pa_asyncmsgq_read_fd(q);
585 pollfd->events = POLLIN;
587 i->before_cb = asyncmsgq_read_before;
588 i->after_cb = asyncmsgq_read_after;
589 i->work_cb = asyncmsgq_read_work;
595 static int asyncmsgq_write_before(pa_rtpoll_item *i) {
598 pa_asyncmsgq_write_before_poll(i->userdata);
602 static void asyncmsgq_write_after(pa_rtpoll_item *i) {
605 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
606 pa_asyncmsgq_write_after_poll(i->userdata);
609 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
611 struct pollfd *pollfd;
616 i = pa_rtpoll_item_new(p, prio, 1);
618 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
619 pollfd->fd = pa_asyncmsgq_write_fd(q);
620 pollfd->events = POLLIN;
622 i->before_cb = asyncmsgq_write_before;
623 i->after_cb = asyncmsgq_write_after;
630 void pa_rtpoll_quit(pa_rtpoll *p) {
636 pa_bool_t pa_rtpoll_timer_elapsed(pa_rtpoll *p) {
639 return p->timer_elapsed;