]> code.delx.au - pulseaudio/blob - src/pulsecore/rtpoll.c
add 'wait' parameter to pa_rtpoll_run(), if zero pa_rtpoll_runn will only update...
[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/utsname.h>
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <errno.h>
35
36 #include <pulse/xmalloc.h>
37
38 #include <pulsecore/core-error.h>
39 #include <pulsecore/rtclock.h>
40 #include <pulsecore/macro.h>
41 #include <pulsecore/llist.h>
42 #include <pulsecore/rtsig.h>
43 #include <pulsecore/flist.h>
44
45 #include "rtpoll.h"
46
47 struct pa_rtpoll {
48
49 struct pollfd *pollfd, *pollfd2;
50 unsigned n_pollfd_alloc, n_pollfd_used;
51
52 int timer_enabled;
53 struct timespec next_elapse;
54 pa_usec_t period;
55
56 int scan_for_dead;
57 int running, installed, rebuild_needed;
58
59 #ifdef HAVE_PPOLL
60 int rtsig;
61 sigset_t sigset_unblocked;
62 timer_t timer;
63 #ifdef __linux__
64 int dont_use_ppoll;
65 #endif
66 #endif
67
68 PA_LLIST_HEAD(pa_rtpoll_item, items);
69 };
70
71 struct pa_rtpoll_item {
72 pa_rtpoll *rtpoll;
73 int dead;
74
75 struct pollfd *pollfd;
76 unsigned n_pollfd;
77
78 int (*before_cb)(pa_rtpoll_item *i);
79 void (*after_cb)(pa_rtpoll_item *i);
80 void *userdata;
81
82 PA_LLIST_FIELDS(pa_rtpoll_item);
83 };
84
85 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
86
87 static void signal_handler_noop(int s) { }
88
89 pa_rtpoll *pa_rtpoll_new(void) {
90 pa_rtpoll *p;
91
92 p = pa_xnew(pa_rtpoll, 1);
93
94 #ifdef HAVE_PPOLL
95
96 #ifdef __linux__
97 /* ppoll is broken on Linux < 2.6.16 */
98
99 p->dont_use_ppoll = 0;
100
101 {
102 struct utsname u;
103 unsigned major, minor, micro;
104
105 pa_assert_se(uname(&u) == 0);
106
107 if (sscanf(u.release, "%u.%u.%u", &major, &minor, &micro) != 3 ||
108 (major < 2) ||
109 (major == 2 && minor < 6) ||
110 (major == 2 && minor == 6 && micro < 16))
111
112 p->dont_use_ppoll = 1;
113 }
114
115 #endif
116
117 p->rtsig = -1;
118 sigemptyset(&p->sigset_unblocked);
119 p->timer = (timer_t) -1;
120
121 #endif
122
123 p->n_pollfd_alloc = 32;
124 p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc);
125 p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
126 p->n_pollfd_used = 0;
127
128 p->period = 0;
129 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
130 p->timer_enabled = 0;
131
132 p->running = 0;
133 p->installed = 0;
134 p->scan_for_dead = 0;
135 p->rebuild_needed = 0;
136
137 PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items);
138
139 return p;
140 }
141
142 void pa_rtpoll_install(pa_rtpoll *p) {
143 pa_assert(p);
144 pa_assert(!p->installed);
145
146 p->installed = 1;
147
148 #ifdef HAVE_PPOLL
149 if (p->dont_use_ppoll)
150 return;
151
152 if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) {
153 pa_log_warn("Failed to reserve POSIX realtime signal.");
154 return;
155 }
156
157 pa_log_debug("Acquired POSIX realtime signal SIGRTMIN+%i", p->rtsig - SIGRTMIN);
158
159 {
160 sigset_t ss;
161 struct sigaction sa;
162
163 pa_assert_se(sigemptyset(&ss) == 0);
164 pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
165 pa_assert_se(pthread_sigmask(SIG_BLOCK, &ss, &p->sigset_unblocked) == 0);
166 pa_assert_se(sigdelset(&p->sigset_unblocked, p->rtsig) == 0);
167
168 memset(&sa, 0, sizeof(sa));
169 sa.sa_handler = signal_handler_noop;
170 pa_assert_se(sigemptyset(&sa.sa_mask) == 0);
171
172 pa_assert_se(sigaction(p->rtsig, &sa, NULL) == 0);
173
174 /* We never reset the signal handler. Why should we? */
175 }
176
177 #endif
178 }
179
180 static void rtpoll_rebuild(pa_rtpoll *p) {
181
182 struct pollfd *e, *t;
183 pa_rtpoll_item *i;
184 int ra = 0;
185
186 pa_assert(p);
187
188 p->rebuild_needed = 0;
189
190 if (p->n_pollfd_used > p->n_pollfd_alloc) {
191 /* Hmm, we have to allocate some more space */
192 p->n_pollfd_alloc = p->n_pollfd_used * 2;
193 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
194 ra = 1;
195 }
196
197 e = p->pollfd2;
198
199 for (i = p->items; i; i = i->next) {
200
201 if (i->n_pollfd > 0) {
202 size_t l = i->n_pollfd * sizeof(struct pollfd);
203
204 if (i->pollfd)
205 memcpy(e, i->pollfd, l);
206 else
207 memset(e, 0, l);
208
209 i->pollfd = e;
210 } else
211 i->pollfd = NULL;
212
213 e += i->n_pollfd;
214 }
215
216 pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used);
217 t = p->pollfd;
218 p->pollfd = p->pollfd2;
219 p->pollfd2 = t;
220
221 if (ra)
222 p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
223
224 }
225
226 static void rtpoll_item_destroy(pa_rtpoll_item *i) {
227 pa_rtpoll *p;
228
229 pa_assert(i);
230
231 p = i->rtpoll;
232
233 PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
234
235 p->n_pollfd_used -= i->n_pollfd;
236
237 if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
238 pa_xfree(i);
239
240 p->rebuild_needed = 1;
241 }
242
243 void pa_rtpoll_free(pa_rtpoll *p) {
244 pa_assert(p);
245
246 while (p->items)
247 rtpoll_item_destroy(p->items);
248
249 pa_xfree(p->pollfd);
250 pa_xfree(p->pollfd2);
251
252 #ifdef HAVE_PPOLL
253 if (p->timer != (timer_t) -1)
254 timer_delete(p->timer);
255 #endif
256
257 pa_xfree(p);
258 }
259
260 int pa_rtpoll_run(pa_rtpoll *p, int wait) {
261 pa_rtpoll_item *i;
262 int r = 0;
263 int no_events = 0;
264 int saved_errno;
265 struct timespec timeout;
266
267 pa_assert(p);
268 pa_assert(!p->running);
269 pa_assert(p->installed);
270
271 p->running = 1;
272
273 for (i = p->items; i; i = i->next) {
274
275 if (i->dead)
276 continue;
277
278 if (!i->before_cb)
279 continue;
280
281 if (i->before_cb(i) < 0) {
282
283 /* Hmm, this one doesn't let us enter the poll, so rewind everything */
284
285 for (i = i->prev; i; i = i->prev) {
286
287 if (i->dead)
288 continue;
289
290 if (!i->after_cb)
291 continue;
292
293 i->after_cb(i);
294 }
295
296 goto finish;
297 }
298 }
299
300 if (p->rebuild_needed)
301 rtpoll_rebuild(p);
302
303 /* Calculate timeout */
304 if (!wait) {
305 timeout.tv_sec = 0;
306 timeout.tv_nsec = 0;
307 } else if (p->timer_enabled) {
308 struct timespec now;
309 pa_rtclock_get(&now);
310
311 if (pa_timespec_cmp(&p->next_elapse, &now) <= 0)
312 memset(&timeout, 0, sizeof(timeout));
313 else
314 pa_timespec_store(&timeout, pa_timespec_diff(&p->next_elapse, &now));
315 }
316
317 /* OK, now let's sleep */
318 #ifdef HAVE_PPOLL
319
320 #ifdef __linux__
321 if (!p->dont_use_ppoll)
322 #endif
323 r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? &timeout : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
324 #ifdef __linux__
325 else
326 #endif
327
328 #else
329 r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
330 #endif
331
332 saved_errno = errno;
333
334 if (p->timer_enabled) {
335 if (p->period > 0) {
336 struct timespec now;
337 pa_rtclock_get(&now);
338
339 pa_timespec_add(&p->next_elapse, p->period);
340
341 /* Guarantee that the next timeout will happen in the future */
342 if (pa_timespec_cmp(&p->next_elapse, &now) < 0)
343 pa_timespec_add(&p->next_elapse, (pa_timespec_diff(&now, &p->next_elapse) / p->period + 1) * p->period);
344
345 } else
346 p->timer_enabled = 0;
347 }
348
349 if (r == 0 || (r < 0 && (errno == EAGAIN || errno == EINTR))) {
350 r = 0;
351 no_events = 1;
352 }
353
354 for (i = p->items; i; i = i->next) {
355
356 if (i->dead)
357 continue;
358
359 if (!i->after_cb)
360 continue;
361
362 if (no_events) {
363 unsigned j;
364
365 for (j = 0; j < i->n_pollfd; j++)
366 i->pollfd[j].revents = 0;
367 }
368
369 i->after_cb(i);
370 }
371
372 finish:
373
374 p->running = 0;
375
376 if (p->scan_for_dead) {
377 pa_rtpoll_item *n;
378
379 p->scan_for_dead = 0;
380
381 for (i = p->items; i; i = n) {
382 n = i->next;
383
384 if (i->dead)
385 rtpoll_item_destroy(i);
386 }
387 }
388
389 if (r < 0)
390 errno = saved_errno;
391
392 return r;
393 }
394
395 static void update_timer(pa_rtpoll *p) {
396 pa_assert(p);
397
398 #ifdef HAVE_PPOLL
399
400 #ifdef __linux__
401 if (!p->dont_use_ppoll) {
402 #endif
403
404 if (p->timer == (timer_t) -1) {
405 struct sigevent se;
406
407 memset(&se, 0, sizeof(se));
408 se.sigev_notify = SIGEV_SIGNAL;
409 se.sigev_signo = p->rtsig;
410
411 if (timer_create(CLOCK_MONOTONIC, &se, &p->timer) < 0)
412 if (timer_create(CLOCK_REALTIME, &se, &p->timer) < 0) {
413 pa_log_warn("Failed to allocate POSIX timer: %s", pa_cstrerror(errno));
414 p->timer = (timer_t) -1;
415 }
416 }
417
418 if (p->timer != (timer_t) -1) {
419 struct itimerspec its;
420 memset(&its, 0, sizeof(its));
421
422 if (p->timer_enabled) {
423 its.it_value = p->next_elapse;
424
425 /* Make sure that 0,0 is not understood as
426 * "disarming" */
427 if (its.it_value.tv_sec == 0)
428 its.it_value.tv_nsec = 1;
429
430 if (p->period > 0)
431 pa_timespec_store(&its.it_interval, p->period);
432 }
433
434 pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
435 }
436
437 #ifdef __linux__
438 }
439 #endif
440
441 #endif
442 }
443
444 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts) {
445 pa_assert(p);
446 pa_assert(ts);
447
448 p->next_elapse = *ts;
449 p->period = 0;
450 p->timer_enabled = 1;
451
452 update_timer(p);
453 }
454
455 void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec) {
456 pa_assert(p);
457
458 p->period = usec;
459 pa_rtclock_get(&p->next_elapse);
460 pa_timespec_add(&p->next_elapse, usec);
461 p->timer_enabled = 1;
462
463 update_timer(p);
464 }
465
466 void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
467 pa_assert(p);
468
469 p->period = 0;
470 pa_rtclock_get(&p->next_elapse);
471 pa_timespec_add(&p->next_elapse, usec);
472 p->timer_enabled = 1;
473
474 update_timer(p);
475 }
476
477 void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
478 pa_assert(p);
479
480 p->period = 0;
481 memset(&p->next_elapse, 0, sizeof(p->next_elapse));
482 p->timer_enabled = 0;
483
484 update_timer(p);
485 }
486
487 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, unsigned n_fds) {
488 pa_rtpoll_item *i;
489
490 pa_assert(p);
491 pa_assert(n_fds > 0);
492
493 if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
494 i = pa_xnew(pa_rtpoll_item, 1);
495
496 i->rtpoll = p;
497 i->dead = 0;
498 i->n_pollfd = n_fds;
499 i->pollfd = NULL;
500
501 i->userdata = NULL;
502 i->before_cb = NULL;
503 i->after_cb = NULL;
504
505 PA_LLIST_PREPEND(pa_rtpoll_item, p->items, i);
506
507 p->rebuild_needed = 1;
508 p->n_pollfd_used += n_fds;
509
510 return i;
511 }
512
513 void pa_rtpoll_item_free(pa_rtpoll_item *i) {
514 pa_assert(i);
515
516 if (i->rtpoll->running) {
517 i->dead = 1;
518 i->rtpoll->scan_for_dead = 1;
519 return;
520 }
521
522 rtpoll_item_destroy(i);
523 }
524
525 struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
526 pa_assert(i);
527
528 if (i->rtpoll->rebuild_needed)
529 rtpoll_rebuild(i->rtpoll);
530
531 if (n_fds)
532 *n_fds = i->n_pollfd;
533
534 return i->pollfd;
535 }
536
537 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i)) {
538 pa_assert(i);
539
540 i->before_cb = before_cb;
541 }
542
543 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i)) {
544 pa_assert(i);
545
546 i->after_cb = after_cb;
547 }
548
549 void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
550 pa_assert(i);
551
552 i->userdata = userdata;
553 }
554
555 void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
556 pa_assert(i);
557
558 return i->userdata;
559 }
560
561 static int fdsem_before(pa_rtpoll_item *i) {
562 return pa_fdsem_before_poll(i->userdata);
563 }
564
565 static void fdsem_after(pa_rtpoll_item *i) {
566 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
567 pa_fdsem_after_poll(i->userdata);
568 }
569
570 pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_fdsem *f) {
571 pa_rtpoll_item *i;
572 struct pollfd *pollfd;
573
574 pa_assert(p);
575 pa_assert(f);
576
577 i = pa_rtpoll_item_new(p, 1);
578
579 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
580
581 pollfd->fd = pa_fdsem_get(f);
582 pollfd->events = POLLIN;
583
584 i->before_cb = fdsem_before;
585 i->after_cb = fdsem_after;
586 i->userdata = f;
587
588 return i;
589 }
590
591 static int asyncmsgq_before(pa_rtpoll_item *i) {
592 return pa_asyncmsgq_before_poll(i->userdata);
593 }
594
595 static void asyncmsgq_after(pa_rtpoll_item *i) {
596 pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
597 pa_asyncmsgq_after_poll(i->userdata);
598 }
599
600 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_asyncmsgq *q) {
601 pa_rtpoll_item *i;
602 struct pollfd *pollfd;
603
604 pa_assert(p);
605 pa_assert(q);
606
607 i = pa_rtpoll_item_new(p, 1);
608
609 pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
610 pollfd->fd = pa_asyncmsgq_get_fd(q);
611 pollfd->events = POLLIN;
612
613 i->before_cb = asyncmsgq_before;
614 i->after_cb = asyncmsgq_after;
615 i->userdata = q;
616
617 return i;
618 }