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