]> code.delx.au - pulseaudio/blob - src/pulsecore/rtpoll.c
drop support for periodic timers, cleanup code a bit
[pulseaudio] / src / pulsecore / rtpoll.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as
11 published by the Free Software Foundation; either version 2.1 of the
12 License, or (at your option) any later version.
13
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <signal.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #ifdef __linux__
36 #include <sys/utsname.h>
37 #endif
38
39 #ifdef HAVE_POLL_H
40 #include <poll.h>
41 #else
42 #include <pulsecore/poll.h>
43 #endif
44
45 #include <pulse/xmalloc.h>
46 #include <pulse/timeval.h>
47
48 #include <pulsecore/core-error.h>
49 #include <pulsecore/rtclock.h>
50 #include <pulsecore/macro.h>
51 #include <pulsecore/llist.h>
52 #include <pulsecore/rtsig.h>
53 #include <pulsecore/flist.h>
54 #include <pulsecore/core-util.h>
55
56 #include <pulsecore/winsock.h>
57
58 #include "rtpoll.h"
59
60 struct pa_rtpoll {
61 struct pollfd *pollfd, *pollfd2;
62 unsigned n_pollfd_alloc, n_pollfd_used;
63
64 pa_bool_t timer_enabled;
65 struct timeval next_elapse;
66
67 pa_bool_t scan_for_dead;
68 pa_bool_t running, installed, rebuild_needed, quit;
69
70 #ifdef HAVE_PPOLL
71 int rtsig;
72 sigset_t sigset_unblocked;
73 timer_t timer;
74 #ifdef __linux__
75 pa_bool_t dont_use_ppoll;
76 #endif
77 #endif
78
79 PA_LLIST_HEAD(pa_rtpoll_item, items);
80 };
81
82 struct pa_rtpoll_item {
83 pa_rtpoll *rtpoll;
84 pa_bool_t dead;
85
86 pa_rtpoll_priority_t priority;
87
88 struct pollfd *pollfd;
89 unsigned n_pollfd;
90
91 int (*work_cb)(pa_rtpoll_item *i);
92 int (*before_cb)(pa_rtpoll_item *i);
93 void (*after_cb)(pa_rtpoll_item *i);
94 void *userdata;
95
96 PA_LLIST_FIELDS(pa_rtpoll_item);
97 };
98
99 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
100
101 static void signal_handler_noop(int s) { write(2, "signal\n", 7); }
102
103 pa_rtpoll *pa_rtpoll_new(void) {
104 pa_rtpoll *p;
105
106 p = pa_xnew(pa_rtpoll, 1);
107
108 #ifdef HAVE_PPOLL
109
110 #ifdef __linux__
111 /* ppoll is broken on Linux < 2.6.16 */
112 p->dont_use_ppoll = FALSE;
113
114 {
115 struct utsname u;
116 unsigned major, minor, micro;
117
118 pa_assert_se(uname(&u) == 0);
119
120 if (sscanf(u.release, "%u.%u.%u", &major, &minor, &micro) != 3 ||
121 (major < 2) ||
122 (major == 2 && minor < 6) ||
123 (major == 2 && minor == 6 && micro < 16))
124
125 p->dont_use_ppoll = TRUE;
126 }
127
128 #endif
129
130 p->rtsig = -1;
131 sigemptyset(&p->sigset_unblocked);
132 p->timer = (timer_t) -1;
133
134 #endif
135
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;
140
141 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
142 p->timer_enabled = FALSE;
143
144 p->running = FALSE;
145 p->installed = FALSE;
146 p->scan_for_dead = FALSE;
147 p->rebuild_needed = FALSE;
148 p->quit = FALSE;
149
150 PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items);
151
152 return p;
153 }
154
155 void pa_rtpoll_install(pa_rtpoll *p) {
156 pa_assert(p);
157 pa_assert(!p->installed);
158
159 p->installed = 1;
160
161 #ifdef HAVE_PPOLL
162 # ifdef __linux__
163 if (p->dont_use_ppoll)
164 return;
165 # endif
166
167 if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) {
168 pa_log_warn("Failed to reserve POSIX realtime signal.");
169 return;
170 }
171
172 pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig));
173
174 {
175 sigset_t ss;
176 struct sigaction sa;
177
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);
182
183 memset(&sa, 0, sizeof(sa));
184 sa.sa_handler = signal_handler_noop;
185 pa_assert_se(sigemptyset(&sa.sa_mask) == 0);
186
187 pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0);
188
189 /* We never reset the signal handler. Why should we? */
190 }
191
192 #endif
193 }
194
195 static void rtpoll_rebuild(pa_rtpoll *p) {
196
197 struct pollfd *e, *t;
198 pa_rtpoll_item *i;
199 int ra = 0;
200
201 pa_assert(p);
202
203 p->rebuild_needed = FALSE;
204
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));
209 ra = 1;
210 }
211
212 e = p->pollfd2;
213
214 for (i = p->items; i; i = i->next) {
215
216 if (i->n_pollfd > 0) {
217 size_t l = i->n_pollfd * sizeof(struct pollfd);
218
219 if (i->pollfd)
220 memcpy(e, i->pollfd, l);
221 else
222 memset(e, 0, l);
223
224 i->pollfd = e;
225 } else
226 i->pollfd = NULL;
227
228 e += i->n_pollfd;
229 }
230
231 pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used);
232 t = p->pollfd;
233 p->pollfd = p->pollfd2;
234 p->pollfd2 = t;
235
236 if (ra)
237 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
238
239 }
240
241 static void rtpoll_item_destroy(pa_rtpoll_item *i) {
242 pa_rtpoll *p;
243
244 pa_assert(i);
245
246 p = i->rtpoll;
247
248 PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
249
250 p->n_pollfd_used -= i->n_pollfd;
251
252 if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
253 pa_xfree(i);
254
255 p->rebuild_needed = TRUE;
256 }
257
258 void pa_rtpoll_free(pa_rtpoll *p) {
259 pa_assert(p);
260
261 while (p->items)
262 rtpoll_item_destroy(p->items);
263
264 pa_xfree(p->pollfd);
265 pa_xfree(p->pollfd2);
266
267 #ifdef HAVE_PPOLL
268 if (p->timer != (timer_t) -1)
269 timer_delete(p->timer);
270 #endif
271
272 pa_xfree(p);
273 }
274
275 static void reset_revents(pa_rtpoll_item *i) {
276 struct pollfd *f;
277 unsigned n;
278
279 pa_assert(i);
280
281 if (!(f = pa_rtpoll_item_get_pollfd(i, &n)))
282 return;
283
284 for (; n > 0; n--)
285 f[n-1].revents = 0;
286 }
287
288 static void reset_all_revents(pa_rtpoll *p) {
289 pa_rtpoll_item *i;
290
291 pa_assert(p);
292
293 for (i = p->items; i; i = i->next) {
294
295 if (i->dead)
296 continue;
297
298 reset_revents(i);
299 }
300 }
301
302 int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
303 pa_rtpoll_item *i;
304 int r = 0;
305 struct timeval timeout;
306
307 pa_assert(p);
308 pa_assert(!p->running);
309 pa_assert(p->installed);
310
311 p->running = TRUE;
312
313 /* First, let's do some work */
314 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
315 int k;
316
317 if (i->dead)
318 continue;
319
320 if (!i->work_cb)
321 continue;
322
323 if (p->quit)
324 goto finish;
325
326 if ((k = i->work_cb(i)) != 0) {
327 if (k < 0)
328 r = k;
329
330 goto finish;
331 }
332 }
333
334 /* Now let's prepare for entering the sleep */
335 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
336 int k = 0;
337
338 if (i->dead)
339 continue;
340
341 if (!i->before_cb)
342 continue;
343
344 if (p->quit || (k = i->before_cb(i)) != 0) {
345
346 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
347
348 for (i = i->prev; i; i = i->prev) {
349
350 if (i->dead)
351 continue;
352
353 if (!i->after_cb)
354 continue;
355
356 i->after_cb(i);
357 }
358
359 if (k < 0)
360 r = k;
361
362 goto finish;
363 }
364 }
365
366 if (p->rebuild_needed)
367 rtpoll_rebuild(p);
368
369 memset(&timeout, 0, sizeof(timeout));
370
371 /* Calculate timeout */
372 if (wait && !p->quit && p->timer_enabled) {
373 struct timeval now;
374 pa_rtclock_get(&now);
375
376 if (pa_timeval_cmp(&p->next_elapse, &now) > 0)
377 pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now));
378 }
379
380 /* OK, now let's sleep */
381 #ifdef HAVE_PPOLL
382
383 #ifdef __linux__
384 if (!p->dont_use_ppoll)
385 #endif
386 {
387 struct timespec ts;
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);
391 }
392 #ifdef __linux__
393 else
394 #endif
395
396 #endif
397 r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (timeout.tv_sec*1000) + (timeout.tv_usec / 1000) : -1);
398
399 if (r < 0) {
400 if (errno == EAGAIN || errno == EINTR)
401 r = 0;
402 else
403 pa_log_error("poll(): %s", pa_cstrerror(errno));
404
405 reset_all_revents(p);
406 }
407
408 /* Let's tell everyone that we left the sleep */
409 for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
410
411 if (i->dead)
412 continue;
413
414 if (!i->after_cb)
415 continue;
416
417 i->after_cb(i);
418 }
419
420 finish:
421
422 p->running = FALSE;
423
424 if (p->scan_for_dead) {
425 pa_rtpoll_item *n;
426
427 p->scan_for_dead = FALSE;
428
429 for (i = p->items; i; i = n) {
430 n = i->next;
431
432 if (i->dead)
433 rtpoll_item_destroy(i);
434 }
435 }
436
437 return r < 0 ? r : !p->quit;
438 }
439
440 static void update_timer(pa_rtpoll *p) {
441 pa_assert(p);
442
443 #ifdef HAVE_PPOLL
444
445 #ifdef __linux__
446 if (!p->dont_use_ppoll) {
447 #endif
448
449 if (p->timer == (timer_t) -1) {
450 struct sigevent se;
451
452 memset(&se, 0, sizeof(se));
453 se.sigev_notify = SIGEV_SIGNAL;
454 se.sigev_signo = p->rtsig;
455
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;
460 }
461 }
462
463 if (p->timer != (timer_t) -1) {
464 struct itimerspec its;
465 memset(&its, 0, sizeof(its));
466
467 if (p->timer_enabled) {
468 its.it_value.tv_sec = p->next_elapse.tv_sec;
469 its.it_value.tv_nsec = p->next_elapse.tv_usec*1000;
470
471 /* Make sure that 0,0 is not understood as
472 * "disarming" */
473 if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
474 its.it_value.tv_nsec = 1;
475 }
476
477 pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
478 }
479
480 #ifdef __linux__
481 }
482 #endif
483
484 #endif
485 }
486
487 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts) {
488 pa_assert(p);
489 pa_assert(ts);
490
491 p->next_elapse = *ts;
492 p->timer_enabled = TRUE;
493
494 update_timer(p);
495 }
496
497 void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
498 pa_assert(p);
499
500 pa_rtclock_get(&p->next_elapse);
501 pa_timeval_add(&p->next_elapse, usec);
502 p->timer_enabled = TRUE;
503
504 update_timer(p);
505 }
506
507 void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
508 pa_assert(p);
509
510 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
511 p->timer_enabled = FALSE;
512
513 update_timer(p);
514 }
515
516 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
517 pa_rtpoll_item *i, *j, *l = NULL;
518
519 pa_assert(p);
520
521 if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
522 i = pa_xnew(pa_rtpoll_item, 1);
523
524 i->rtpoll = p;
525 i->dead = FALSE;
526 i->n_pollfd = n_fds;
527 i->pollfd = NULL;
528 i->priority = prio;
529
530 i->userdata = NULL;
531 i->before_cb = NULL;
532 i->after_cb = NULL;
533 i->work_cb = NULL;
534
535 for (j = p->items; j; j = j->next) {
536 if (prio <= j->priority)
537 break;
538
539 l = j;
540 }
541
542 PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i);
543
544 if (n_fds > 0) {
545 p->rebuild_needed = 1;
546 p->n_pollfd_used += n_fds;
547 }
548
549 return i;
550 }
551
552 void pa_rtpoll_item_free(pa_rtpoll_item *i) {
553 pa_assert(i);
554
555 if (i->rtpoll->running) {
556 i->dead = TRUE;
557 i->rtpoll->scan_for_dead = TRUE;
558 return;
559 }
560
561 rtpoll_item_destroy(i);
562 }
563
564 struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
565 pa_assert(i);
566
567 if (i->n_pollfd > 0)
568 if (i->rtpoll->rebuild_needed)
569 rtpoll_rebuild(i->rtpoll);
570
571 if (n_fds)
572 *n_fds = i->n_pollfd;
573
574 return i->pollfd;
575 }
576
577 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) {
578 pa_assert(i);
579 pa_assert(i->priority < PA_RTPOLL_NEVER);
580
581 i->before_cb = before_cb;
582 }
583
584 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) {
585 pa_assert(i);
586 pa_assert(i->priority < PA_RTPOLL_NEVER);
587
588 i->after_cb = after_cb;
589 }
590
591 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i)) {
592 pa_assert(i);
593 pa_assert(i->priority < PA_RTPOLL_NEVER);
594
595 i->work_cb = work_cb;
596 }
597
598 void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
599 pa_assert(i);
600
601 i->userdata = userdata;
602 }
603
604 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
605 pa_assert(i);
606
607 return i->userdata;
608 }
609
610 static int fdsem_before(pa_rtpoll_item *i) {
611
612 if (pa_fdsem_before_poll(i->userdata) < 0)
613 return 1; /* 1 means immediate restart of the loop */
614
615 return 0;
616 }
617
618 static void fdsem_after(pa_rtpoll_item *i) {
619 pa_assert(i);
620
621 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
622 pa_fdsem_after_poll(i->userdata);
623 }
624
625 pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) {
626 pa_rtpoll_item *i;
627 struct pollfd *pollfd;
628
629 pa_assert(p);
630 pa_assert(f);
631
632 i = pa_rtpoll_item_new(p, prio, 1);
633
634 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
635
636 pollfd->fd = pa_fdsem_get(f);
637 pollfd->events = POLLIN;
638
639 i->before_cb = fdsem_before;
640 i->after_cb = fdsem_after;
641 i->userdata = f;
642
643 return i;
644 }
645
646 static int asyncmsgq_before(pa_rtpoll_item *i) {
647 pa_assert(i);
648
649 if (pa_asyncmsgq_before_poll(i->userdata) < 0)
650 return 1; /* 1 means immediate restart of the loop */
651
652 return 0;
653 }
654
655 static void asyncmsgq_after(pa_rtpoll_item *i) {
656 pa_assert(i);
657
658 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
659 pa_asyncmsgq_after_poll(i->userdata);
660 }
661
662 static int asyncmsgq_work(pa_rtpoll_item *i) {
663 pa_msgobject *object;
664 int code;
665 void *data;
666 pa_memchunk chunk;
667 int64_t offset;
668
669 pa_assert(i);
670
671 if (pa_asyncmsgq_get(i->userdata, &object, &code, &data, &offset, &chunk, 0) == 0) {
672 int ret;
673
674 if (!object && code == PA_MESSAGE_SHUTDOWN) {
675 pa_asyncmsgq_done(i->userdata, 0);
676 pa_rtpoll_quit(i->rtpoll);
677 return 1;
678 }
679
680 ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
681 pa_asyncmsgq_done(i->userdata, ret);
682 return 1;
683 }
684
685 return 0;
686 }
687
688 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
689 pa_rtpoll_item *i;
690 struct pollfd *pollfd;
691
692 pa_assert(p);
693 pa_assert(q);
694
695 i = pa_rtpoll_item_new(p, prio, 1);
696
697 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
698 pollfd->fd = pa_asyncmsgq_get_fd(q);
699 pollfd->events = POLLIN;
700
701 i->before_cb = asyncmsgq_before;
702 i->after_cb = asyncmsgq_after;
703 i->work_cb = asyncmsgq_work;
704 i->userdata = q;
705
706 return i;
707 }
708
709 void pa_rtpoll_quit(pa_rtpoll *p) {
710 pa_assert(p);
711
712 p->quit = TRUE;
713 }