default: esd is obsolete, hence don't load it anymore by default
[pulseaudio-mirror.git] / src / pulsecore / rtpoll.c
blobd90c996c1b3302ff10e0e2ce95ced01091fcd690
1 /***
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
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <sys/types.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
35 #include <pulsecore/poll.h>
36 #include <pulsecore/core-error.h>
37 #include <pulsecore/core-rtclock.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/llist.h>
40 #include <pulsecore/flist.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/ratelimit.h>
43 #include <pulse/rtclock.h>
45 #include "rtpoll.h"
47 /* #define DEBUG_TIMING */
49 struct pa_rtpoll {
50 struct pollfd *pollfd, *pollfd2;
51 unsigned n_pollfd_alloc, n_pollfd_used;
53 struct timeval next_elapse;
54 pa_bool_t timer_enabled:1;
56 pa_bool_t scan_for_dead:1;
57 pa_bool_t running:1;
58 pa_bool_t rebuild_needed:1;
59 pa_bool_t quit:1;
60 pa_bool_t timer_elapsed:1;
62 #ifdef DEBUG_TIMING
63 pa_usec_t timestamp;
64 pa_usec_t slept, awake;
65 #endif
67 PA_LLIST_HEAD(pa_rtpoll_item, items);
70 struct pa_rtpoll_item {
71 pa_rtpoll *rtpoll;
72 pa_bool_t dead;
74 pa_rtpoll_priority_t priority;
76 struct pollfd *pollfd;
77 unsigned n_pollfd;
79 int (*work_cb)(pa_rtpoll_item *i);
80 int (*before_cb)(pa_rtpoll_item *i);
81 void (*after_cb)(pa_rtpoll_item *i);
82 void *userdata;
84 PA_LLIST_FIELDS(pa_rtpoll_item);
87 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
89 pa_rtpoll *pa_rtpoll_new(void) {
90 pa_rtpoll *p;
92 p = pa_xnew0(pa_rtpoll, 1);
94 p->n_pollfd_alloc = 32;
95 p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc);
96 p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
98 #ifdef DEBUG_TIMING
99 p->timestamp = pa_rtclock_now();
100 #endif
102 return p;
105 static void rtpoll_rebuild(pa_rtpoll *p) {
107 struct pollfd *e, *t;
108 pa_rtpoll_item *i;
109 int ra = 0;
111 pa_assert(p);
113 p->rebuild_needed = FALSE;
115 if (p->n_pollfd_used > p->n_pollfd_alloc) {
116 /* Hmm, we have to allocate some more space */
117 p->n_pollfd_alloc = p->n_pollfd_used * 2;
118 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
119 ra = 1;
122 e = p->pollfd2;
124 for (i = p->items; i; i = i->next) {
126 if (i->n_pollfd > 0) {
127 size_t l = i->n_pollfd * sizeof(struct pollfd);
129 if (i->pollfd)
130 memcpy(e, i->pollfd, l);
131 else
132 memset(e, 0, l);
134 i->pollfd = e;
135 } else
136 i->pollfd = NULL;
138 e += i->n_pollfd;
141 pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used);
142 t = p->pollfd;
143 p->pollfd = p->pollfd2;
144 p->pollfd2 = t;
146 if (ra)
147 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
150 static void rtpoll_item_destroy(pa_rtpoll_item *i) {
151 pa_rtpoll *p;
153 pa_assert(i);
155 p = i->rtpoll;
157 PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
159 p->n_pollfd_used -= i->n_pollfd;
161 if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
162 pa_xfree(i);
164 p->rebuild_needed = TRUE;
167 void pa_rtpoll_free(pa_rtpoll *p) {
168 pa_assert(p);
170 while (p->items)
171 rtpoll_item_destroy(p->items);
173 pa_xfree(p->pollfd);
174 pa_xfree(p->pollfd2);
176 pa_xfree(p);
179 static void reset_revents(pa_rtpoll_item *i) {
180 struct pollfd *f;
181 unsigned n;
183 pa_assert(i);
185 if (!(f = pa_rtpoll_item_get_pollfd(i, &n)))
186 return;
188 for (; n > 0; n--)
189 f[n-1].revents = 0;
192 static void reset_all_revents(pa_rtpoll *p) {
193 pa_rtpoll_item *i;
195 pa_assert(p);
197 for (i = p->items; i; i = i->next) {
199 if (i->dead)
200 continue;
202 reset_revents(i);
206 int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait_op) {
207 pa_rtpoll_item *i;
208 int r = 0;
209 struct timeval timeout;
211 pa_assert(p);
212 pa_assert(!p->running);
214 #ifdef DEBUG_TIMING
215 pa_log("rtpoll_run");
216 #endif
218 p->running = TRUE;
219 p->timer_elapsed = FALSE;
221 /* First, let's do some work */
222 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
223 int k;
225 if (i->dead)
226 continue;
228 if (!i->work_cb)
229 continue;
231 if (p->quit) {
232 #ifdef DEBUG_TIMING
233 pa_log("rtpoll finish");
234 #endif
235 goto finish;
238 if ((k = i->work_cb(i)) != 0) {
239 if (k < 0)
240 r = k;
241 #ifdef DEBUG_TIMING
242 pa_log("rtpoll finish");
243 #endif
244 goto finish;
248 /* Now let's prepare for entering the sleep */
249 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
250 int k = 0;
252 if (i->dead)
253 continue;
255 if (!i->before_cb)
256 continue;
258 if (p->quit || (k = i->before_cb(i)) != 0) {
260 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
262 for (i = i->prev; i; i = i->prev) {
264 if (i->dead)
265 continue;
267 if (!i->after_cb)
268 continue;
270 i->after_cb(i);
273 if (k < 0)
274 r = k;
275 #ifdef DEBUG_TIMING
276 pa_log("rtpoll finish");
277 #endif
278 goto finish;
282 if (p->rebuild_needed)
283 rtpoll_rebuild(p);
285 pa_zero(timeout);
287 /* Calculate timeout */
288 if (wait_op && !p->quit && p->timer_enabled) {
289 struct timeval now;
290 pa_rtclock_get(&now);
292 if (pa_timeval_cmp(&p->next_elapse, &now) > 0)
293 pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now));
296 #ifdef DEBUG_TIMING
298 pa_usec_t now = pa_rtclock_now();
299 p->awake = now - p->timestamp;
300 p->timestamp = now;
301 if (!wait_op || p->quit || p->timer_enabled)
302 pa_log("poll timeout: %d ms ",(int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)));
303 else
304 pa_log("poll timeout is ZERO");
306 #endif
308 /* OK, now let's sleep */
309 #ifdef HAVE_PPOLL
311 struct timespec ts;
312 ts.tv_sec = timeout.tv_sec;
313 ts.tv_nsec = timeout.tv_usec * 1000;
314 r = ppoll(p->pollfd, p->n_pollfd_used, (!wait_op || p->quit || p->timer_enabled) ? &ts : NULL, NULL);
316 #else
317 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);
318 #endif
320 p->timer_elapsed = r == 0;
322 #ifdef DEBUG_TIMING
324 pa_usec_t now = pa_rtclock_now();
325 p->slept = now - p->timestamp;
326 p->timestamp = now;
328 pa_log("Process time %llu ms; sleep time %llu ms",
329 (unsigned long long) (p->awake / PA_USEC_PER_MSEC),
330 (unsigned long long) (p->slept / PA_USEC_PER_MSEC));
332 #endif
334 if (r < 0) {
335 if (errno == EAGAIN || errno == EINTR)
336 r = 0;
337 else
338 pa_log_error("poll(): %s", pa_cstrerror(errno));
340 reset_all_revents(p);
343 /* Let's tell everyone that we left the sleep */
344 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
346 if (i->dead)
347 continue;
349 if (!i->after_cb)
350 continue;
352 i->after_cb(i);
355 finish:
357 p->running = FALSE;
359 if (p->scan_for_dead) {
360 pa_rtpoll_item *n;
362 p->scan_for_dead = FALSE;
364 for (i = p->items; i; i = n) {
365 n = i->next;
367 if (i->dead)
368 rtpoll_item_destroy(i);
372 return r < 0 ? r : !p->quit;
375 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) {
376 pa_assert(p);
378 pa_timeval_store(&p->next_elapse, usec);
379 p->timer_enabled = TRUE;
382 void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
383 pa_assert(p);
385 /* Scheduling a timeout for more than an hour is very very suspicious */
386 pa_assert(usec <= PA_USEC_PER_SEC*60ULL*60ULL);
388 pa_rtclock_get(&p->next_elapse);
389 pa_timeval_add(&p->next_elapse, usec);
390 p->timer_enabled = TRUE;
393 void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
394 pa_assert(p);
396 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
397 p->timer_enabled = FALSE;
400 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
401 pa_rtpoll_item *i, *j, *l = NULL;
403 pa_assert(p);
405 if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
406 i = pa_xnew(pa_rtpoll_item, 1);
408 i->rtpoll = p;
409 i->dead = FALSE;
410 i->n_pollfd = n_fds;
411 i->pollfd = NULL;
412 i->priority = prio;
414 i->userdata = NULL;
415 i->before_cb = NULL;
416 i->after_cb = NULL;
417 i->work_cb = NULL;
419 for (j = p->items; j; j = j->next) {
420 if (prio <= j->priority)
421 break;
423 l = j;
426 PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i);
428 if (n_fds > 0) {
429 p->rebuild_needed = 1;
430 p->n_pollfd_used += n_fds;
433 return i;
436 void pa_rtpoll_item_free(pa_rtpoll_item *i) {
437 pa_assert(i);
439 if (i->rtpoll->running) {
440 i->dead = TRUE;
441 i->rtpoll->scan_for_dead = TRUE;
442 return;
445 rtpoll_item_destroy(i);
448 struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
449 pa_assert(i);
451 if (i->n_pollfd > 0)
452 if (i->rtpoll->rebuild_needed)
453 rtpoll_rebuild(i->rtpoll);
455 if (n_fds)
456 *n_fds = i->n_pollfd;
458 return i->pollfd;
461 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) {
462 pa_assert(i);
463 pa_assert(i->priority < PA_RTPOLL_NEVER);
465 i->before_cb = before_cb;
468 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) {
469 pa_assert(i);
470 pa_assert(i->priority < PA_RTPOLL_NEVER);
472 i->after_cb = after_cb;
475 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)) {
476 pa_assert(i);
477 pa_assert(i->priority < PA_RTPOLL_NEVER);
479 i->work_cb = work_cb;
482 void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
483 pa_assert(i);
485 i->userdata = userdata;
488 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
489 pa_assert(i);
491 return i->userdata;
494 static int fdsem_before(pa_rtpoll_item *i) {
496 if (pa_fdsem_before_poll(i->userdata) < 0)
497 return 1; /* 1 means immediate restart of the loop */
499 return 0;
502 static void fdsem_after(pa_rtpoll_item *i) {
503 pa_assert(i);
505 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
506 pa_fdsem_after_poll(i->userdata);
509 pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) {
510 pa_rtpoll_item *i;
511 struct pollfd *pollfd;
513 pa_assert(p);
514 pa_assert(f);
516 i = pa_rtpoll_item_new(p, prio, 1);
518 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
520 pollfd->fd = pa_fdsem_get(f);
521 pollfd->events = POLLIN;
523 i->before_cb = fdsem_before;
524 i->after_cb = fdsem_after;
525 i->userdata = f;
527 return i;
530 static int asyncmsgq_read_before(pa_rtpoll_item *i) {
531 pa_assert(i);
533 if (pa_asyncmsgq_read_before_poll(i->userdata) < 0)
534 return 1; /* 1 means immediate restart of the loop */
536 return 0;
539 static void asyncmsgq_read_after(pa_rtpoll_item *i) {
540 pa_assert(i);
542 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
543 pa_asyncmsgq_read_after_poll(i->userdata);
546 static int asyncmsgq_read_work(pa_rtpoll_item *i) {
547 pa_msgobject *object;
548 int code;
549 void *data;
550 pa_memchunk chunk;
551 int64_t offset;
553 pa_assert(i);
555 if (pa_asyncmsgq_get(i->userdata, &object, &code, &data, &offset, &chunk, 0) == 0) {
556 int ret;
558 if (!object && code == PA_MESSAGE_SHUTDOWN) {
559 pa_asyncmsgq_done(i->userdata, 0);
560 pa_rtpoll_quit(i->rtpoll);
561 return 1;
564 ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
565 pa_asyncmsgq_done(i->userdata, ret);
566 return 1;
569 return 0;
572 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
573 pa_rtpoll_item *i;
574 struct pollfd *pollfd;
576 pa_assert(p);
577 pa_assert(q);
579 i = pa_rtpoll_item_new(p, prio, 1);
581 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
582 pollfd->fd = pa_asyncmsgq_read_fd(q);
583 pollfd->events = POLLIN;
585 i->before_cb = asyncmsgq_read_before;
586 i->after_cb = asyncmsgq_read_after;
587 i->work_cb = asyncmsgq_read_work;
588 i->userdata = q;
590 return i;
593 static int asyncmsgq_write_before(pa_rtpoll_item *i) {
594 pa_assert(i);
596 pa_asyncmsgq_write_before_poll(i->userdata);
597 return 0;
600 static void asyncmsgq_write_after(pa_rtpoll_item *i) {
601 pa_assert(i);
603 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
604 pa_asyncmsgq_write_after_poll(i->userdata);
607 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
608 pa_rtpoll_item *i;
609 struct pollfd *pollfd;
611 pa_assert(p);
612 pa_assert(q);
614 i = pa_rtpoll_item_new(p, prio, 1);
616 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
617 pollfd->fd = pa_asyncmsgq_write_fd(q);
618 pollfd->events = POLLIN;
620 i->before_cb = asyncmsgq_write_before;
621 i->after_cb = asyncmsgq_write_after;
622 i->work_cb = NULL;
623 i->userdata = q;
625 return i;
628 void pa_rtpoll_quit(pa_rtpoll *p) {
629 pa_assert(p);
631 p->quit = TRUE;
634 pa_bool_t pa_rtpoll_timer_elapsed(pa_rtpoll *p) {
635 pa_assert(p);
637 return p->timer_elapsed;