• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of PulseAudio.
3 
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 
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.
11 
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.
16 
17   You should have received a copy of the GNU Lesser General Public
18   License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include <sys/types.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29 
30 #include <pulse/xmalloc.h>
31 #include <pulse/timeval.h>
32 
33 #include <pulsecore/poll.h>
34 #include <pulsecore/core-error.h>
35 #include <pulsecore/core-rtclock.h>
36 #include <pulsecore/macro.h>
37 #include <pulsecore/llist.h>
38 #include <pulsecore/flist.h>
39 #include <pulsecore/core-util.h>
40 #include <pulsecore/ratelimit.h>
41 #include <pulse/rtclock.h>
42 
43 #include "log/audio_log.h"
44 
45 #include "rtpoll.h"
46 #include "time.h"
47 
48 /* #define DEBUG_TIMING */
49 
50 struct pa_rtpoll {
51     struct pollfd *pollfd, *pollfd2;
52     unsigned n_pollfd_alloc, n_pollfd_used;
53 
54     struct timeval next_elapse;
55     bool timer_enabled:1;
56 
57     bool scan_for_dead:1;
58     bool running:1;
59     bool rebuild_needed:1;
60     bool quit:1;
61     bool timer_elapsed:1;
62 
63 #ifdef DEBUG_TIMING
64     pa_usec_t timestamp;
65     pa_usec_t slept, awake;
66 #endif
67 
68     PA_LLIST_HEAD(pa_rtpoll_item, items);
69 };
70 
71 struct pa_rtpoll_item {
72     pa_rtpoll *rtpoll;
73     bool dead;
74 
75     pa_rtpoll_priority_t priority;
76 
77     struct pollfd *pollfd;
78     unsigned n_pollfd;
79 
80     int (*work_cb)(pa_rtpoll_item *i);
81     int (*before_cb)(pa_rtpoll_item *i);
82     void (*after_cb)(pa_rtpoll_item *i);
83     void *work_userdata;
84     void *before_userdata;
85     void *after_userdata;
86 
87     PA_LLIST_FIELDS(pa_rtpoll_item);
88 };
89 
90 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
91 
pa_rtpoll_new(void)92 pa_rtpoll *pa_rtpoll_new(void) {
93     pa_rtpoll *p;
94 
95     p = pa_xnew0(pa_rtpoll, 1);
96 
97     p->n_pollfd_alloc = 32;
98     p->pollfd = pa_xnew(struct pollfd, p->n_pollfd_alloc);
99     p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
100 
101 #ifdef DEBUG_TIMING
102     p->timestamp = pa_rtclock_now();
103 #endif
104 
105     return p;
106 }
107 
rtpoll_rebuild(pa_rtpoll * p)108 static void rtpoll_rebuild(pa_rtpoll *p) {
109 
110     struct pollfd *e, *t;
111     pa_rtpoll_item *i;
112     int ra = 0;
113 
114     pa_assert(p);
115 
116     p->rebuild_needed = false;
117 
118     if (p->n_pollfd_used > p->n_pollfd_alloc) {
119         /* Hmm, we have to allocate some more space */
120         p->n_pollfd_alloc = p->n_pollfd_used * 2;
121         p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
122         ra = 1;
123     }
124 
125     e = p->pollfd2;
126 
127     for (i = p->items; i; i = i->next) {
128 
129         if (i->n_pollfd > 0) {
130             size_t l = i->n_pollfd * sizeof(struct pollfd);
131 
132             if (i->pollfd)
133                 memcpy(e, i->pollfd, l);
134             else
135                 memset(e, 0, l);
136 
137             i->pollfd = e;
138         } else
139             i->pollfd = NULL;
140 
141         e += i->n_pollfd;
142     }
143 
144     pa_assert((unsigned) (e - p->pollfd2) == p->n_pollfd_used);
145     t = p->pollfd;
146     p->pollfd = p->pollfd2;
147     p->pollfd2 = t;
148 
149     if (ra)
150         p->pollfd2 = pa_xrealloc(p->pollfd2, p->n_pollfd_alloc * sizeof(struct pollfd));
151 }
152 
rtpoll_item_destroy(pa_rtpoll_item * i)153 static void rtpoll_item_destroy(pa_rtpoll_item *i) {
154     pa_rtpoll *p;
155 
156     pa_assert(i);
157 
158     p = i->rtpoll;
159 
160     PA_LLIST_REMOVE(pa_rtpoll_item, p->items, i);
161 
162     p->n_pollfd_used -= i->n_pollfd;
163 
164     if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
165         pa_xfree(i);
166 
167     p->rebuild_needed = true;
168 }
169 
pa_rtpoll_free(pa_rtpoll * p)170 void pa_rtpoll_free(pa_rtpoll *p) {
171     pa_assert(p);
172 
173     while (p->items)
174         rtpoll_item_destroy(p->items);
175 
176     pa_xfree(p->pollfd);
177     pa_xfree(p->pollfd2);
178 
179     pa_xfree(p);
180 }
181 
reset_revents(pa_rtpoll_item * i)182 static void reset_revents(pa_rtpoll_item *i) {
183     struct pollfd *f;
184     unsigned n;
185 
186     pa_assert(i);
187 
188     if (!(f = pa_rtpoll_item_get_pollfd(i, &n)))
189         return;
190 
191     for (; n > 0; n--)
192         f[n-1].revents = 0;
193 }
194 
reset_all_revents(pa_rtpoll * p)195 static void reset_all_revents(pa_rtpoll *p) {
196     pa_rtpoll_item *i;
197 
198     pa_assert(p);
199 
200     for (i = p->items; i; i = i->next) {
201 
202         if (i->dead)
203             continue;
204 
205         reset_revents(i);
206     }
207 }
208 
pa_rtpoll_run(pa_rtpoll * p)209 int pa_rtpoll_run(pa_rtpoll *p) {
210     pa_rtpoll_item *i;
211     int r = 0;
212     struct timeval timeout;
213 
214     pa_assert(p);
215     pa_assert(!p->running);
216 
217 #ifdef DEBUG_TIMING
218     pa_log("rtpoll_run");
219 #endif
220 
221     p->running = true;
222     p->timer_elapsed = false;
223 
224     /* First, let's do some work */
225     for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
226         int k;
227 
228         if (i->dead)
229             continue;
230 
231         if (!i->work_cb)
232             continue;
233 
234         if (p->quit) {
235 #ifdef DEBUG_TIMING
236             pa_log("rtpoll finish");
237 #endif
238             goto finish;
239         }
240 
241         if ((k = i->work_cb(i)) != 0) {
242             if (k < 0) {
243                 r = k;
244                 AUDIO_ERR_LOG("Error %{public}d in i->work_cb, goto finish", r);
245             }
246 #ifdef DEBUG_TIMING
247             pa_log("rtpoll finish");
248 #endif
249             goto finish;
250         }
251     }
252 
253     /* Now let's prepare for entering the sleep */
254     for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
255         int k = 0;
256 
257         if (i->dead)
258             continue;
259 
260         if (!i->before_cb)
261             continue;
262 
263         if (p->quit || (k = i->before_cb(i)) != 0) {
264 
265             /* Hmm, this one doesn't let us enter the poll, so rewind everything */
266 
267             for (i = i->prev; i; i = i->prev) {
268 
269                 if (i->dead)
270                     continue;
271 
272                 if (!i->after_cb)
273                     continue;
274 
275                 i->after_cb(i);
276             }
277 
278             if (k < 0) {
279                 AUDIO_ERR_LOG("Error %{public}d in i->before_cb, goto finish", r);
280                 r = k;
281             }
282 #ifdef DEBUG_TIMING
283             pa_log("rtpoll finish");
284 #endif
285             goto finish;
286         }
287     }
288 
289     if (p->rebuild_needed)
290         rtpoll_rebuild(p);
291 
292     pa_zero(timeout);
293 
294     /* Calculate timeout */
295     if (!p->quit && p->timer_enabled) {
296         struct timeval now;
297         pa_rtclock_get(&now);
298 
299         if (pa_timeval_cmp(&p->next_elapse, &now) > 0)
300             pa_timeval_add(&timeout, pa_timeval_diff(&p->next_elapse, &now));
301     }
302 
303 #ifdef DEBUG_TIMING
304     {
305         pa_usec_t now = pa_rtclock_now();
306         p->awake = now - p->timestamp;
307         p->timestamp = now;
308         if (!p->quit && p->timer_enabled)
309             pa_log("poll timeout: %d ms ",(int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)));
310         else if (p->quit)
311             pa_log("poll timeout is ZERO");
312         else
313             pa_log("poll timeout is FOREVER");
314     }
315 #endif
316 
317     /* OK, now let's sleep */
318 #ifdef HAVE_PPOLL
319     {
320         struct timespec ts;
321         ts.tv_sec = timeout.tv_sec;
322         ts.tv_nsec = timeout.tv_usec * 1000;
323         r = ppoll(p->pollfd, p->n_pollfd_used, (p->quit || p->timer_enabled) ? &ts : NULL, NULL);
324     }
325 #else
326     r = pa_poll(p->pollfd, p->n_pollfd_used, (p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1);
327 #endif
328 
329     p->timer_elapsed = r == 0;
330 
331 #ifdef DEBUG_TIMING
332     {
333         pa_usec_t now = pa_rtclock_now();
334         p->slept = now - p->timestamp;
335         p->timestamp = now;
336 
337         pa_log("Process time %llu ms; sleep time %llu ms",
338                (unsigned long long) (p->awake / PA_USEC_PER_MSEC),
339                (unsigned long long) (p->slept / PA_USEC_PER_MSEC));
340     }
341 #endif
342 
343     if (r < 0) {
344         if (errno == EAGAIN || errno == EINTR) {
345             r = 0;
346         } else {
347             AUDIO_ERR_LOG("Error %{public}d in ppoll, errno: %{public}s", r, pa_cstrerror(errno));
348             pa_log_error("poll(): %s", pa_cstrerror(errno));
349         }
350 
351         reset_all_revents(p);
352     }
353 
354     /* Let's tell everyone that we left the sleep */
355     for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
356 
357         if (i->dead)
358             continue;
359 
360         if (!i->after_cb)
361             continue;
362 
363         i->after_cb(i);
364     }
365 
366 finish:
367 
368     p->running = false;
369 
370     if (p->scan_for_dead) {
371         pa_rtpoll_item *n;
372 
373         p->scan_for_dead = false;
374 
375         for (i = p->items; i; i = n) {
376             n = i->next;
377 
378             if (i->dead)
379                 rtpoll_item_destroy(i);
380         }
381     }
382 
383     return r < 0 ? r : !p->quit;
384 }
385 
pa_rtpoll_set_timer_absolute(pa_rtpoll * p,pa_usec_t usec)386 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) {
387     pa_assert(p);
388 
389     pa_timeval_store(&p->next_elapse, usec);
390     p->timer_enabled = true;
391 }
392 
pa_rtpoll_set_timer_relative(pa_rtpoll * p,pa_usec_t usec)393 void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
394     pa_assert(p);
395 
396     /* Scheduling a timeout for more than an hour is very very suspicious */
397     pa_assert(usec <= PA_USEC_PER_SEC*60ULL*60ULL);
398 
399     pa_rtclock_get(&p->next_elapse);
400     pa_timeval_add(&p->next_elapse, usec);
401     p->timer_enabled = true;
402 }
403 
pa_rtpoll_set_timer_disabled(pa_rtpoll * p)404 void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
405     pa_assert(p);
406 
407     memset(&p->next_elapse, 0, sizeof(p->next_elapse));
408     p->timer_enabled = false;
409 }
410 
pa_rtpoll_item_new(pa_rtpoll * p,pa_rtpoll_priority_t prio,unsigned n_fds)411 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsigned n_fds) {
412     pa_rtpoll_item *i, *j, *l = NULL;
413 
414     pa_assert(p);
415 
416     if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
417         i = pa_xnew(pa_rtpoll_item, 1);
418 
419     i->rtpoll = p;
420     i->dead = false;
421     i->n_pollfd = n_fds;
422     i->pollfd = NULL;
423     i->priority = prio;
424 
425     i->work_userdata = NULL;
426     i->before_userdata = NULL;
427     i->work_userdata = NULL;
428     i->before_cb = NULL;
429     i->after_cb = NULL;
430     i->work_cb = NULL;
431 
432     for (j = p->items; j; j = j->next) {
433         if (prio <= j->priority)
434             break;
435 
436         l = j;
437     }
438 
439     PA_LLIST_INSERT_AFTER(pa_rtpoll_item, p->items, j ? j->prev : l, i);
440 
441     if (n_fds > 0) {
442         p->rebuild_needed = 1;
443         p->n_pollfd_used += n_fds;
444     }
445 
446     return i;
447 }
448 
pa_rtpoll_item_free(pa_rtpoll_item * i)449 void pa_rtpoll_item_free(pa_rtpoll_item *i) {
450     pa_assert(i);
451 
452     if (i->rtpoll->running) {
453         i->dead = true;
454         i->rtpoll->scan_for_dead = true;
455         return;
456     }
457 
458     rtpoll_item_destroy(i);
459 }
460 
pa_rtpoll_item_get_pollfd(pa_rtpoll_item * i,unsigned * n_fds)461 struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
462     pa_assert(i);
463 
464     if (i->n_pollfd > 0)
465         if (i->rtpoll->rebuild_needed)
466             rtpoll_rebuild(i->rtpoll);
467 
468     if (n_fds)
469         *n_fds = i->n_pollfd;
470 
471     return i->pollfd;
472 }
473 
pa_rtpoll_item_set_before_callback(pa_rtpoll_item * i,int (* before_cb)(pa_rtpoll_item * i),void * userdata)474 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i), void *userdata) {
475     pa_assert(i);
476     pa_assert(i->priority < PA_RTPOLL_NEVER);
477 
478     i->before_cb = before_cb;
479     i->before_userdata = userdata;
480 }
481 
pa_rtpoll_item_set_after_callback(pa_rtpoll_item * i,void (* after_cb)(pa_rtpoll_item * i),void * userdata)482 void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rtpoll_item *i), void *userdata) {
483     pa_assert(i);
484     pa_assert(i->priority < PA_RTPOLL_NEVER);
485 
486     i->after_cb = after_cb;
487     i->after_userdata = userdata;
488 }
489 
pa_rtpoll_item_set_work_callback(pa_rtpoll_item * i,int (* work_cb)(pa_rtpoll_item * i),void * userdata)490 void pa_rtpoll_item_set_work_callback(pa_rtpoll_item *i, int (*work_cb)(pa_rtpoll_item *i), void *userdata) {
491     pa_assert(i);
492     pa_assert(i->priority < PA_RTPOLL_NEVER);
493 
494     i->work_cb = work_cb;
495     i->work_userdata = userdata;
496 }
497 
pa_rtpoll_item_get_work_userdata(pa_rtpoll_item * i)498 void* pa_rtpoll_item_get_work_userdata(pa_rtpoll_item *i) {
499     pa_assert(i);
500 
501     return i->work_userdata;
502 }
503 
fdsem_before(pa_rtpoll_item * i)504 static int fdsem_before(pa_rtpoll_item *i) {
505 
506     if (pa_fdsem_before_poll(i->before_userdata) < 0)
507         return 1; /* 1 means immediate restart of the loop */
508 
509     return 0;
510 }
511 
fdsem_after(pa_rtpoll_item * i)512 static void fdsem_after(pa_rtpoll_item *i) {
513     pa_assert(i);
514 
515     pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
516     pa_fdsem_after_poll(i->after_userdata);
517 }
518 
pa_rtpoll_item_new_fdsem(pa_rtpoll * p,pa_rtpoll_priority_t prio,pa_fdsem * f)519 pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_fdsem *f) {
520     pa_rtpoll_item *i;
521     struct pollfd *pollfd;
522 
523     pa_assert(p);
524     pa_assert(f);
525 
526     i = pa_rtpoll_item_new(p, prio, 1);
527 
528     pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
529 
530     pollfd->fd = pa_fdsem_get(f);
531     pollfd->events = POLLIN;
532 
533     pa_rtpoll_item_set_before_callback(i, fdsem_before, f);
534     pa_rtpoll_item_set_after_callback(i, fdsem_after, f);
535 
536     return i;
537 }
538 
asyncmsgq_read_before(pa_rtpoll_item * i)539 static int asyncmsgq_read_before(pa_rtpoll_item *i) {
540     pa_assert(i);
541 
542     if (pa_asyncmsgq_read_before_poll(i->before_userdata) < 0)
543         return 1; /* 1 means immediate restart of the loop */
544 
545     return 0;
546 }
547 
asyncmsgq_read_after(pa_rtpoll_item * i)548 static void asyncmsgq_read_after(pa_rtpoll_item *i) {
549     pa_assert(i);
550 
551     pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
552     pa_asyncmsgq_read_after_poll(i->after_userdata);
553 }
554 
asyncmsgq_read_work(pa_rtpoll_item * i)555 static int asyncmsgq_read_work(pa_rtpoll_item *i) {
556     pa_msgobject *object;
557     int code;
558     void *data;
559     pa_memchunk chunk;
560     int64_t offset;
561 
562     pa_assert(i);
563 
564     if (pa_asyncmsgq_get(i->work_userdata, &object, &code, &data, &offset, &chunk, 0) == 0) {
565         int ret;
566 
567         if (!object && code == PA_MESSAGE_SHUTDOWN) {
568             pa_asyncmsgq_done(i->work_userdata, 0);
569             /* Requests the loop to exit. Will cause the next iteration of
570              * pa_rtpoll_run() to return 0 */
571             i->rtpoll->quit = true;
572             return 1;
573         }
574 
575         clock_t start = clock();
576         ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
577         clock_t end = clock();
578         double deltatime = (double)(end - start) / CLOCKS_PER_SEC;
579         if (deltatime > 1.0) {
580             AUDIO_ERR_LOG("code %{public}d time out %{public}f s", code, deltatime);
581         }
582         pa_asyncmsgq_done(i->work_userdata, ret);
583         return 1;
584     }
585 
586     return 0;
587 }
588 
pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll * p,pa_rtpoll_priority_t prio,pa_asyncmsgq * q)589 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
590     pa_rtpoll_item *i;
591     struct pollfd *pollfd;
592 
593     pa_assert(p);
594     pa_assert(q);
595 
596     i = pa_rtpoll_item_new(p, prio, 1);
597 
598     pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
599     pollfd->fd = pa_asyncmsgq_read_fd(q);
600     pollfd->events = POLLIN;
601 
602     pa_rtpoll_item_set_before_callback(i, asyncmsgq_read_before, q);
603     pa_rtpoll_item_set_after_callback(i, asyncmsgq_read_after, q);
604     pa_rtpoll_item_set_work_callback(i, asyncmsgq_read_work, q);
605 
606     return i;
607 }
608 
asyncmsgq_write_before(pa_rtpoll_item * i)609 static int asyncmsgq_write_before(pa_rtpoll_item *i) {
610     pa_assert(i);
611 
612     pa_asyncmsgq_write_before_poll(i->before_userdata);
613     return 0;
614 }
615 
asyncmsgq_write_after(pa_rtpoll_item * i)616 static void asyncmsgq_write_after(pa_rtpoll_item *i) {
617     pa_assert(i);
618 
619     pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
620     pa_asyncmsgq_write_after_poll(i->after_userdata);
621 }
622 
pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll * p,pa_rtpoll_priority_t prio,pa_asyncmsgq * q)623 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
624     pa_rtpoll_item *i;
625     struct pollfd *pollfd;
626 
627     pa_assert(p);
628     pa_assert(q);
629 
630     i = pa_rtpoll_item_new(p, prio, 1);
631 
632     pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
633     pollfd->fd = pa_asyncmsgq_write_fd(q);
634     pollfd->events = POLLIN;
635 
636     pa_rtpoll_item_set_before_callback(i, asyncmsgq_write_before, q);
637     pa_rtpoll_item_set_after_callback(i, asyncmsgq_write_after, q);
638 
639     return i;
640 }
641 
pa_rtpoll_timer_elapsed(pa_rtpoll * p)642 bool pa_rtpoll_timer_elapsed(pa_rtpoll *p) {
643     pa_assert(p);
644 
645     return p->timer_elapsed;
646 }
647